2012-05-14 26 views
5

有人可以看到,如果我這樣做的權利,請:我SetupDiEnumDeviceInterfaces不工作

//DeviceManager.h 
#include <windows.h> 
//#include <hidsdi.h> 
#include <setupapi.h> 
#include <iostream> 
#include <cfgmgr32.h> 
#include <tchar.h> 
#include <devpkey.h> 

extern "C"{ 
    #include <hidsdi.h> 
} 

//#pragma comment (lib, "setupapi.lib") 

class DeviceManager 
{ 
public: 
    DeviceManager(); 
    ~DeviceManager(); 

    void ListAllDevices(); 
    void GetDevice(std::string vid, std::string pid); 

    HANDLE PSMove; 
    byte reportBuffer; 
private: 
    HDEVINFO deviceInfoSet;    //A list of all the devices 
    SP_DEVINFO_DATA deviceInfoData;  //A device from deviceInfoSet 

    SP_DEVICE_INTERFACE_DATA deviceInterfaceData; 
    SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailedData; 

}; 

//DeviceManager.cpp 
#include"DeviceManager.h" 

DeviceManager::DeviceManager() 
{ 
    deviceInfoSet = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); //Gets all Devices 
} 

DeviceManager::~DeviceManager() 
{ 
} 

void DeviceManager::ListAllDevices() 
{ 
    DWORD deviceIndex = 0; 

    deviceInfoData.cbSize = sizeof(deviceInfoData); 

    while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData)) 
    { 
     deviceInfoData.cbSize = sizeof(deviceInfoData); 

     ULONG tcharSize; 
     CM_Get_Device_ID_Size(&tcharSize, deviceInfoData.DevInst, 0); 
     TCHAR* deviceIDBuffer = new TCHAR[tcharSize]; //the device ID will be stored in this array, so the tcharSize needs to be big enough to hold all the info. 
                 //Or we can use MAX_DEVICE_ID_LEN, which is 200 

     CM_Get_Device_ID(deviceInfoData.DevInst, deviceIDBuffer, MAX_PATH, 0); //gets the devices ID - a long string that looks like a file path. 

     /* 
     //SetupDiGetDevicePropertyKeys(deviceInfoSet, &deviceInfoData, &devicePropertyKey, NULL, 0, 0); 
     if(deviceIDBuffer[8]=='8' && deviceIDBuffer[9]=='8' && deviceIDBuffer[10]=='8' && deviceIDBuffer[11]=='8' && //VID 
      deviceIDBuffer[17]=='0' && deviceIDBuffer[18]=='3' && deviceIDBuffer[19]=='0' && deviceIDBuffer[20]=='8') //PID 
     { 
      std::cout << deviceIDBuffer << "\t<-- Playstation Move" << std::endl; 
     } 
     else 
     { 
      std::cout << deviceIDBuffer << std::endl; 
     }*/ 

     std::cout << deviceIDBuffer << std::endl; 

     deviceIndex++; 
    } 
} 

void DeviceManager::GetDevice(std::string vid, std::string pid) 
{ 

    DWORD deviceIndex = 0; 
    deviceInfoData.cbSize = sizeof(deviceInfoData); 

    while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData)) 
    { 
     deviceInfoData.cbSize = sizeof(deviceInfoData); 

     ULONG IDSize; 
     CM_Get_Device_ID_Size(&IDSize, deviceInfoData.DevInst, 0); 

     TCHAR* deviceID = new TCHAR[IDSize]; 

     CM_Get_Device_ID(deviceInfoData.DevInst, deviceID, MAX_PATH, 0); 

     if(deviceID[8]==vid.at(0) && deviceID[9]==vid.at(1) && deviceID[10]==vid.at(2) && deviceID[11]==vid.at(3) && //VID 
      deviceID[17]==pid.at(0) && deviceID[18]==pid.at(1) && deviceID[19]==pid.at(2) && deviceID[20]==pid.at(3)) //PID 
     { 
      //DWORD requiredBufferSize; 
      //SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &requiredBufferSize, 


      HDEVINFO deviceInterfaceSet = SetupDiGetClassDevs(&deviceInfoData.ClassGuid, NULL, NULL, DIGCF_ALLCLASSES); 

      DWORD deviceInterfaceIndex = 0; 
      deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 
      while(SetupDiEnumDeviceInterfaces(deviceInterfaceSet, NULL, &deviceInterfaceData.InterfaceClassGuid, deviceInterfaceIndex, &deviceInterfaceData)) 
      { 
       deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 
       std::cout << deviceInterfaceIndex << std::endl; 

       deviceInterfaceIndex++; 
      } 

      //std::cout << deviceInterfaceData.cbSize << std::endl; 

      break; 
     } 

     deviceIndex++; 
    } 
} 

