windows下枚举USB设备

在网上看到很多是通过枚举卷来枚举USB的,但是一个USB设备可能有多个卷,若想获取一个USB设备的描述符,就行不通了。

我这里使用的方法是先枚举所有的hub设备,然后再遍历每个hub下port所连接的设备。因为所有的port都是在hub下的,所有不会有遗漏。

1. 构建hub的GUID

    DEFINE_GUID(GUID_DEVINTERFACE_USB_HUB,

    0xf18a0e88, 0xc30c, 0x11d0, 0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8);

    #define GUID_CLASS_USB_HUB GUID_DEVINTERFACE_USB_HUB

2. 通过hub的GUID来获取hub的信息集:

    HDEVINFO info = SetupDiGetClassDevs(lpGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);

3. 枚举信息集下的所有hub设备:

    for (i = 0; SetupDiEnumDeviceInfo(info, i, &DeviceInfoData); i++)

    {

    ......

    if (!SetupDiGetDeviceInstanceId(info, &DeviceInfoData, (PTSTR)did, buffersize, &req_bufsize)){

    continue;

    ......

    }

通过 SetupDiEnumDeviceInfo 函数枚举hub设备,再通过 SetupDiGetDeviceInstanceId 函数获取到ID。

4. 获取hub句柄

将 1 中获取到的ID拼接成devicepath,即在ID的前面添加"\\\\.\\",ID后添加"#{f18a0e88-c30c-11d0-8815-00a0c906bed8}"。

    HANDLE hubUsbHandle = CreateFile(hubDevicePathW,

        GENERIC_WRITE,

        FILE_SHARE_WRITE,

        NULL,

        OPEN_EXISTING,

        0,

        NULL);

通过 CreateFile 函数获取到hub的句柄。

5. 获取hub连接信息

    BOOL success = DeviceIoControl(hHubDevice,

        IOCTL_USB_GET_NODE_INFORMATION,

        HubInfo,

        sizeof(USB_NODE_INFORMATION),

        HubInfo,

        sizeof(USB_NODE_INFORMATION),

        &nBytes,

        NULL);

通过 DeviceIoControl 获取到对应hub的信息。接着获取对应的hub下的port数:

    HubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts

6. 遍历所有port

    PUSB_NODE_CONNECTION_INFORMATION connectionInfo;

    connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)malloc(nBytes);

    if (connectionInfo == NULL)

        return false;

    connectionInfo->ConnectionIndex = index;

    BOOL success;

    success = DeviceIoControl(hHubDevice,

        IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,

        connectionInfo,

        nBytes,

        connectionInfo,

        nBytes,

        &nBytes,

        NULL);

首先构建 connectionInfo,设置其index。通过 DeviceIoControl 获取当前port的信息,信息储存在 connectionInfo 中。

    UCHAR nSerialno = connectionInfo->DeviceDescriptor.iSerialNumber;

    USHORT idVendor = connectionInfo->DeviceDescriptor.idVendor;

    USHORT idProduct = connectionInfo->DeviceDescriptor.idProduct;

以上是获取SN的索引和vid及pid的值。

目前为止,我的需求只是获取USB设备的 pid ,所以并没有在此描述获取其他的数据信息。因为之前有在网上看到一个通过hub的句柄来获取连接到其port上的USB设备的信息,所以这里就遍历所有的hub。当然也可以直接遍历所有的USB,只需将 1 中的GUID换成USB的GUID:

    DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE,

    0xA5DCBF10/*L*/, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);

    #define GUID_CLASS_USB_DEVICE GUID_DEVINTERFACE_USB_DEVICE

接下的步骤和获取hub句柄类似,也是先构建好devicepath,便可获取到USB的句柄,然后通过DeviceIoControl 来获取到连接的设备信息,不过具体要传哪些参数就得自己去琢磨了。

以下是通过 usb device tree viewer 看到的结构图。强烈建议下载一个 UsbTreeView ,开发时有很大的帮助。

猜你喜欢

转载自blog.csdn.net/qq_23867503/article/details/85463675