internal static List<HidDevice> Open(int vendorId, IEnumerable<int> productIds)
{
// Obtain system-defined GUID for HIDClass devices.
Guid hidClassGuid;
Hid.HidD_GetHidGuid(out hidClassGuid);
var deviceList = new List<HidDevice>();
// Obtain handle to an opaque device-information-set
// describing device interface supported by all HID
// collections currently installed in the system.
IntPtr deviceInfoSet = SetupApi.SetupDiGetClassDevs(
ref hidClassGuid,
null,
IntPtr.Zero,
SetupApi.DiGetFlags.DeviceInterface | SetupApi.DiGetFlags.Present);
if (deviceInfoSet == Kernel32.InvalidHandleValue) {
throw new Win32Exception();
}
// Retrieve all available interface information.
SetupApi.SpDeviceInterfaceData did = new SetupApi.SpDeviceInterfaceData();
did.Size = Marshal.SizeOf(did);
int i = 0;
while (SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref hidClassGuid, i++, ref did)) {
// Obtain DevicePath
var didd = new SetupApi.SpDeviceInterfaceDetailData();
// On x64 only 8 appears to work while on x86 it must be sizeof (int) + sizeof (TCHAR)
didd.Size = IntPtr.Size == 8 ? 8 : IntPtr.Size + Marshal.SystemDefaultCharSize;
if (SetupApi.SetupDiGetDeviceInterfaceDetail(
deviceInfoSet,
ref did,
ref didd,
Marshal.SizeOf(didd),
IntPtr.Zero,
IntPtr.Zero)) {
// Write access causes failure if not running elevated.
IntPtr hDevice = Kernel32.CreateFile(
didd.DevicePath,
(uint)FileAccess.Read, // we just need read
FileShare.ReadWrite, // and we don't want to restrict others from write
IntPtr.Zero,
FileMode.Open,
FileAttributes.Device,
IntPtr.Zero);
if (hDevice != Kernel32.InvalidHandleValue) {
Hid.DeviceAttributes attributes;
if (Hid.HidD_GetAttributes(hDevice, out attributes)) {
if (vendorId == attributes.VendorId && productIds.Contains(attributes.ProductId)) {
deviceList.Add(
new HidDevice(
hDevice,
didd.DevicePath,
vendorId,
attributes.ProductId,
attributes.VersionNumber));
continue;
}
}
// Close the wrong device handle
Kernel32.CloseHandle(hDevice);
}
}
}
// Free the device-information-set.
SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
return deviceList;
}