Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get the raw descriptor data from a USB HID device in Windows?

Tags:

c++

c#

windows

usb

hid

How do you get the raw descriptor data from a HID device in Windows?

Background:

I need to get the Manufacturer, Product Name, and Serial Number from a HID device in Windows. I'm using hid.dll to access the devices using the functions seen here. My question is very similar to this one. I am able to get the manufacturer string and product string from SOME HID devices, but most fail to return this data with HidD_GetManufacturerString returning false. However, I KNOW these devices do have the string information in their descriptors because I am able to see it using USBTreeView.

The interesting thing is, even for the devices that do return manufacturer and product names, the values I'm getting through hid.dll are very different from the values I see using the above tool which gets the raw data from the USB device.

For example, an Xbox 360 controller:

Via USB Tree View:
Device Description       : Xbox 360 Controller for Windows
Language 0x0409          : "©Microsoft Corporation"
iProduct                 : 0x02
Language 0x0409          : "Controller"
iSerialNumber            : 0x03
Language 0x0409          : "0843806"

Via hid.dll using HidD_GetManufacturerString, HidD_GetProductString, and HidD_GetSerialNumberString:
Description              : HID-compliant game controller
Product                  : Controller (XBOX 360 Controller for Windows)
Manufacturer             : FAILS
Serial Number            : FAILS

WinUSB is unable to open these devices at all to retrieve this data as they do not use the winusb.sys driver.

1) I don't understand why the values returned by the HidD functions do not match the values in the USB descriptor. 2) I can't find any way to access the raw USB descriptor data for a HID device because I cannot access them with WinUSB.


Edit 1:

Okay, so I've learned a bit more about HID. It seems the data I'm getting through hid.dll is driver-specified data, not data coming from the USB device. HID can apply to devices on transports other than USB as well. So that's fine. Ultimately, what I really want to know is how can I get the USB device when I have the HID device and what API do I use for that. Besides WinUSB which doesn't work, the only thing I can find are kernel-level functions IOCTL. I don't know if that's suitable for a normal, non admin application.

like image 703
Guavaman Avatar asked Oct 04 '14 10:10

Guavaman


People also ask

How do I get USB descriptor?

To view the hardware ID of a particular device, open Device Manager and view device properties. In the Details tab, the Hardware Ids property value indicates the hardware ID ("USB\XXX") that is generated by Windows. The bcdUSB field indicates the version of the USB specification to which the device conforms.

What is HID report descriptor?

To define an HID device, you need to supply an HID report descriptor. When you plug in an HID device, it sends its report descriptor(s) to the host computer. The report descriptor is binary data that specifies the device type and the details of the reports that the device sends and receives.

What is raw HID?

If you want to create a custom application, Raw HID is simple way to send 64 byte packets between your code on the Teensy and your application on the PC or Mac. HID works automatically with built-in drivers in Linux, Mac OS X and Windows, so users will not need to load any drivers.

What is the HID mean in reference to USB devices?

In computing, the USB human interface device class (USB HID class) is a part of the USB specification for computer peripherals: it specifies a device class (a type of computer hardware) for human interface devices such as keyboards, mice, game controllers and alphanumeric display devices.


1 Answers

I finally found the solution. The main problem was just associating a HID device to its parent USB device. This is the basic process:

Assuming you already have the HID device and the SP_DEVINFO_DATA for it:

  1. Enumerate all USB devices as seen here.
  2. Find all children of the USB devices with CM_GetChild and CM_GetSibling.
  3. Compare the known HID device's instance handle (SP_DEVINFO_DATA->DevInst) with each child device's instance handle that was returned by the CM functions to determine which USB device is the parent.
  4. From there, you can get any USB info you want including the descriptor.
like image 76
Guavaman Avatar answered Nov 14 '22 23:11

Guavaman