public string GetVendorString() { var buffer = new byte[260]; Hid.HidD_GetManufacturerString(this._handle, ref buffer[0], Convert.ToUInt32(buffer.Length)); return(buffer.GetString()); }
private static UsbDescriptorStrings GetDescriptionStrings(SafeFileHandle deviceHadle) { const int stringSizelimit = 64; //TODO: While this should cover almost all cases it is hardcoded which is bad UsbDescriptorStrings descriptorStrings; var manufacturer = new StringBuilder(stringSizelimit); var product = new StringBuilder(stringSizelimit); var serial = new StringBuilder(stringSizelimit); try { Hid.HidD_GetManufacturerString(deviceHadle, manufacturer, stringSizelimit); Hid.HidD_GetProductString(deviceHadle, product, stringSizelimit); Hid.HidD_GetSerialNumberString(deviceHadle, serial, stringSizelimit); } finally { descriptorStrings = new UsbDescriptorStrings(manufacturer.ToString(), product.ToString(), serial.ToString()); } return(descriptorStrings); }
private void _DeviceSearchThread() { _Logger.Info("Started"); while (_Running) { var loopStart = DateTime.Now; #region Device enumeration var devices = new List <UsbDevice>(); var detailDataBuffer = IntPtr.Zero; var deviceInfoSet = IntPtr.Zero; try { int listIndex = 0; int lastError = 0; var deviceInterfaceData = new SpDeviceInterfaceData(); var systemHidGuid = new Guid(); Hid.HidD_GetHidGuid(ref systemHidGuid); deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref systemHidGuid, IntPtr.Zero, IntPtr.Zero, Constants.DigcfPresent | Constants.DigcfDeviceinterface); deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData); while (SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex++, ref deviceInterfaceData) || (lastError = Marshal.GetLastWin32Error()) != Constants.ERROR_NO_MORE_ITEMS) { if (lastError == 0) { int bufferSize = 0; SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero); detailDataBuffer = Marshal.AllocHGlobal(bufferSize); Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8); if (SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero)) { var pDevicePathName = IntPtr.Add(detailDataBuffer, 4); var devicePath = Marshal.PtrToStringAuto(pDevicePathName); // Get device capabilities (to determine usage page) using (var hidHandle = Kernel32.CreateFile(devicePath, 0, Constants.FileShareRead | Constants.FileShareWrite, IntPtr.Zero, Constants.OpenExisting, 0, 0)) { var preparsedData = IntPtr.Zero; try { preparsedData = new IntPtr(); Hid.HidD_GetPreparsedData(hidHandle, ref preparsedData); var caps = new HidpCaps(); Hid.HidP_GetCaps(preparsedData, ref caps); var attrs = new HiddAttributes(); Hid.HidD_GetAttributes(hidHandle, ref attrs); // Only add the device if it has our VID, PID, and RAW usage page var deviceClass = FindDeviceClass(attrs.VendorID, attrs.ProductID, attrs.VersionNumber, caps.UsagePage); if (deviceClass != null) { var manufacturer = new StringBuilder(STRING_SIZE_LIMIT); var product = new StringBuilder(STRING_SIZE_LIMIT); var serial = new StringBuilder(STRING_SIZE_LIMIT); Hid.HidD_GetManufacturerString(hidHandle, manufacturer, STRING_SIZE_LIMIT); Hid.HidD_GetProductString(hidHandle, product, STRING_SIZE_LIMIT); Hid.HidD_GetSerialNumberString(hidHandle, serial, STRING_SIZE_LIMIT); var device = new UsbDevice(new DeviceInstance(deviceClass, devicePath, manufacturer.ToString(), product.ToString(), serial.ToString()), caps); devices.Add(device); } } finally { // Free up the memory before finishing if (preparsedData != IntPtr.Zero) { Hid.HidD_FreePreparsedData(preparsedData); } } } } } } } catch (Exception ex) { _Logger.Error(ex, "Error scanning for devices:"); devices.Clear(); } finally { // Clean up the unmanaged memory allocations and free resources held by the windows API if (detailDataBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(detailDataBuffer); } if (deviceInfoSet != IntPtr.Zero) { SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet); } } var addedDevices = devices.Except(_CurrentDevices); var removedDevices = _CurrentDevices.Except(devices); _CurrentDevices = devices; if (DeviceRemoved != null) { foreach (var dev in removedDevices) { _Logger.Info("Device removed: {0}", dev); DeviceRemoved(this, new DeviceEventArgs(dev.Instance)); } } if (DeviceAdded != null) { foreach (var dev in addedDevices) { _Logger.Info("Device added: {0}", dev); DeviceAdded(this, new DeviceEventArgs(dev.Instance)); } } #endregion #region Active device I/O // If we receive a request to change the active device while we are processing messages, we need to stop immediately because they are about to become invalid { byte[] msg; while (true) { byte[] response = null; // Block until SetActiveDevice finishes lock (_LockObject) { // If we created a new message queue in the call to SetActiveDevice, this will return false and we'll break out of the loop if (_ActiveDevice == null || !_MessageQueue.TryDequeue(out msg)) { break; } try { response = SendDeviceRequest(_ActiveDevice, msg); } catch (Exception ex) { _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult); } } if (response != null) { ProcessResponse(msg, response); } else { _Logger.Error("Failed to read data from device. req = {0}", FormatByteArray(msg)); } } } // Get LED config (it may have changed) { byte[] response = null; byte[] msg = CreateSimpleMessage(hid_pkt_req.HID_PKT_REQ_CONFIG_LED_GET); // Block until SetActiveDevice finishes lock (_LockObject) { if (_ActiveDevice != null) { try { response = SendDeviceRequest(_ActiveDevice, msg); } catch (Exception ex) { _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult); } } } if (response != null) { ProcessResponse(msg, response); } } // Get LED status { byte[] response = null; byte[] msg = new byte[2]; msg[0] = (byte)hid_pkt_req.HID_PKT_REQ_LED_STATUS; msg[1] = 0; var ledStatuses = new List <LedColor>(); do { lock (_LockObject) { if (_ActiveDevice != null) { try { response = SendDeviceRequest(_ActiveDevice, msg); } catch (Exception ex) { _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult); } } } if (response != null) { // Parse response for (byte i = 0; i < response[1] && i < 10; i++) { var led = new LedColor( response[i * 3 + 2], response[i * 3 + 3], response[i * 3 + 4] ); ledStatuses.Add(led); } msg[1] += 10; } } while (response != null && response[0] == (byte)hid_pkt_res.HID_PKT_RES_MORE); LedStatusReceived?.Invoke(this, new LedStatusReceivedEventArgs(ledStatuses)); } #endregion // Wait until the entire loop execution is at least 100ms var loopTime = DateTime.Now - loopStart; if (loopTime < LOOP_DELAY) { var waitTime = LOOP_DELAY - loopTime; Thread.Sleep(waitTime); } } }