Windows系统获取所有USB设备端口位置的方法
多个厂商名字、序列号、设备名都一样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_#0002Desc:USB 2.0 集线器
HardwareId:USB\VID05E3&PID_0610&REV_0654
Location:Port#0003.Hub_#0001Desc:USB 输入设备
HardwareId:USB\VID0955&PID_6789&REV_0200
Location:Port#0002.Hub_#0001Desc:Realtek USB 2.0 Card Reader
HardwareId:USB\VID0BDA&PID_0129&REV_3960
Location:Port#0005.Hub_#0001Desc:Generic Bluetooth Adapter
HardwareId:USB\VID0BDA&PID_0821&REV_0200
Location:Port#0007.Hub_#0001Desc:Total Phase Beagle Protocol Analyzer
HardwareId:USB\VID1679&PID_2001&REV_0100
Location:Port#0001.Hub_#0002Desc:USB Composite Device
HardwareId:USB\VID1D6C&PID_0513&REV_0010
Location:Port#0001.Hub_#0001Desc:USB Composite Device
HardwareId:USB\VID248A&PID_8367&REV_0100
Location:Port#0004.Hub_#0002Desc:USB Composite Device
HardwareId:USB\VID5986&PID_06B2&REV_5307
Location:Port#0004.Hub_#0001total 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设备。