我SetupDiEnumDeviceInterfaces(在的getDevice()函數)沒有做任何事情。它甚至沒有進入while循環...有人可以請嘗試指出我做錯了什麼嗎?

感謝

編輯/更多信息:我剛剛叫GetLastError()函數,它返回一個259 - ERROR_NO_MORE_ITEMS。設備是否可能不包含接口?

+2

'SetupDiEnumDeviceInfo'返回false然後。查看文檔以確定這可能是什麼,然後使用您的調試器。如果你仍然無法弄清楚,那就問一個更具體的問題,那就是你被困在哪裏了。 – AJG85

+0

那麼請問如果deviceInfoData.ClassGuid傳遞正確了嗎?我的意思是,我願意通過該GUID獲取deviceInterfaceSet?或者我願意通過一個不同的GUID? – Danny

+1

如果你永遠不會進入while循環,那麼你永遠不會進入那行代碼,這意味着你正在使用在構造函數中分配的'deviceInfoSet'。提示:使用具有'GetLastError'的'FormatMessage'來確定在調用'SetupDiEnumDeviceInfo'之後出了什麼問題。這可能僅僅是因爲系統中沒有可用的活動USB設備。 – AJG85

回答

7

一起去吧。


我試圖儘可能少地破解你的原代碼;下面的代碼(至少對我來說)打通內while(SetupDiEnumDeviceInterfaces..)

void DeviceManager::GetDeviceUSB(std::string vid, std::string pid) 
{ 
    DWORD deviceIndex = 0; 
    deviceInfoData.cbSize = sizeof(deviceInfoData); 

    //buried somewhere deep in the ddk 
    static GUID GUID_DEVINTERFACE_USB_HUB={ 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} }; 
    static GUID GUID_DEVINTERFACE_USB_DEVICE ={ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; 
    static GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER={ 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27}}; 

    //get usb device interfaces 
    HDEVINFO deviceInterfaceSet=SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_DEVICEINTERFACE); 


    while(SetupDiEnumDeviceInfo(deviceInterfaceSet, deviceIndex, &deviceInfoData)) 
    { 
     deviceInfoData.cbSize = sizeof(deviceInfoData); 

     ULONG IDSize; 
     CM_Get_Device_ID_Size(&IDSize, deviceInfoData.DevInst, 0); 

     TCHAR* deviceID = new TCHAR[IDSize]; 

     CM_Get_Device_ID(deviceInfoData.DevInst, deviceID, MAX_PATH, 0); 

     if(deviceID[8]==vid.at(0) && deviceID[9]==vid.at(1) && deviceID[10]==vid.at(2) && deviceID[11]==vid.at(3) && //VID 
      deviceID[17]==pid.at(0) && deviceID[18]==pid.at(1) && deviceID[19]==pid.at(2) && deviceID[20]==pid.at(3)) //PID 
     { 
      DWORD deviceInterfaceIndex = 0; 
      deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 

      while(SetupDiEnumDeviceInterfaces(deviceInterfaceSet, &deviceInfoData, &GUID_DEVINTERFACE_USB_DEVICE, deviceInterfaceIndex, &deviceInterfaceData)) 
      { 
       deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); 
       std::cout << deviceInterfaceIndex << std::endl; 

       //get some more details etc 
       //DWORD requiredBufferSize; 
       //SetupDiGetDeviceInterfaceDetail(deviceInterfaceSet, &deviceInterfaceData, NULL, 0, &requiredBufferSize, 

       deviceInterfaceIndex++; 
      } 
     } 

     deviceIndex++; 
    } 
} 



據我所知,這種方法拿起相同的設備與您的OP構造函數調用:
(注:我包括其他一些有用的接口的GUID)

deviceInfoSet = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); //Gets all Devices 


,但我這樣做是爲了讓設備接口

