USB应用层开发
+ -

Windows系统获取所有USB设备端口位置的方法

2021-09-26 6519 10

多个厂商名字、序列号、设备名都一样USB插到电脑上要怎么区分呢?可以通过获取设备的hub端口位置来区分。示例代码如下:

DEFINE_GUID( GUID_DEVCLASS_USB,  0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 );
int PrintAllUsbDevicesLocationInfo()
{
    DWORD i; 
    HDEVINFO hDevInfo = {0}; 

    TCHAR szDescBuf[MAX_PATH] = {0};
    TCHAR szLocationBuf[MAX_PATH] = {0};
    TCHAR szHwId[MAX_PATH] = {0};

    SP_DEVINFO_DATA DeviceInfoData = {0}; 
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    // 得到所有USB设备 HDEVINFO  
    // 第一个参数不能设置为GUID_DEVCLASS_USB,因为hid设备类为HIDClass,以及一些其他设备的设备也不一定是USB
    hDevInfo = SetupDiGetClassDevs(NULL, TEXT("USB"), 0, DIGCF_ALLCLASSES|DIGCF_PRESENT);     
    if (hDevInfo == INVALID_HANDLE_VALUE)     
        return 0;

    int cnt = 0;

    // 循环列举 
    for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++)     
    {
        if (!SetupDiGetDeviceRegistryProperty(hDevInfo, 
            &DeviceInfoData, 
            SPDRP_HARDWAREID, 
            NULL, 
            (PBYTE)szHwId, 
            MAX_PATH - 1,
            NULL))         
        {
            continue;            
        }

        if (!SetupDiGetDeviceRegistryProperty(hDevInfo, 
            &DeviceInfoData, 
            SPDRP_DEVICEDESC, 
            NULL, 
            (PBYTE)szDescBuf, 
            MAX_PATH - 1, 
            NULL))
        {
            continue;
        }

        // 获取设备在Hub中的Port位置
        if (!SetupDiGetDeviceRegistryProperty(hDevInfo, 
            &DeviceInfoData, 
            SPDRP_LOCATION_INFORMATION,
            NULL, 
            (PBYTE)szLocationBuf, 
            MAX_PATH - 1, 
            NULL))   
        {
            continue;
        }

        if (_tcsstr(szLocationBuf, TEXT("Port")))
        {
            printf("Desc:%s\r\n",szDescBuf);
            printf("HardwareId:%s\r\n", szHwId);
            printf("Location:%s\r\n\r\n", szLocationBuf);
            cnt++;
        }
    }     
    //  释放     
    SetupDiDestroyDeviceInfoList(hDevInfo);
    printf("total usb devices num = %d\r\n", cnt);
}

运行该函数,在我的电脑输出信息如下:

Desc:USB Serial Converter
HardwareId:USB\VID0403&PID_6001&REV_0600
Location:Port
#0003.Hub_#0002

Desc:USB 2.0 集线器
HardwareId:USB\VID05E3&PID_0610&REV_0654
Location:Port
#0003.Hub_#0001

Desc:USB 输入设备
HardwareId:USB\VID0955&PID_6789&REV_0200
Location:Port
#0002.Hub_#0001

Desc:Realtek USB 2.0 Card Reader
HardwareId:USB\VID0BDA&PID_0129&REV_3960
Location:Port
#0005.Hub_#0001

Desc:Generic Bluetooth Adapter
HardwareId:USB\VID0BDA&PID_0821&REV_0200
Location:Port
#0007.Hub_#0001

Desc:Total Phase Beagle Protocol Analyzer
HardwareId:USB\VID1679&PID_2001&REV_0100
Location:Port
#0001.Hub_#0002

Desc:USB Composite Device
HardwareId:USB\VID1D6C&PID_0513&REV_0010
Location:Port
#0001.Hub_#0001

Desc:USB Composite Device
HardwareId:USB\VID248A&PID_8367&REV_0100
Location:Port
#0004.Hub_#0002

Desc:USB Composite Device
HardwareId:USB\VID5986&PID_06B2&REV_5307
Location:Port
#0004.Hub_#0001

total usb devices num = 9

经过比对,设备数量和UsbTreeView枚举结果完全一致。

程序通过SetupXX系列函数枚举所有USB设备,然后通过SetupDiGetDeviceRegistryProperty传参SPDRP_LOCATION_INFORMATION就可以获取到设备的Hub口Port信息了。

函数获取的HardwareId信息是包括设备的VID和PID的,过滤一下就能获得特定VID/PID设备的位置信息啦。

需要注意的是
SetupDiGetClassDevs(&GUID_DEVCLASS_USB, NULL, 0, DIGCF_ALLCLASSES|DIGCF_PRESENT)
这样调用并不能枚举到所有USB设备,譬如Hid设备的GUID设备类就不是USB, 而是HIDClass。

经过探测发现所有USB设备信息的枚举值都是USB,因此可以通过
SetupDiGetClassDevs(NULL, TEXT(“USB”), 0, DIGCF_ALLCLASSES|DIGCF_PRESENT)
这样调用来枚举所有USB设备。

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

Windows系统获取所有USB设备端口位置的方法
多个厂商名字、序列号、设备名都一样USB插到电脑上要怎么区分呢?可以通过获取设备的hub端口位置来区分。示例代码如下:DEFINE_GUID( GUID_DEVCLASS_USB, 0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53,......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!