/// <summary> /// Enumerates all valid USB devics of the specified Vid. /// </summary> /// <returns>list of all devices found, ordered by USB port connection</returns> public static IList <PIEDevice> EnumeratePIE(int vid) { // FileIOApiDeclarations.SECURITY_ATTRIBUTES securityAttrUnusedE = new FileIOApiDeclarations.SECURITY_ATTRIBUTES(); List <PIEDevice> devices = new List <PIEDevice>(); // Get all device paths Guid guid = Guid.Empty; HidApiDeclarations.HidD_GetHidGuid(ref guid); IntPtr deviceInfoSet = DeviceManagementApiDeclarations.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, DeviceManagementApiDeclarations.DIGCF_PRESENT | DeviceManagementApiDeclarations.DIGCF_DEVICEINTERFACE); DeviceManagementApiDeclarations.SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new DeviceManagementApiDeclarations.SP_DEVICE_INTERFACE_DATA(); deviceInterfaceData.Size = Marshal.SizeOf(deviceInterfaceData); //28; List <string> paths = new List <string>(); for (int i = 0; 0 != DeviceManagementApiDeclarations.SetupDiEnumDeviceInterfaces(deviceInfoSet, 0, ref guid, i, ref deviceInterfaceData); i++) { int buffSize = 0; DeviceManagementApiDeclarations.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref buffSize, IntPtr.Zero); // Use IntPtr to simulate detail data structure IntPtr detailBuffer = Marshal.AllocHGlobal(buffSize); // sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) depends on the process bitness, // it's 6 with an X86 process (byte packing + 1 char, auto -> unicode -> 4 + 2*1) // and 8 with an X64 process (8 bytes packing anyway). Marshal.WriteInt32(detailBuffer, Environment.Is64BitProcess ? 8 : 6); if (DeviceManagementApiDeclarations.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailBuffer, buffSize, ref buffSize, IntPtr.Zero)) { // convert buffer (starting past the cbsize variable) to string path paths.Add(Marshal.PtrToStringAuto(detailBuffer + 4)); } } _ = DeviceManagementApiDeclarations.SetupDiDestroyDeviceInfoList(deviceInfoSet); foreach (string devicePath in paths) { IntPtr fileH = FileIOApiDeclarations.CreateFile(devicePath, FileIOApiDeclarations.GENERIC_WRITE, FileIOApiDeclarations.FILE_SHARE_READ | FileIOApiDeclarations.FILE_SHARE_WRITE, IntPtr.Zero, FileIOApiDeclarations.OPEN_EXISTING, 0, 0); SafeFileHandle fileHandle = new SafeFileHandle(fileH, true); if (fileHandle.IsInvalid) { // Bad handle, try next path continue; } try { HidApiDeclarations.HIDD_ATTRIBUTES hidAttributes = new HidApiDeclarations.HIDD_ATTRIBUTES(); hidAttributes.Size = Marshal.SizeOf(hidAttributes); if (0 != HidApiDeclarations.HidD_GetAttributes(fileHandle, ref hidAttributes) && hidAttributes.VendorID == vid) { // Good attributes and right vid, try to get caps IntPtr pPerparsedData = new IntPtr(); if (HidApiDeclarations.HidD_GetPreparsedData(fileHandle, ref pPerparsedData)) { HidApiDeclarations.HIDP_CAPS hidCaps = new HidApiDeclarations.HIDP_CAPS(); if (0 != HidApiDeclarations.HidP_GetCaps(pPerparsedData, ref hidCaps)) { // Got Capabilities, add device to list char[] Mstring = new char[128]; StringBuilder manufacturer = new StringBuilder(); StringBuilder productName = new StringBuilder(); _ = HidApiDeclarations.HidD_GetManufacturerString(fileHandle, manufacturer, 128); _ = HidApiDeclarations.HidD_GetProductString(fileHandle, productName, 128); devices.Add(new PIEDevice(devicePath, hidAttributes.VendorID, hidAttributes.ProductID, hidAttributes.VersionNumber, hidCaps.Usage, hidCaps.UsagePage, hidCaps.InputReportByteLength, hidCaps.OutputReportByteLength, manufacturer.ToString(), productName.ToString())); } } } } catch (Exception) { continue; } finally { fileHandle.Close(); } } return(devices); }
//----------------------------------------------------------------------------- /// <summary> /// Sets connection to the enumerated device. /// If inputReportSize greater than zero it generates a read handle. /// If outputReportSize greater than zero it generates a write handle. /// </summary> /// <returns></returns> public int SetupInterface() { int retin = 0; int retout = 0; if (null != cts) { cts.Cancel(); cts.Dispose(); } cts = new CancellationTokenSource(); if (connected) { return(203); } if (ReadLength > 0) { IntPtr readFileH = FileIOApiDeclarations.CreateFile(Path, FileIOApiDeclarations.GENERIC_READ, FileIOApiDeclarations.FILE_SHARE_READ | FileIOApiDeclarations.FILE_SHARE_WRITE, IntPtr.Zero, FileIOApiDeclarations.OPEN_EXISTING, FileIOApiDeclarations.FILE_FLAG_OVERLAPPED, 0); readFileHandle = new SafeFileHandle(readFileH, true); if (readFileHandle.IsInvalid) { readRing = null; retin = 207; } else { readRing = new RingBuffer(128, ReadLength); _ = ReadFromHid(); } } if (WriteLength > 0) { IntPtr writeFileH = FileIOApiDeclarations.CreateFile(Path, FileIOApiDeclarations.GENERIC_WRITE, FileIOApiDeclarations.FILE_SHARE_READ | FileIOApiDeclarations.FILE_SHARE_WRITE, IntPtr.Zero, FileIOApiDeclarations.OPEN_EXISTING, FileIOApiDeclarations.FILE_FLAG_OVERLAPPED, 0); writeFileHandle = new SafeFileHandle(writeFileH, true); if (writeFileHandle.IsInvalid) { writeRing = null; retout = 208; } else { writeRing = new RingBuffer(128, WriteLength); _ = WriteToHid(); } } if ((retin == 0) && (retout == 0)) { connected = true; return(0); } else if ((retin == 207) && (retout == 208)) { return(209); } else { return(retin + retout); } }