// /coughs/ you might want to put back the DIGCF_PRESENT flag i removed for testing 
HDEVINFO deviceInterfaceSet=SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_DEVICEINTERFACE); 


我也通過deviceInfoDataSetupDiEnumDeviceInterfaces根據文件的時間:

一個指向SP_DEVINFO_DATA結構,其在DeviceInfoSet中指定設備 信息元素。該參數是可選的,並且 可以是NULL。如果指定此參數,則SetupDiEnumDeviceInterfaces將枚舉限制爲指定設備支持的接口 。如果這個 參數爲NULL,以SetupDiEnumDeviceInterfaces千呼萬喚 返回有關與在DeviceInfoSet所有 設備信息元素相關聯接口的信息。這個指針通常是由SetupDiEnumDeviceInfo返回的 。



    [編輯:附加註釋(如請求;)]


你的USB設備具有相關聯的 設置 接口類(ES):

來自device setup classes documentation

設備設置類定義中涉及的安裝設備

device interface classes documentation類別安裝程序和類共同安裝:

設備接口類是一方式向其他系統組件(包括其他驅動程序)導出設備和驅動程序功能,如 以及用戶模式應用程序


Also, see this handy comparison
Also, this related doc is useful


所以:

deviceInfoSet = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL,DIGCF_PRESENT|DIGCF_ALLCLASSES); 

這是檢索所有設置類信息集和過濾的 「USB」


做到這一點:

deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES|DIGCF_DEVICEINTERFACE);` 

此檢索類別信息設置該支持設備接口的任何設備。 (應用的emumerator ID S/A 「USB」 似乎也沒有影響) 最重要的是但是:The function adds to the device information set a device information element that represents such a device and then adds to the device information element a device interface list that contains all the device interfaces that the device supports.


及注意事項:SP_DEVINFO_DATA.ClassGuid總是設備的設置的GUID類)


據我所知:
但你當時還需要提供一個InterfaceClassGuid WH恩調用SetupDiEnumDeviceInterfaces() 〜TBH,我真的不明白,爲什麼在調用者提供可選的DeviceInfoData 這將是必要的,但因爲它的所有閉源的,我怎麼會知道!?:)


&這裏是info regarding GUID_DEVINTERFACE_USB_DEVICE


(;免責聲明:我不爲M $的工作;做治療上述相關信息以懷疑:)當然dyoRs的& &)



希望這會有所幫助,祝你好運!

+0

的作品,這正是我需要的!非常感謝:D。如果你不介意,我還可以請你解釋一下你在頂部聲明的GUID?爲什麼我在使用TEXT(「USB」)時需要它們?有什麼不同?或者你能否至少爲我提供一個鏈接,我可以查找關於你聲明的GUID的更多信息?謝謝:D – Danny

+0

noP,看修訂後的答案,, btw大聲笑,我*不是[很多](http://hyperboleandahalf.blogspot.co.uk/2010/04/alot-is-better-than-you-at -everything.html)XD – violet313

+1

我希望我能夠不止一次地投票。你必須付出很多努力才能解決這個問題。我有更多的信息需要添加,經過了一整天的尋找:如果你的設備是WinUSB設備,那麼你傳遞給'SetupDiEnumDeviceInterfaces()'的GUID將是來自注冊表的「DeviceInterfaceGUIDs」值/ inf文件。我非常懷疑這是記錄在任何地方。 –

3

該問題從如何調用SetupDiGetClassDevs開始。

如果你希望得到一個設備路徑,使用 SetupDiGetClassDevs(& GUID_DEVINTERFACE_USB_DEVICE ,,,)

SetupDiEnumDeviceInterfaces失敗,錯誤259,如果SetupDiGetClassDevs給出了錯誤的GUID在 ClassGuid其中MS幫助說是 指向設備設置類或設備接口類的GUID的指針。

包含文件devguid.h包含一組GUID_DEVCLASS值。這些是不是與GUID_DEVINTERFACE_ *值相同,這是您需要的值。

使用#include <uuids.h>其中包含ksuuids.h,您將在其中找到GUID_DEVINTERFACE_ *值。

在我的網站上有一個更詳細的解釋,有一些源代碼應該有助於正確枚舉USB設備。

請參閱http://pixcl.com/SetupDiEnumInterfaces_Fail.htm