2

我想在我的系统上获取 USB 设备的设备描述符。我正在 Windows 中创建一个用户空间应用程序(非托管,本机 c++)。从这些描述符中,我想识别广告牌设备并解析广告牌功能描述符(解析 bos 描述符)。

这是我的方法。

  1. 通过以下方式获取系统上的 USB 设备SetupDiGetClassDevs(&GUID_CLASS_USB_DEVICE,...)
  2. 使用获取每个设备的设备路径SetupDiGetDeviceInterfaceDetail()
  3. 在设备路径上使用CreateFile()以获取设备的句柄。
  4. 使用和句柄发出IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTIONIOCTL以获取设备描述符。DeviceIoControl()

我被困在第四步(getLastError() - Invalid Function)。
其他项目(例如来自 Intel 的示例代码),枚举系统上的所有 USB 控制器、根集线器、端口和接口,并在根集线器的句柄上发出 IOCTL,指定设备连接到的端口号。

我不想关心系统的 USB 层次结构。使用设置 API 在系统中获取 USB 设备更不容易出错且更容易。但是,我在任何地方都看不到直接向他们发出 IOCTL。

更新1

来自docs.microsoft.com:I/O
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION控制请求检索与指定端口索引关联的设备的一个或多个描述符。此请求以 USB 集线器设备(GUID_DEVINTERFACE_USB_HUB) 为目标。因此,这个可以为我提供 USB 设备的设备描述符的 ioctl 应该由 USB 集线器处理,而不是由 USB 设备处理。

因此,其他解决方案将集线器的句柄传递给 DeviceIoControl(),如Intel 源代码的第 68 行所示(在此处链接)。

相反,我想使用上面第 3 步(设备的句柄)中获得的句柄来获取设备描述符。因此,IOCTL 可能不同,或者可能有一种方法可以获取集线器的句柄,以及使用 USB 设备的句柄连接设备的端口索引。

在我看来,设备描述符是 USB 设备的固有属性,因此必须有一种方法可以直接从 USB 设备获取它。

4

1 回答 1

1

假设您首先已经拥有 USB 设备句柄,您需要从中获取DEVPKEY_Device_Driver属性字符串(通过CM_Get_DevNode_PropertyWor SetupDiGetDevicePropertyW)。

你会收到类似的字符串{36fc9e60-c465-11cf-8056-444553540000}\0010

接下来,您需要遍历系统中的每个 USB 集线器(具有GUID_DEVINTERFACE_USB_HUB接口的设备)并为每个集线器:

  1. CreateFile()通过调用打开它
  2. 调用DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_INFORMATION, ...)以获取包含 USB 端口数量的USB_NODE_INFORMATION结构hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts
  3. 对于从 1 开始的每个端口(它们是基于一个的!!!)bNumberOfPorts调用DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ...)以获取DriverKey连接到该端口的唯一设备。
  4. 将您在上一步中获得的 DriverKey 字符串与您在DEVPKEY_Device_Driver调用中获得的字符串进行比较。如果它们相同 - 恭喜您找到连接 USB 设备的 USB 集线器和端口!

现在您可以调用DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, ...)以获取包含USB_DEVICE_DESCRIPTOR的USB_NODE_CONNECTION_INFORMATION结构!

此外,您还可以使用 USB_DESCRIPTOR_REQUEST 调用DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ...)获取除 basic 之外的其他 USB 描述符USB_DEVICE_DESCRIPTOR

例如代码参见官方EnumerateHubPorts()USBView示例GetDriverKeyName()

我也只是在我的RawInputDemo 存储库中这样做了

于 2021-06-14T15:12:33.867 回答