2010-05-29 2 views
6

Ich verwende Qt auf Windows-Plattform.wie Vendor ID und Produkt-ID eines angeschlossenen USB-Gerät auf Windows

Ich möchte die Hersteller-ID und die Produkt-ID eines angeschlossenen USB-Geräts von meinem lokalen System abrufen und anzeigen.

Im Folgenden finden Sie meinen vollständigen Quellcode, um die Hersteller-ID und die Produkt-ID vom USB-Gerät abzurufen.

wenn ich die my qt-Anwendung ausführen, wirft es mir keine Fehler.

so stecke ich das USB-Gerät in das System.

aber meine print-Anweisung zeigt das Ergebnis, wie unten

qDebug()<<pDetData->DevicePath;

i das Ergebnis als 0x4

Ob ich in meinem Quellcode keine Implementierung Fehler haben bekommen?

wenn ja bitte leite mich, was ich falsch mache ..

habe ich verpasst keine anderen Funktionen aus?

Ist es möglich, die Hersteller-ID und die Produkt-ID von dem USB-Gerät basierend auf meinem Quellcode zu erhalten (meine Implementierung des Codes)?

freundlich meine Quellcode unter

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

--------------- Edited hinzufügen finden: ------------- ----

Hallo ... die Anwendung kommt und druckt diese

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

wieder geht es Schleife um während .... hier ist es in der else-Anweisung ...

Qt-Code breaked wird:

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

Irgendwelche Ideen in diesem ....

+0

Sie müssen diese Codewand besser formatieren, wenn Sie sie lesen möchten. –

+0

umformatiert ich den Code ... – egrunin

+2

ich Ihren Kommentar zu meiner Antwort (unten) kopiert und den beigefügten es auf Ihre Frage (wo er hingehört) – egrunin

Antwort

8

Nach dieser Zeile:

SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL; 

Fügen Sie diese:

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

Nach dieser Zeile:

qDebug()<<pDetData->DevicePath; 

hinzufügen:

free(pDetData); 

Aber irgendwann müssen Sie die Dokumente für SetupDiGetDeviceInterfaceDetail() lesen. Tun Sie es, es gibt viele Funktionen, die so funktionieren, mit Zeigern auf Strukturen variabler Größe.

-------- Edited hinzufügen: --------

Du wirklich darüber in die falsche Richtung gehen. Ich sehe, du folgst dem Rat, den du bekommen hast here, und es hat dich auf den falschen Weg gebracht. idVendor und idProduct sind nur in der USB_DEVICE_DESCRIPTOR (MSDN) zu finden.

Es sieht so aus, als ob Sie bereits wissen, wie Sie das Gerätehandle bekommen (mit CreateFile()). Danach rufen Sie WinUsb_Initialize() (MSDN). Das bringt dir eine WINUSB_INTERFACE_HANDLE.

Sobald Sie diesen Griff haben, möchten Sie WinUsb_GetDescriptor() (MSDN), mit dem DescriptorType Satz URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE nennen. Ich kann jetzt nicht testen Code, aber es wird in etwa so aussehen:

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

Danach, udd->idVendor und udd->idProduct sollten, was Sie wollen.

Microsoft verwendet, um Beispielcode für all dies im DDK zu liefern, und wahrscheinlich immer noch, aber ich habe keinen Zugriff auf einen.

---------- Edited hinzufügen: ----------

Daniel K schreibt, dass der Code wirklich sein sollte:

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

Siehe die Kommentare für weitere Details.

+0

Hallo ... die Anwendung kommt und druckt diese „\\? \ usb # vid_04f2 & pid_0111 # 5 & 1ba5a77f & 0, 2 # {a5dcbf1 0-6530-11d2-901f-00c04fb951ed}“ wieder geht es Schleife um während .... hier es wird in der else-Anweisung ... Qt-Code breaked: if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // Ändern Sie die Puffergröße. if (Puffer) LocalFree (Puffer); Puffer = (LPTSTR) LocalAlloc (LPTR, Puffergröße); } sonst { qDebug() << "Hier wird die Anwendung beendet"; // Fügen Sie hier die Fehlerbehandlung ein. Pause; } Irgendwelche Ideen in diese .... – user198725878

+0

+1 für diese, aber ich würde empfehlen, 'std :: vector ' für C++ Code, anstatt manuell 'malloc' verwenden. –

+0

@Billy ONeal: gute Idee. – egrunin

0

Sie listen das Gerät "Schnittstelle" auf. Schnittstellen haben keine VID oder PID - Geräte Instanzen tun. Ich bin nicht sicher, ob Sie die Schnittstellen aufzählen, um die Geräte einzugrenzen, an denen Sie interessiert sind, weil es ein Fehler ist.

Wenn Sie nur die Geräteinstanzen aufzählen, können Sie SetupDiGetDeviceProperty mit DEVPKEY_Device_HardwareIds aufrufen und dann die resultierende Hardware-ID für die VID und PID eingeben.

Wenn Sie die Geräteschnittstellen absichtlich verwenden, müssen Sie SetupDiGetDeviceInterfaceDetail einmal mit einem NULL-Parameter PSP_DEVICE_INTERFACE_DETAIL und einem gültigen requiredSize-Zeiger aufrufen, um die erforderliche Speichergröße zu erhalten, diesen Speicher zuzuordnen und die Funktion dann erneut aufzurufen . In diesem Aufruf ist der letzte Parameter eine SP_DEVINFO_DATA-Struktur, die einmal abgerufen wurde, die Sie im Aufruf von SetupDiGetDeviceProperty verwenden können, wie oben erwähnt.

0

Eine Alternative besteht darin, die HardwareID zu erhalten, die die VID und PID enthält.

Anruf SetupDiGetDeviceRegistryProperty mit SPDRP_HARDWAREID wie so:

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

Dies gibt Ihnen eine Zeichenfolge wie USB\ROOT_HUB20&VID1002&PID4396&REV0000, die Sie analysieren können.

* Hinweis: Nicht alle Geräte verfügen über eine VID und PID, z. B. Nicht-USB-Geräte.