public static InterfaceDetails[] getConnectedDevices() { InterfaceDetails[] devices = new InterfaceDetails[0]; //Create structs to hold interface information SP_DEVINFO_DATA devInfo = new SP_DEVINFO_DATA(); SP_DEVICE_INTERFACE_DATA devIface = new SP_DEVICE_INTERFACE_DATA(); devInfo.cbSize = (uint)Marshal.SizeOf(devInfo); devIface.cbSize = (uint)(Marshal.SizeOf(devIface)); Guid G = new Guid(); HID.HidD_GetHidGuid(ref G); //Get the guid of the HID device class IntPtr i = SetupAPI.SetupDiGetClassDevs(ref G, IntPtr.Zero, IntPtr.Zero, SetupAPI.DIGCF_DEVICEINTERFACE | SetupAPI.DIGCF_PRESENT); //Loop through all available entries in the device list, until false SP_DEVICE_INTERFACE_DETAIL_DATA didd = new SP_DEVICE_INTERFACE_DETAIL_DATA(); if (IntPtr.Size == 8) // for 64 bit operating systems { didd.cbSize = 8; } else { didd.cbSize = 4 + Marshal.SystemDefaultCharSize; // for 32 bit systems } int j = -1; bool b = true; SafeFileHandle tempHandle; while (b) { ++j; b = SetupAPI.SetupDiEnumDeviceInterfaces(i, IntPtr.Zero, ref G, (uint)j, ref devIface); if (b == false) { break; } uint requiredSize = 0; SetupAPI.SetupDiGetDeviceInterfaceDetail(i, ref devIface, ref didd, 256, out requiredSize, ref devInfo); string devicePath = didd.DevicePath; //create file handles using CT_CreateFile tempHandle = Kernel32.CreateFile(devicePath, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero); //get capabilites - use getPreParsedData, and getCaps //store the reportlengths IntPtr ptrToPreParsedData = new IntPtr(); bool ppdSucsess = HID.HidD_GetPreparsedData(tempHandle, ref ptrToPreParsedData); if (ppdSucsess == false) { continue; } HIDP_CAPS capabilities = new HIDP_CAPS(); HID.HidP_GetCaps(ptrToPreParsedData, ref capabilities); HIDD_ATTRIBUTES attributes = new HIDD_ATTRIBUTES(); HID.HidD_GetAttributes(tempHandle, ref attributes); string productName = ""; string SN = ""; string manfString = ""; IntPtr buffer = Marshal.AllocHGlobal(126);//max alloc for string; if (HID.HidD_GetProductString(tempHandle, buffer, 126)) { productName = Marshal.PtrToStringAuto(buffer); } if (HID.HidD_GetSerialNumberString(tempHandle, buffer, 126)) { SN = Marshal.PtrToStringAuto(buffer); } if (HID.HidD_GetManufacturerString(tempHandle, buffer, 126)) { manfString = Marshal.PtrToStringAuto(buffer); } Marshal.FreeHGlobal(buffer); //Call freePreParsedData to release some stuff HID.HidD_FreePreparsedData(ref ptrToPreParsedData); //If connection was sucsessful, record the values in a global struct InterfaceDetails productInfo = new InterfaceDetails(); productInfo.devicePath = devicePath; productInfo.manufacturer = manfString; productInfo.product = productName; productInfo.PID = (ushort)attributes.ProductID; productInfo.VID = (ushort)attributes.VendorID; productInfo.versionNumber = (ushort)attributes.VersionNumber; productInfo.IN_reportByteLength = (int)capabilities.InputReportByteLength; productInfo.OUT_reportByteLength = (int)capabilities.OutputReportByteLength; productInfo.serialNumber = SN; //Check that serial number is actually a number int newSize = devices.Length + 1; Array.Resize(ref devices, newSize); devices[newSize - 1] = productInfo; } SetupAPI.SetupDiDestroyDeviceInfoList(i); return(devices); }
/// <summary> /// Modifies the device registry entry to use the specified name /// in the windows device manager. /// REQUIRES ADMINISTRATOR PRIVILEGE /// </summary> /// <param name="name">The name to display in the windows device manager</param> public void SetFriendlyName(string name) { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) { throw new Exception("This function requires administrator privileges"); } var deviceInterfaceData = new SetupAPI.SP_DEVICE_INTERFACE_DATA(); var deviceInfoData = new SetupAPI.SP_DEVINFO_DATA(); UInt32 interfaceIndex = 0; // Populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. IntPtr pDeviceInfoTable = SetupAPI.SetupDiGetClassDevs( ref InterfaceClassGuid, null, IntPtr.Zero, SetupAPI.DIGCF_PRESENT | SetupAPI.DIGCF_DEVICEINTERFACE ); try { while (true) { deviceInterfaceData.cbSize = (UInt32)Marshal.SizeOf(typeof(SetupAPI.SP_DEVICE_INTERFACE_DATA)); if (!SetupAPI.SetupDiEnumDeviceInterfaces(pDeviceInfoTable, IntPtr.Zero, ref InterfaceClassGuid, interfaceIndex, ref deviceInterfaceData)) { int error = Marshal.GetLastWin32Error(); if (error == SetupAPI.ERROR_NO_MORE_ITEMS) { return; } else { throw new Win32Exception(error); } } //Initialize an appropriate SP_DEVINFO_DATA structure. We need this structure for SetupDiGetDeviceRegistryProperty(). deviceInfoData.cbSize = (UInt32)Marshal.SizeOf(typeof(SetupAPI.SP_DEVINFO_DATA)); if (!SetupAPI.SetupDiEnumDeviceInfo(pDeviceInfoTable, interfaceIndex, ref deviceInfoData)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } String deviceIdFromRegistry = SetupAPI.SetupDiGetDeviceRegistryProperty(pDeviceInfoTable, ref deviceInfoData, SetupAPI.SPDRP_HARDWAREID); if (deviceIdFromRegistry != null) { deviceIdFromRegistry = deviceIdFromRegistry.ToLowerInvariant();; String deviceIdToFind = this.DeviceId.ToLowerInvariant(); if (deviceIdFromRegistry.Contains(deviceIdToFind)) { // Set the friendly name that's displayed in the device manager SetupAPI.SetupDiSetDeviceRegistryProperty(pDeviceInfoTable, ref deviceInfoData, SetupAPI.SPDRP_FRIENDLYNAME, name); this.DeviceDescription = SetupAPI.SetupDiGetDeviceRegistryProperty(pDeviceInfoTable, ref deviceInfoData, SetupAPI.SPDRP_FRIENDLYNAME); if (this.DeviceDescription == null) { this.DeviceDescription = SetupAPI.SetupDiGetDeviceRegistryProperty(pDeviceInfoTable, ref deviceInfoData, SetupAPI.SPDRP_DEVICEDESC); } } } interfaceIndex++; if (interfaceIndex == 10000000) //Surely there aren't more than 10 million interfaces attached to a single PC. { return; } } } finally { //Clean up the old structure we no longer need. SetupAPI.SetupDiDestroyDeviceInfoList(pDeviceInfoTable); } }
/// <summary> /// Scans the computer for any USB devices matching th specified VID/PID DeviceID. /// Throws an exception if none are found /// </summary> public void Connect() { var deviceInterfaceDetailData = new SetupAPI.SP_DEVICE_INTERFACE_DETAIL_DATA(); var deviceInterfaceData = new SetupAPI.SP_DEVICE_INTERFACE_DATA(); var deviceInfoData = new SetupAPI.SP_DEVINFO_DATA(); UInt32 interfaceIndex = 0; UInt32 dwRegType; UInt32 dwRegSize; UInt32 structureSize = 0; bool matchFound = false; //First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID. IntPtr pDeviceInfoTable = SetupAPI.SetupDiGetClassDevs( ref InterfaceClassGuid, null, IntPtr.Zero, SetupAPI.DIGCF_PRESENT | SetupAPI.DIGCF_DEVICEINTERFACE ); try { //Now look through the list we just populated. We are trying to see if any of them match our device. while (true) { deviceInterfaceData.cbSize = (UInt32)Marshal.SizeOf(typeof(SetupAPI.SP_DEVICE_INTERFACE_DATA)); if (!SetupAPI.SetupDiEnumDeviceInterfaces(pDeviceInfoTable, IntPtr.Zero, ref InterfaceClassGuid, interfaceIndex, ref deviceInterfaceData)) { int error = Marshal.GetLastWin32Error(); if (error == SetupAPI.ERROR_NO_MORE_ITEMS) { throw new HidDeviceException(String.Format("No HID devices found matching {0}", this.DeviceId)); } else { throw new Win32Exception(error); } } //Now retrieve the hardware ID from the registry. The hardware ID contains the VID and PID, which we will then //check to see if it is the correct device or not. //Initialize an appropriate SP_DEVINFO_DATA structure. We need this structure for SetupDiGetDeviceRegistryProperty(). deviceInfoData.cbSize = (UInt32)Marshal.SizeOf(typeof(SetupAPI.SP_DEVINFO_DATA)); if (!SetupAPI.SetupDiEnumDeviceInfo(pDeviceInfoTable, interfaceIndex, ref deviceInfoData)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } //Retrieve the hardware IDs for the current device we are looking at. PropertyValueBuffer gets filled with a //REG_MULTI_SZ (array of null terminated strings). To find a device, we only care about the very first string in the //buffer, which will be the "device ID". The device ID is a string which contains the VID and PID, in the example //format "Vid_04d8&Pid_003f". String deviceIdFromRegistry = SetupAPI.SetupDiGetDeviceRegistryProperty(pDeviceInfoTable, ref deviceInfoData, SetupAPI.SPDRP_HARDWAREID); if (deviceIdFromRegistry == null) { throw new Win32Exception(Marshal.GetLastWin32Error()); } //Now check if the first string in the hardware ID matches the device ID of my USB device. //Convert both strings to lower case. This makes the code more robust/portable across OS Versions deviceIdFromRegistry = deviceIdFromRegistry.ToLowerInvariant(); var deviceIdToFind = this.DeviceId.ToLowerInvariant(); //Now check if the hardware ID we are looking at contains the correct VID/PID matchFound = deviceIdFromRegistry.Contains(deviceIdToFind); if (matchFound == true) { //Device must have been found. (Goal: Open read and write handles) In order to do this, we will need the actual device path first. //We can get the path by calling SetupDiGetDeviceInterfaceDetail(), however, we have to call this function twice: The first //time to get the size of the required structure/buffer to hold the detailed interface data, then a second time to actually //get the structure (after we have allocated enough memory for the structure.) deviceInterfaceDetailData = new SetupAPI.SP_DEVICE_INTERFACE_DETAIL_DATA(); if (IntPtr.Size == 8) // for 64 bit operating systems { deviceInterfaceDetailData.cbSize = 8; } else { deviceInterfaceDetailData.cbSize = (UInt32)(4 + Marshal.SystemDefaultCharSize); // for 32 bit systems } UInt32 bufferSize = 1000; if (!SetupAPI.SetupDiGetDeviceInterfaceDetail(pDeviceInfoTable, ref deviceInterfaceData, ref deviceInterfaceDetailData, bufferSize, out structureSize, ref deviceInfoData)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // Finally set the devicePath this.DevicePath = deviceInterfaceDetailData.DevicePath; // Also get the device description this.DeviceDescription = SetupAPI.SetupDiGetDeviceRegistryProperty(pDeviceInfoTable, ref deviceInfoData, SetupAPI.SPDRP_FRIENDLYNAME); if (this.DeviceDescription == null) { this.DeviceDescription = SetupAPI.SetupDiGetDeviceRegistryProperty(pDeviceInfoTable, ref deviceInfoData, SetupAPI.SPDRP_DEVICEDESC); } return; } interfaceIndex++; if (interfaceIndex == 10000000) //Surely there aren't more than 10 million interfaces attached to a single PC. { //If execution gets to here, it is probably safe to assume some kind of unanticipated problem occurred. //In this case, bug out, to avoid infinite blocking while(true) loop. throw new Exception("Unknown Error in HidDevice.Open()"); } //Keep looping until we either find a device with matching VID and PID, or until we run out of items, or some error is encountered. } } finally { //Clean up the old structure we no longer need. SetupAPI.SetupDiDestroyDeviceInfoList(pDeviceInfoTable); } }
public static InterfaceDetails[] getConnectedDevices() { InterfaceDetails[] devices = new InterfaceDetails[0]; //Create structs to hold interface information SP_DEVINFO_DATA devInfo = new SP_DEVINFO_DATA(); devInfo.cbSize = (uint)Marshal.SizeOf(devInfo); SP_DEVICE_INTERFACE_DATA devIface = new SP_DEVICE_INTERFACE_DATA(); devIface.cbSize = (uint)(Marshal.SizeOf(devIface)); Guid G = Guid.Empty; HID.HidD_GetHidGuid(ref G); //Get the guid of the HID device class IntPtr deviceInfo = SetupAPI.SetupDiGetClassDevs(ref G, IntPtr.Zero, IntPtr.Zero, SetupAPI.DIGCF_DEVICEINTERFACE | SetupAPI.DIGCF_PRESENT); //Loop through all available entries in the device list, until false int j = 0; while (true) { if (!SetupAPI.SetupDiEnumDeviceInterfaces(deviceInfo, IntPtr.Zero, ref G, (uint)j, ref devIface)) { break; } uint requiredSize = 0; IntPtr detailMemory = Marshal.AllocHGlobal((int)requiredSize); SP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = (SP_DEVICE_INTERFACE_DETAIL_DATA)Marshal.PtrToStructure(detailMemory, Typeof <SP_DEVICE_INTERFACE_DETAIL_DATA>()); functionClassDeviceData.cbSize = Marshal.SizeOf(functionClassDeviceData); if (!SetupAPI.SetupDiGetDeviceInterfaceDetail(deviceInfo, ref devIface, ref functionClassDeviceData, requiredSize, out requiredSize, ref devInfo)) { Marshal.FreeHGlobal(detailMemory); break; } string devicePath = functionClassDeviceData.DevicePath; Marshal.FreeHGlobal(detailMemory); //create file handles using CT_CreateFile uint desiredAccess = Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE; uint shareMode = Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE; SafeFileHandle tempHandle = Kernel32.CreateFile(devicePath, desiredAccess, shareMode, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero); //get capabilites - use getPreParsedData, and getCaps //store the reportlengths IntPtr ptrToPreParsedData = new IntPtr(); bool ppdSucsess = HID.HidD_GetPreparsedData(tempHandle, ref ptrToPreParsedData); if (!ppdSucsess) { continue; } HIDP_CAPS capability = new HIDP_CAPS(); HID.HidP_GetCaps(ptrToPreParsedData, ref capability); HIDD_ATTRIBUTES attributes = new HIDD_ATTRIBUTES(); HID.HidD_GetAttributes(tempHandle, ref attributes); string productName = EMPTY; string SN = EMPTY; string manfString = EMPTY; const int bufferLen = 128; IntPtr buffer = Marshal.AllocHGlobal(bufferLen); if (HID.HidD_GetProductString(tempHandle, buffer, bufferLen)) { productName = Marshal.PtrToStringAuto(buffer); } if (HID.HidD_GetSerialNumberString(tempHandle, buffer, bufferLen)) { SN = Marshal.PtrToStringAuto(buffer); } if (HID.HidD_GetManufacturerString(tempHandle, buffer, bufferLen)) { manfString = Marshal.PtrToStringAuto(buffer); } Marshal.FreeHGlobal(buffer); //Call freePreParsedData to release some stuff HID.HidD_FreePreparsedData(ref ptrToPreParsedData); //If connection was sucsessful, record the values in a global struct InterfaceDetails productInfo = new InterfaceDetails(); productInfo.devicePath = devicePath; productInfo.manufacturer = manfString; productInfo.product = productName; productInfo.PID = (ushort)attributes.ProductID; productInfo.VID = (ushort)attributes.VendorID; productInfo.versionNumber = (ushort)attributes.VersionNumber; productInfo.IN_reportByteLength = capability.InputReportByteLength; productInfo.OUT_reportByteLength = capability.OutputReportByteLength; productInfo.serialNumber = SN; //Check that serial number is actually a number int newSize = devices.Length + 1; Array.Resize(ref devices, newSize); devices[newSize - 1] = productInfo; ++j; } SetupAPI.SetupDiDestroyDeviceInfoList(deviceInfo); return(devices); }