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

问题描述 投票:0回答:4

我在windows平台上使用Qt。

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

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

当我运行我的 qt 应用程序时,它不会抛出任何错误。

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

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

qDebug ()<<pDetData->DevicePath;

我得到的结果是 0x4

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

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

我错过了任何其他功能吗?

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

请在下面找到我的源代码

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; 
} 

任何想法......

c++ windows qt winapi usb
4个回答
10
投票

这一行之后:

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()
的文档。做吧,有很多函数是这样工作的,带有指向可变大小结构的指针。

--------编辑添加:--------

你真的走错了路。我看到您正在遵循 here 的建议,但它让您走错了路。

idVendor
idProduct
只能在
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->idVendor
udd->idProduct
应该有你想要的。

Microsoft 曾经在 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);

有关详细信息,请参阅评论。


2
投票

另一种方法是获取包含 VID 和 PID 的硬件 ID。

像这样使用 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设备。


0
投票

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

如果您只是枚举设备实例,那么您可以使用 DEVPKEY_Device_HardwareIds 调用 SetupDiGetDeviceProperty,然后为 VID 和 PID 获取结果硬件 ID。

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


-1
投票

看着一个人和几个不同的自我来回聊天真是太搞笑了 我总能说出来。 氛围总是单一的,与普遍的看法相反我不是傻子

© www.soinside.com 2019 - 2024. All rights reserved.