How do I obtain USB_DEVICE_DESCRIPTOR given a device path

こ雲淡風輕ζ 提交于 2019-12-03 16:14:07

Your best bet would be to extract the info from the device path and use the SetupDi functions to get the other bits and pieces. As far as I know, the device path always follows the same convention. i.e.:

"\\?\usb#vid_0000&pid_1111#SERIAL#{GUID}" where 0000 is the VID and 1111 is the PID as hex strings. SERIAL is either the serial provided by the hardware or the OS-assigned serial value.

I personally found an instance where I absolutely wanted to get the device descriptor in order to pull the serial that way. In some instances, the OS was not recognizing the serial number provided by my hardware. I fixed that on the hardware side, but I still wanted to accommodate old hardware on the PC side. Below is my approach. There may be something better, but this is the best that I have come up with so far. You may still consider it to be "hack-ish" though.

  1. Call SetupDiGetClassDevs() to setup your desired DeviceInfoSet
  2. Obtain your device info data using SetupDiEnumDeviceInfo()
  3. Call SetupDiGetDeviceRegistryProperty() with SPDRP_LOCATION_INFORMATION to get the location information. This string should look like "Port_#0001.Hub_#0001". Parse this string to get the port number where your device is located. (I assume that this value is base 10, but I haven't verified this yet)
  4. Call CM_Get_Parent() to get the device node pointer value of the parent (hub)
  5. Call SetupDiGetClassDevs() with the GUID of {0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8}} to get all of the hubs on your system. That GUID should be defined as GUID_DEVINTERFACE_USB_HUB in usbiodef.h.
  6. Iterate through the list of devices using SetupDiEnumDeviceInfo(). Stop once DevInst equals the value obtained in step 4.
  7. Call SetupDiGetDeviceInterfaceDetail() on the index found in step 6.
  8. Call CreateFile() on the DevicePath obtained in step 7.
  9. Call DeviceIoControl() using the file created in step 8 and the port number obtained in step 3 as your connection index.

-EDIT-

As Ben pointed out in the comments, you can skip steps 5, 6, and 7 by using CM_Get_Device_ID on the parent's dev node obtained in step 4. Change the slashes (\) in this string to pounds (#). Prepend "\\?\" and then append "#{f18a0e88-c30c-11d0-8815-00a0c906bed8}". Use that as your device path in step 8. This avoids iterating through all of the hub devices on your system :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!