如何在给定设备路径的情况下获取USB_DEVICE_DESCRIPTOR

时间:2015-01-18 05:33:05

标签: c# windows winapi usb setupapi

我已经能够使用SetupAPI枚举USB设备,我已经从WDK查看了usbview应用程序,但我仍然无法弄清楚如何获取USB_DEVICE_DESCRIPTOR

  • 我宁愿避免使用WMI。
  • DeviceIoControl是示例应用程序usbview使用的内容,但这只有在您在集线器上枚举设备时才有效。我想如果我可以在给定设备路径(或Id)的情况下到达父集线器(和端口),这种方法可能会起作用,但我还无法确定如何执行此操作。
  • 我有各种各样的设备,我想要获取描述符。其中一些是HID,有些可能是WinUsb.sys设备。如果它们是WinUsb设备,我可以使用WinUsb_GetDescriptor,但这不适用于HID(我不知道如何从Id或Path ...接口类中区分它们我猜?)。
  • 我可以使用SetupDiGetDeviceRegistryProperty但是在可用属性列表中,我可以看到制造商字符串,但不能看到供应商ID。
  • 我可能会从设备路径或设备ID中解析此值,但这似乎有点...... hack-ish。这只是人们做的事情吗?如果我想要制造商等其他领域,它仍然会让我去其他方法,如果我能得到整个USB_DEVICE_DESCRIPTOR,我想我已经拥有了我需要的一切。
  • LibUsb.Net显然只支持WinUsb设备。这就是它如何获得描述符。
  • 显然WinRT有一些新的API,因此Windows应用商店应用程序有一个很好的获取描述符的方法。但这绝对不是Windows应用商店应用,我也不知道还有另一种方法可以使用更新的API。

有人能指出我正确的方向吗?如果没有从Hub开始,是不是可以以一种很好的方式从WinAPI获取这些信息?

1 个答案:

答案 0 :(得分:0)

您最好的选择是从设备路径中提取信息,并使用SetupDi函数来获取其他的碎片。据我所知,设备路径始终遵循相同的约定。即:

" \\?\ USB#vid_的 0000 &安培; PID_的 1111 #的 SERIAL #{的 GUID }" 其中0000是VID,1111是PID作为十六进制字符串。 SERIAL是硬件提供的串行或OS分配的串行值。

我个人发现了一个实例,我绝对想要获取设备描述符以便以这种方式拉出串口。在某些情况下,操作系统无法识别我的硬件提供的序列号。我在硬件方面修复了这个问题,但我仍然希望在PC端容纳旧硬件。以下是我的方法。可能有更好的东西,但这是我迄今为止提出的最好的。你可能仍然认为它是" hack-ish"虽然。

  1. 调用SetupDiGetClassDevs()来设置所需的DeviceInfoSet
  2. 使用SetupDiEnumDeviceInfo()
  3. 获取设备信息数据
  4. 使用SPDRP_LOCATION_INFORMATION调用SetupDiGetDeviceRegistryProperty()以获取位置信息。此字符串应如下所示" Port_#0001.Hub_#0001"。解析此字符串以获取设备所在的端口号。 (我假设这个值是10的基础,但我还没有对此进行验证)
  5. 调用CM_Get_Parent()以获取父(集线器)的设备节点指针值
  6. 使用GUID {0xf18a0e88,0xc30c,0x11d0,{0x88,0x15,0x00,0xa0,0xc9,0x06,0xbe,0xd8}}调用SetupDiGetClassDevs()以获取系统上的所有集线器。该GUID应在usbiodef.h中定义为GUID_DEVINTERFACE_USB_HUB。
  7. 使用SetupDiEnumDeviceInfo()遍历设备列表。一旦DevInst等于步骤4中获得的值,就停止。
  8. 在步骤6中找到的索引上调用SetupDiGetDeviceInterfaceDetail()。
  9. 在步骤7中获取的DevicePath上调用CreateFile()。
  10. 使用步骤8中创建的文件和步骤3中获取的端口号作为连接索引调用DeviceIoControl()。
  11. - 编辑 -

    正如Ben在评论中指出的那样,你可以通过在步骤4中获得的父节点开发节点上使用CM_Get_Device_ID来跳过步骤5,6和7.将此字符串中的斜杠(\)更改为磅( #)。前置" \\?\"然后追加"#{f18a0e88-c30c-11d0-8815-00a0c906bed8}"。在步骤8中将其用作设备路径。这可以避免迭代系统上的所有集线器设备:)