Currently I'm having a problem with getting input reports from a HID device. What's happening is that I'm getting the device path of the device, but CreateFileW doesn't recognize it as a valid device path.
Here's my platform invokes and main function if anyone has any clue.
C#
using System;``using System.Runtime.InteropServices;
class Program
{
private const int FILE_FLAG_OVERLAPPED = 0x40000000;
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, ref OVERLAPPED lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFileW(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("hid.dll")]
private static extern void HidD_GetHidGuid(out Guid HidGuid);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, string Enumerator, IntPtr hwndParent, uint Flags);
[DllImport("setupapi.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref Guid InterfaceClassGuid, uint MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, uint DeviceInterfaceDetailDataSize, out uint RequiredSize, IntPtr DeviceInfoData);
[DllImport("setupapi.dll")]
private static extern void SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVICE_INTERFACE_DATA
{
public uint cbSize;
public Guid InterfaceClassGuid;
public uint Flags;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public uint cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DevicePath;
}
[StructLayout(LayoutKind.Sequential)]
public struct OVERLAPPED
{
public IntPtr Internal;
public IntPtr InternalHigh;
public uint Offset;
public uint OffsetHigh;
public IntPtr hEvent;
}
private const uint DIGCF_PRESENT = 0x00000002;
private const uint DIGCF_DEVICEINTERFACE = 0x00000010;
static void Main()
{
Guid hidGuid;
HidD_GetHidGuid(out hidGuid);
IntPtr deviceInfoSet = SetupDiGetClassDevs(ref hidGuid, null, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (deviceInfoSet == IntPtr.Zero)
{
Console.WriteLine("Failed to get device info set");
return;
}
SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA
{
cbSize = (uint)Marshal.SizeOf<SP_DEVICE_INTERFACE_DATA>()
};
uint index = 0;
while (SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref hidGuid, index++, ref deviceInterfaceData))
{
uint requiredSize = 0;
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, out requiredSize, IntPtr.Zero);
if (requiredSize == 0)
{
continue;
}
IntPtr detailDataBuffer = Marshal.AllocHGlobal((int)requiredSize);
try
{
Marshal.WriteInt32(detailDataBuffer, IntPtr.Size == 8 ? 8 : 5);
if (SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailDataBuffer, requiredSize, out requiredSize, IntPtr.Zero))
{
IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + Marshal.OffsetOf<SP_DEVICE_INTERFACE_DETAIL_DATA>("DevicePath").ToInt64());
string devicePath = Marshal.PtrToStringAuto(pDevicePathName);
string searchString1 = "pid&2007";
string searchString2 = "pid&2006";
string VIDstring = "vid&0002057e";
if (devicePath != null && (devicePath.Contains(searchString1) || devicePath.Contains(searchString2)) && devicePath.Contains(VIDstring))
{
Console.WriteLine("Device found!");
Console.WriteLine("Device Path: " + devicePath);
IntPtr ptr = CreateFileW(devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, IntPtr.Zero);
if (ptr == INVALID_HANDLE_VALUE)
{
int errorCode = Marshal.GetLastWin32Error();
Console.WriteLine($"CreateFileW failed with error code: {errorCode}");
Console.WriteLine("Error Message: " + new System.ComponentModel.Win32Exception(errorCode).Message);
return;
}
byte[] buffer = new byte[64];
uint bytesRead;
OVERLAPPED overlapped = new OVERLAPPED();
if (ReadFile(ptr, buffer, (uint)buffer.Length, out bytesRead, ref overlapped))
{
Console.WriteLine("Read successful");
// Example processing: Check if the A button is pressed
bool aButtonPressed = (buffer[1] & 0x04) != 0;
Console.WriteLine("A button pressed: " + (aButtonPressed ? "Yes" : "No"));
}
else
{
Console.WriteLine("Failed to read from device");
}
CloseHandle(ptr);
}
}
}
finally
{
Marshal.FreeHGlobal(detailDataBuffer);
}
}
SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
}