예제 #1
0
        public string GetVendorString()
        {
            var buffer = new byte[260];

            Hid.HidD_GetManufacturerString(this._handle, ref buffer[0], Convert.ToUInt32(buffer.Length));
            return(buffer.GetString());
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
                }
            }
        }