using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace HidLibrary { public class HidDevices { private class DeviceInfo { public string Path { get; set; } public string Description { get; set; } } private static Guid _hidClassGuid = Guid.Empty; private static Guid HidClassGuid { get { if (_hidClassGuid.Equals(Guid.Empty)) { NativeMethods.HidD_GetHidGuid(ref _hidClassGuid); } return _hidClassGuid; } } public static bool IsConnected(string devicePath) { return EnumerateDevices().Any((DeviceInfo x) => x.Path == devicePath); } public static HidDevice GetDevice(string devicePath) { return Enumerate(devicePath).FirstOrDefault(); } public static IEnumerable Enumerate() { return from x in EnumerateDevices() select new HidDevice(x.Path, x.Description); } public static IEnumerable Enumerate(string devicePath) { return from x in EnumerateDevices() where x.Path == devicePath select new HidDevice(x.Path, x.Description); } public static IEnumerable EnumerateFastRead(int vendorId, params int[] productIds) { return from x in EnumerateFastReadDevices() select new HidFastReadDevice(x.Path, x.Description) into x where x.Attributes.VendorId == vendorId && productIds.Contains(x.Attributes.ProductId) select x; } public static IEnumerable Enumerate(int vendorId, params int[] productIds) { return from x in EnumerateDevices() select new HidDevice(x.Path, x.Description) into x where x.Attributes.VendorId == vendorId && productIds.Contains(x.Attributes.ProductId) select x; } public static IEnumerable Enumerate(int vendorId) { return from x in EnumerateDevices() select new HidDevice(x.Path, x.Description) into x where x.Attributes.VendorId == vendorId select x; } private static IEnumerable EnumerateDevices() { List list = new List(); Guid classGuid = HidClassGuid; IntPtr deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref classGuid, null, 0, 18); if (deviceInfoSet.ToInt64() != -1) { NativeMethods.SP_DEVINFO_DATA deviceInfoData = CreateDeviceInfoData(); int num = 0; while (NativeMethods.SetupDiEnumDeviceInfo(deviceInfoSet, num, ref deviceInfoData)) { num++; NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData = default(NativeMethods.SP_DEVICE_INTERFACE_DATA); deviceInterfaceData.cbSize = Marshal.SizeOf((object)deviceInterfaceData); int num2 = 0; while (NativeMethods.SetupDiEnumDeviceInterfaces(deviceInfoSet, ref deviceInfoData, ref classGuid, num2, ref deviceInterfaceData)) { int num3 = num2; num2 = num3 + 1; string devicePath = GetDevicePath(deviceInfoSet, deviceInterfaceData); string description = GetBusReportedDeviceDescription(deviceInfoSet, ref deviceInfoData) ?? GetDeviceDescription(deviceInfoSet, ref deviceInfoData); list.Add(new DeviceInfo { Path = devicePath, Description = description }); } } NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet); } return list; } private static IEnumerable EnumerateFastReadDevices() { List list = new List(); Guid classGuid = HidClassGuid; IntPtr deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref classGuid, null, 0, 18); if (deviceInfoSet.ToInt64() != -1) { NativeMethods.SP_DEVINFO_DATA deviceInfoData = CreateDeviceInfoData(); int num = 0; while (NativeMethods.SetupDiEnumDeviceInfo(deviceInfoSet, num, ref deviceInfoData)) { num++; NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData = default(NativeMethods.SP_DEVICE_INTERFACE_DATA); deviceInterfaceData.cbSize = Marshal.SizeOf((object)deviceInterfaceData); int num2 = 0; while (NativeMethods.SetupDiEnumDeviceInterfaces(deviceInfoSet, ref deviceInfoData, ref classGuid, num2, ref deviceInterfaceData)) { int num3 = num2; num2 = num3 + 1; string devicePath = GetDevicePath(deviceInfoSet, deviceInterfaceData); string description = GetBusReportedDeviceDescription(deviceInfoSet, ref deviceInfoData) ?? GetDeviceDescription(deviceInfoSet, ref deviceInfoData); list.Add(new DeviceInfo { Path = devicePath, Description = description }); } } NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet); } return list; } private static NativeMethods.SP_DEVINFO_DATA CreateDeviceInfoData() { NativeMethods.SP_DEVINFO_DATA sP_DEVINFO_DATA = default(NativeMethods.SP_DEVINFO_DATA); sP_DEVINFO_DATA.cbSize = Marshal.SizeOf((object)sP_DEVINFO_DATA); sP_DEVINFO_DATA.DevInst = 0; sP_DEVINFO_DATA.ClassGuid = Guid.Empty; sP_DEVINFO_DATA.Reserved = IntPtr.Zero; return sP_DEVINFO_DATA; } private static string GetDevicePath(IntPtr deviceInfoSet, NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData) { int requiredSize = 0; NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA sP_DEVICE_INTERFACE_DETAIL_DATA = default(NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA); sP_DEVICE_INTERFACE_DETAIL_DATA.Size = ((IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8); NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = sP_DEVICE_INTERFACE_DETAIL_DATA; NativeMethods.SetupDiGetDeviceInterfaceDetailBuffer(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref requiredSize, IntPtr.Zero); return NativeMethods.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, ref deviceInterfaceDetailData, requiredSize, ref requiredSize, IntPtr.Zero) ? deviceInterfaceDetailData.DevicePath : null; } private static string GetDeviceDescription(IntPtr deviceInfoSet, ref NativeMethods.SP_DEVINFO_DATA devinfoData) { byte[] array = new byte[1024]; int requiredSize = 0; int propertyRegDataType = 0; NativeMethods.SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref devinfoData, 0, ref propertyRegDataType, array, array.Length, ref requiredSize); return array.ToUTF8String(); } private static string GetBusReportedDeviceDescription(IntPtr deviceInfoSet, ref NativeMethods.SP_DEVINFO_DATA devinfoData) { byte[] array = new byte[1024]; if (Environment.OSVersion.Version.Major > 5) { ulong propertyDataType = 0uL; int requiredSize = 0; if (NativeMethods.SetupDiGetDeviceProperty(deviceInfoSet, ref devinfoData, ref NativeMethods.DEVPKEY_Device_BusReportedDeviceDesc, ref propertyDataType, array, array.Length, ref requiredSize, 0u)) { return array.ToUTF16String(); } } return null; } } }