как получить идентификатор поставщика и идентификатор продукта подключенного USB-устройства на Windows - PullRequest
7 голосов
/ 29 мая 2010

Я использую Qt на платформе Windows.

Я хочу получить и отобразить идентификатор поставщика и идентификатор продукта подключенного USB-устройства из моей локальной системы.

Ниже приведен мой полный исходный код для получения идентификатора поставщика и идентификатора продукта с USB-устройства.

когда я запускаю приложение qt, оно не выдает никаких ошибок.

поэтому я подключаю USB-устройство к системе.

но мой оператор печати отображает результат как показано ниже

qDebug ()<<pDetData->DevicePath;

я получаю результат как 0x4

Есть ли у меня ошибки реализации в моем исходном коде?

Если так, пожалуйста, объясните мне, что я делаю неправильно ..

Я пропустил какие-либо другие функции?

Можно ли получить идентификатор поставщика и идентификатор продукта с USB-устройства на основе моего исходного кода (моя реализация кода)?

пожалуйста, найдите мой исходный код ниже

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 Code:

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

Любые идеи в этом ....

Ответы [ 3 ]

9 голосов
/ 29 мая 2010

После этой строки:

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(). Сделайте это, есть много функций, которые работают следующим образом, с указателями на структуры переменного размера.

-------- Отредактировано, чтобы добавить: --------

Вы действительно делаете это неправильно. Я вижу, что вы следуете совету, который вы получили здесь , и это привело вас на неверный путь. 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 и, вероятно, все еще делает, но у меня нет доступа к одному.

---------- Отредактировано, чтобы добавить: ----------

Даниэль К пишет, что код действительно должен быть:

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

Подробнее см. В комментариях.

1 голос
/ 18 декабря 2012

Альтернативой является получение идентификатора оборудования, который включает VID и PID.

Вызовите SetupDiGetDeviceRegistryProperty с SPDRP_HARDWAREID примерно так:

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 голосов
/ 31 мая 2010

Вы перечисляете «интерфейс» устройства. Интерфейсы не имеют VID или PID - экземпляры устройства имеют. Я не уверен, перечисляете ли вы интерфейсы для сужения интересующих вас устройств, потому что это ошибка.

Если вы просто перечислите экземпляры устройства, то вы можете вызвать SetupDiGetDeviceProperty с DEVPKEY_Device_HardwareIds, а затем получить полученный аппаратный идентификатор для VID и PID.

Если вы намеренно используете интерфейсы устройства, то вам нужно один раз вызвать SetupDiGetDeviceInterfaceDetail с параметром NULL PSP_DEVICE_INTERFACE_DETAIL и действительным указателем requiredSize, чтобы получить необходимый объем памяти для выделения, выделить эту память и затем снова вызвать функцию. В этом вызове последний параметр представляет собой структуру SP_DEVINFO_DATA, которую после извлечения вы можете использовать при вызове SetupDiGetDeviceProperty, как я упоминал выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...