2010-05-29 28 views
6

Tôi đang sử dụng Qt trên nền tảng cửa sổ.cách nhận id nhà cung cấp và id sản phẩm của thiết bị cắm USB trên các cửa sổ

tôi muốn nhận và hiển thị id nhà cung cấp và id sản phẩm của thiết bị USB được cắm từ hệ thống cục bộ của tôi.

Dưới đây là mã nguồn đầy đủ của tôi để lấy id nhà cung cấp và id sản phẩm từ thiết bị USB.

khi tôi chạy ứng dụng qt của mình, nó không phát sinh bất kỳ lỗi nào.

vì vậy tôi cắm thiết bị USB vào hệ thống.

nhưng tuyên bố trên báo của tôi hiển thị kết quả như sau

qDebug()<<pDetData->DevicePath;

tôi nhận được kết quả như 0x4

Cho dù tôi có bất kỳ sai lầm thực hiện trong mã nguồn của tôi?

nếu vậy hãy hướng dẫn tôi những gì tôi đang làm sai ..

Tôi có bỏ lỡ bất kỳ chức năng nào khác không?

Có thể lấy id nhà cung cấp và id sản phẩm từ thiết bị USB dựa trên mã nguồn của tôi hay không (thực hiện mã của tôi)?

vui lòng tìm mã nguồn của tôi dưới đây

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 thêm: ------------- ----

Hi ... các ứng dụng đi kèm và in này

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

một lần nữa nó đi tới, trong khi vòng lặp .... đây nó được breaked trong báo cáo khác ...

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

Mọi ý tưởng trong này ....

+0

Bạn sẽ cần phải định dạng bức tường mã này tốt hơn nếu bạn muốn bất kỳ ai đọc mã đó. –

+0

tôi định dạng lại mã ... – egrunin

+2

tôi sao chép bình luận của bạn cho câu trả lời của tôi (dưới đây) và nối nó với câu hỏi của bạn (nơi nó thuộc về) – egrunin

Trả lời

8

Sau dòng này:

SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL; 

Thêm này:

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

Sau dòng này:

qDebug()<<pDetData->DevicePath; 

Thêm này:

free(pDetData); 

Nhưng cuối cùng bạn sẽ phải đọc tài liệu cho SetupDiGetDeviceInterfaceDetail(). Làm điều đó, có rất nhiều chức năng hoạt động như thế này, với các con trỏ tới các cấu trúc có kích thước biến đổi.

-------- Edited thêm: --------

Bạn đang thực sự xảy ra về vấn đề này một cách sai lầm. Tôi thấy bạn đang theo dõi lời khuyên bạn đã nhận được here và nó đưa bạn xuống con đường sai. idVendoridProduct chỉ có thể được tìm thấy trong USB_DEVICE_DESCRIPTOR (MSDN).

Có vẻ như bạn đã biết cách xử lý thiết bị (sử dụng CreateFile()). Sau đó, bạn gọi số WinUsb_Initialize() (MSDN). Điều đó giúp bạn có được một số WINUSB_INTERFACE_HANDLE.

Khi bạn có tay cầm đó, bạn muốn gọi WinUsb_GetDescriptor() (MSDN), với DescriptorType được đặt thành URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE. Tôi không thể kiểm tra mã bây giờ, nhưng nó sẽ giống như thế này:

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

Sau đó, udd->idVendorudd->idProduct nên có những gì bạn muốn.

Microsoft đã sử dụng để cung cấp mã mẫu cho tất cả điều này trong DDK và có thể vẫn còn, nhưng tôi không có quyền truy cập vào một.

---------- Edited thêm: ----------

Daniel K viết rằng mã thực sự cần là:

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

Xem nhận xét để biết thêm chi tiết.

+0

Hi ... các ứng dụng đi kèm và in này "\\? \ usb # vid_04f2 & pid_0111 # 5 & 1ba5a77f & 0 & 2 # {a5dcbf1 0-6530-11d2-901f-00c04fb951ed}" một lần nữa nó đi tới, trong khi vòng lặp .... đây nó được breaked trong báo cáo khác ... Qt Code: if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // Thay đổi kích thước bộ đệm. nếu (bộ đệm) LocalFree (bộ đệm); buffer = (LPTSTR) LocalAlloc (LPTR, đệm); } else { qDebug() << "Ở đây, thoát ứng dụng"; // Chèn xử lý lỗi tại đây. ngắt; } Bất kỳ ý tưởng nào trong số này .... – user198725878

+0

+1 cho điều này, nhưng tôi khuyên bạn nên 'std :: vector ' cho mã C++ thay vì sử dụng 'malloc' theo cách thủ công. –

+0

@Billy ONeal: ý tưởng hay. – egrunin

0

Bạn đang liệt kê "giao diện" của thiết bị. Giao diện không có một VID hoặc PID - trường hợp thiết bị làm. Tôi không chắc liệu bạn đang liệt kê các giao diện để thu hẹp các thiết bị mà bạn quan tâm, bởi vì đó là một lỗi.

Nếu bạn chỉ liệt kê các phiên bản thiết bị, bạn có thể gọi SetupDiGetDeviceProperty với DEVPKEY_Device_HardwareIds và sau đó grep id phần cứng kết quả cho VID và PID.

Nếu bạn đang sử dụng giao diện thiết bị, bạn cần gọi SetupDiGetDeviceInterfaceDetail một lần với tham số NULL_D_DICICE_INTERFACE_DETAIL và một con trỏ yêu cầu hợp lệ để nhận kích thước bộ nhớ cần thiết để cấp phát, cấp phát bộ nhớ đó và sau đó gọi lại hàm . Trong cuộc gọi đó, tham số cuối cùng là cấu trúc SP_DEVINFO_DATA, khi đã truy xuất, bạn có thể sử dụng trong lệnh gọi tới SetupDiGetDeviceProperty như tôi đã đề cập ở trên.

0

Cách khác là lấy phần cứngID bao gồm VID và PID.

Gọi SetupDiGetDeviceRegistryProperty với SPDRP_HARDWAREID như vậy:

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

này sẽ cung cấp cho bạn một chuỗi như USB\ROOT_HUB20&VID1002&PID4396&REV0000 mà bạn có thể phân tích cú pháp.

* Lưu ý: không phải tất cả các thiết bị đều có VID và PID, chẳng hạn như thiết bị không phải USB.

Các vấn đề liên quan