如何获得在Windows上插入USB设备的供应商ID和产品ID

我在Windows平台上使用Qt。

我想获得并显示从我的本地系统插入的USB设备的供应商ID和产品ID。

以下是我的完整源代码从USB设备获取供应商ID和产品ID。

当我运行我的QT应用程序,它不会给我任何错误。

所以我把USB设备插入系统。

但是我的打印语句显示如下结果

qDebug ()<<pDetData->DevicePath;

我得到的结果为0x4

我的源代码中是否有任何实现错误?

如果是这样,请指导我我做错了什么..

我错过了其他function吗?

是否有可能根据我的源代码从USB设备获得供应商ID和产品ID(我的代码实现)?

请在下面find我的源代码

 static GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; HANDLE hInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE,NULL,NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if ( hInfo == INVALID_HANDLE_VALUE ) { qDebug ()<<"invalid"; } else { qDebug ()<<"valid handle"; SP_DEVINFO_DATA DeviceInfoData; DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); SP_INTERFACE_DEVICE_DATA Interface_Info; Interface_Info.cbSize = sizeof(Interface_Info); BYTE Buf[1024]; DWORD i; DWORD InterfaceNumber= 0; PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA) Buf; for (i=0;SetupDiEnumDeviceInfo(hInfo,i,&DeviceInfoData);i++) { DWORD DataT; LPTSTR buffer = NULL; DWORD buffersize = 0; while (!SetupDiGetDeviceRegistryProperty( hInfo, &DeviceInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buffer, buffersize, &buffersize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // Change the buffer size. if (buffer) LocalFree(buffer); buffer = (LPTSTR)LocalAlloc(LPTR,buffersize); } else { // Insert error handling here. break; } qDebug ()<<(TEXT("Device Number %i is: %s\n"),i, buffer); if (buffer) LocalFree(buffer); if ( GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS ) { // Insert error handling here. qDebug ()<<"return false"; } InterfaceNumber = 0; // this just returns the first one, you can iterate on this if (SetupDiEnumDeviceInterfaces(hInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, InterfaceNumber, &Interface_Info)) { printf("Got interface"); DWORD needed; pspdidd->cbSize = sizeof(*pspdidd); SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL; DWORD dwDetDataSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256; SetupDiGetDeviceInterfaceDetail(hInfo, &Interface_Info, pDetData,dwDetDataSize, NULL, &DeviceInfoData); qDebug ()<<pDetData->DevicePath; //qDebug ()<<QString::fromWCharArray(pDetData->DevicePath); } else { printf("\nNo interface"); //ErrorExit((LPTSTR) "SetupDiEnumDeviceInterfaces"); if ( GetLastError() == ERROR_NO_MORE_ITEMS) printf(", since there are no more items found."); else printf(", unknown reason."); } // Cleanup SetupDiDestroyDeviceInfoList(hInfo); qDebug ()<<"return true"; } } } 

—————编辑添加:—————–

嗨…应用程序来打印这个

\?\ usb#vid_04f2&pid_0111#5&1ba5a77f&0&2#{a5dcbf1 0-6530-11d2-901f-00c04fb951ed}

再次它去while循环….在这里它得到在else语句中打破…

Qt代码:

 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // Change the buffer size. if (buffer) LocalFree(buffer); buffer = (LPTSTR)LocalAlloc(LPTR,buffersize); } else { qDebug ()<<"Here it quits the application"; // Insert error handling here. break; } 

任何想法在这….

在这行之后:

 SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL; 

添加这个:

 DWORD dwDetDataSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA) + 256; pDetData = (_SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc (dwDetDataSize); pDetData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); 

在这行之后:

 qDebug ()<<pDetData->DevicePath; 

添加这个:

 free(pDetData); 

但最终你将不得不阅读SetupDiGetDeviceInterfaceDetail()的文档。 做到这一点,有很多这样的功能,指向可变大小的结构。

——–编辑补充:——–

你真的正在做这个错误的方式。 我看到你正在听从你在这里的建议,并且把你带到了错误的路上。 idProductidProduct只能在USB_DEVICE_DESCRIPTOR ( MSDN )中找到。

看起来你已经知道如何获得设备句柄(使用CreateFile() )。 之后,您可以调用WinUsb_Initialize() ( MSDN )。 这让你一个WINUSB_INTERFACE_HANDLE

一旦拥有该句柄,就需要调用WinUsb_GetDescriptor() ( MSDN ),将DescriptorType设置为URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 我现在不能测试代码,但它看起来像这样:

 USB_DEVICE_DESCRIPTOR udd; memset(&udd, 0, sizeof(udd)); ULONG LengthTransferred = 0; WinUsb_GetDescriptor( winusb_interface_handle, // returned by WinUsbInitialize URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, 0, // not sure if we need this 0x409, // not sure if we need this &udd, sizeof(udd), &LengthTransferred); 

之后, udd->idProductudd->idProduct应该有你想要的。

微软过去提供所有这些在DDK中的示例代码,并且可能仍然有,但我没有访问一个。

———-编辑补充:———-

Daniel K写道,代码应该是:

 USB_DEVICE_DESCRIPTOR udd; memset(&udd, 0, sizeof(udd)); ULONG LengthTransferred = 0; WinUsb_GetDescriptor( winusb_interface_handle, // returned by WinUsbInitialize USB_DEVICE_DESCRIPTOR_TYPE, // Daniel K's suggestion 0, 0x409, // asks for English &udd, sizeof(udd), &LengthTransferred); 

请参阅评论了解更多详情。

您正在枚举设备“接口”。 接口没有VID或PID – 设备实例。 我不确定您是否列举了缩小您感兴趣的设备的接口,因为这是一个错误。

如果您只是枚举设备实例,则可以使用DEVPKEY_Device_HardwareIds调用SetupDiGetDeviceProperty,然后grep生成的VID和PID的硬件ID。

如果您有意使用设备接口,则需要使用一个NULL PSP_DEVICE_INTERFACE_DETAIL参数和一个有效的requiredSize指针来调用SetupDiGetDeviceInterfaceDetail一次,以获取所需的大小的内存分配,然后分配该内存,然后再次调用该函数。 在那个调用中,最后一个参数是一个SP_DEVINFO_DATA结构,它一旦被检索到,就可以在上面提到的调用SetupDiGetDeviceProperty中使用。

另一种方法是获取包含VID和PID的hardwareID。

使用SPDRP_HARDWAREID调用SetupDiGetDeviceRegistryProperty,如下所示:

 wchar_t *hardwareID; // First get requiredLength SetupDiGetDeviceRegistryProperty(deviceInfoList, &deviceInfoData, SPDRP_HARDWAREID, NULL, NULL, 0, &requiredLength); hardwareID = (wchar_t*)(new char[requiredLength]()); // Second call to populate hardwareID SetupDiGetDeviceRegistryProperty(deviceInfoList, &deviceInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)hardwareID, requiredLength, NULL); // Display the string qDebug() << "hardwareID =" << QString::fromWCharArray(hardwareID); 

这会给你一个像USB\ROOT_HUB20&VID1002&PID4396&REV0000你可以解析的字符串。

*注意:并非所有设备都有VID和PID,如非USB设备。