我想在我的系统上获取USB设备的设备描述符。我正在Windows中创建一个用户空间应用程序(un-managed,native c ++)。从这些描述符中我想识别广告牌设备,并解析广告牌功能描述符(解析bos描述符)。
这是我的方法。
SetupDiGetClassDevs(&GUID_CLASS_USB_DEVICE,...)
SetupDiGetDeviceInterfaceDetail()
CreateFile()
来获取设备的句柄。IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
IOCTL使用DeviceIoControl()
和句柄来获取设备描述符。我被困在第4步(getLastError() - Invalid Function
)
其他项目(like this sample code from Intel),枚举系统上的所有USB控制器,根集线器,端口和接口,并在根集线器的句柄上发出IOCTL,指定设备连接的端口号。
我不想关心系统的USB层次结构。 它不易出错,并且使用安装API更容易在系统中获取USB设备。然而,我无法直接向他们发出IOCTL。
Update1
来自docs.microsoft.com:
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
I / O控制请求检索与指示的端口索引相关联的设备的一个或多个描述符。此请求 定位到USB集线器设备 (GUID_DEVINTERFACE_USB_HUB)。因此,这个能给我USB设备设备描述符的ioctl意味着由USB Hub处理,而 NOT 则由USB设备处理。
因此,其他解决方案将集线器的句柄传递给DeviceIoControl(),这可以从英特尔(Line 68)的源代码Linked here上看到。
我想要使用上面步骤3中获得的句柄(设备句柄)来获取设备描述符。因此,IOCTL可能不同,或者可能有一种方法来处理集线器,以及使用USB设备的句柄连接设备的端口索引。
我看到它的方式,设备描述符是USB设备的固有属性,因此必须有一种方法直接从USB设备获取它。
答案 0 :(得分:1)
假设您首先已经拥有 USB 设备句柄,您需要从中获取 DEVPKEY_Device_Driver
属性字符串(通过 CM_Get_DevNode_PropertyW
或 SetupDiGetDevicePropertyW
)。
您将收到类似 {36fc9e60-c465-11cf-8056-444553540000}\0010
的字符串。
接下来,您需要遍历系统中的每个 USB 集线器(具有 GUID_DEVINTERFACE_USB_HUB
接口的设备)和每个:
CreateFile()
调用打开它DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_INFORMATION, ...)
以获取 USB_NODE_INFORMATION 结构,该结构在其 hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts
中包含多个 USB 端口bNumberOfPorts
的每个端口,调用 DeviceIoControl(hubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ...)
以获得连接到该端口的设备的唯一 DriverKey
。DEVPKEY_Device_Driver
调用中的字符串进行比较。如果它们相同 - 恭喜您找到了连接 USB 设备的 USB 集线器和端口!现在您可以调用 DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, ...)
来获取包含 USB_NODE_CONNECTION_INFORMATION 的 USB_DEVICE_DESCRIPTOR 结构!
此外,您还可以使用 USB_DESCRIPTOR_REQUEST 调用 DeviceIoControl(usbHubInterfaceHandle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ...)
以获取除基本 USB_DEVICE_DESCRIPTOR
之外的其他 USB 描述符。
示例代码参见官方 USBView sample 中的 EnumerateHubPorts()
和 GetDriverKeyName()
。
我也是在我的 RawInputDemo repo here 中这样做的。