给定设备路径,如何获取 USB_DEVICE_DESCRIPTOR [英] How do I obtain USB_DEVICE_DESCRIPTOR given a device path

查看:24
本文介绍了给定设备路径,如何获取 USB_DEVICE_DESCRIPTOR的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经能够使用 SetupAPI 枚举 USB 设备,并且我已经查看了 WDK 中的 usbview 应用程序,但我仍然不知道如何获取 USB_DEVICE_DESCRIPTOR.

I have been able to enumerate USB devices using the SetupAPI, and I've looked at the usbview application from the WDK, but I still can't figure out how to get the USB_DEVICE_DESCRIPTOR.

  • 我宁愿避免使用 WMI.
  • DeviceIoControl 是示例应用程序 usbview 使用的内容,但实际上只有在您枚举集线器上的设备时才有效.我想如果我可以在给定设备路径(或 Id)的情况下访问父集线器(和端口),则此方法可能有效,但我也无法确定如何执行此操作.
  • 我有多种设备想要获取描述符.其中一些是 HID,一些可能是 WinUsb.sys 设备.如果它们是 WinUsb 设备,我可以使用 WinUsb_GetDescriptor,但这对 HID 不起作用(我不知道如何区分它们与 Id 或 Path...Interface 类之间的区别,我猜?).
  • 我可以使用 SetupDiGetDeviceRegistryProperty 但在可用属性列表中,我可以看到制造商字符串,但看不到供应商 ID.
  • 我可以从设备路径或设备 ID 中解析出这个值,但这似乎有点...hack-ish.然而,这只是人们所做的吗?此外,如果我想要像制造商这样的其他领域,它仍然让我去其他方法,如果我能得到整个 USB_DEVICE_DESCRIPTOR,我想我会拥有我需要的一切.
  • LibUsb.Net 显然只支持 WinUsb 设备.这就是获取描述符的方式.
  • 显然 WinRT 有一些新的 API,因此 Windows 应用商店应用程序有一个很好的方法来获取描述符.但这绝对不是 Windows 应用商店应用,我不知道还有其他方法可以使用较新的 API.
  • I would rather avoid using WMI.
  • DeviceIoControl is what the sample app usbview uses, but that really only works if you're enumerating devices on a Hub. I suppose if I can get to the parent hub (and port) given a device path (or Id), this method may work but I haven't been able to determine how to do this either.
  • I have a mix of devices for which I'd like to get the descriptor. Some of these are HIDs, and it's possible some are WinUsb.sys devices. If they are WinUsb devices I can use WinUsb_GetDescriptor, but that won't work for HIDs (and I don't know how to tell the difference between them from the Id or Path...Interface class I guess?).
  • I could use SetupDiGetDeviceRegistryProperty but in the list of available properties, I can see the Manufacturer string, but not the vendor Id.
  • I could possibly parse this value from the device path or the device Id, but that seems sort of...hack-ish. Is that just what people do though? Also it still leaves me going to other methods if I want other fields like the Manufacturer, where if I could just get the whole USB_DEVICE_DESCRIPTOR I think I'd have about everything I need.
  • LibUsb.Net only supports WinUsb devices apparently. That's how it seems to get the descriptor.
  • Apparently WinRT has some new APIs and therefore Windows Store apps have a nice way of getting the descriptor. But this is definitely not a Windows Store app, and I don't know that there is another way to use the newer APIs.

谁能指出我正确的方向?如果不从集线器开始,就不可能以一种很好的方式从 WinAPI 获取这些信息吗?

Can anyone point me in the right direction? Is it just not possible to get this information from the WinAPI in a nice way without starting at the Hub?

推荐答案

最好的办法是从设备路径中提取信息并使用 SetupDi 函数获取其他零碎信息.据我所知,设备路径始终遵循相同的约定.即:

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}"其中 0000 是 VID,1111 是十六进制字符串的 PID.SERIAL 要么是硬件提供的串行,要么是操作系统分配的串行值.

"\\?\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.

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

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

-编辑-

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

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 :)

这篇关于给定设备路径,如何获取 USB_DEVICE_DESCRIPTOR的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