6

私はこれを正しく行っているかどうかを知りたいです:

//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 が返されました。デバイスにインターフェイスが含まれていない可能性さえありますか?

4

2 に答える 2

9

これを試してみてください。

元のコードをできるだけハッキングしないようにしました。次のコードは(少なくとも私にとっては)内部に到達します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); 

deviceInfoDataドキュメントにSetupDiEnumDeviceInterfacesよると、 私もに渡します:

DeviceInfoSet のデバイス情報要素を指定する SP_DEVINFO_DATA 構造体へのポインター。このパラメータはオプションで、NULL にすることができます。このパラメーターが指定されている場合、SetupDiEnumDeviceInterfaces は、指定されたデバイスでサポートされているインターフェイスへの列挙を制限します。このパラメーターが NULL の場合、SetupDiEnumDeviceInterfaces を繰り返し呼び出すと、DeviceInfoSet 内のすべてのデバイス情報要素に関連付けられているインターフェイスに関する情報が返されます。このポインターは通常、SetupDiEnumDeviceInfo によって返されます。

編集

要求に応じて追加のメモ。USB デバイスには、セットアップクラス インターフェイスクラスが関連付けられています。

デバイス セットアップ クラスのドキュメントから:

デバイス セットアップ クラスは、デバイスのインストールに関係するクラス インストーラーとクラス共同インストーラーを定義します。

デバイス インターフェイス クラスのドキュメントから:

デバイス インターフェイス クラスは、デバイスとドライバーの機能を、他のドライバーやユーザー モード アプリケーションを含む他のシステム コンポーネントにエクスポートする方法です。

そう:

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

これは、すべてのセットアップクラス情報セットを取得し、「USB」でフィルタリングしています。

あなたはこれを行うことができます:

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

これにより、任意のクラスのデバイス インターフェイスをサポートするデバイスのクラス情報セットが取得されます。(エミュレータ 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呼び出し時にを提供する必要がありますSetupDiEnumDeviceInterfaces()。正直なところ、呼び出し元がオプションを提供している場合にこれが必要になる理由がよくわかりませんが、DeviceInfoDataすべてクローズドソースであるため、どうすればわかりますか? :)

そして、ここにGUID_DEVINTERFACE_USB_DEVICE に関する情報があります

免責事項: 私は M$ で働いていません。上記の情報を疑って扱い、もちろん独自の調査を行ってください。

于 2012-05-15T00:31:16.763 に答える
4

問題は、SetupDiGetClassDevs の呼び出し方法から始まります。

デバイス パスを取得する場合は、SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE ,,,) を使用します。

SetupDiGetClassDevs に ClassGuid で間違った GUID が与えられた場合、SetupDiEnumDeviceInterfaces はエラー 259 で失敗します。これは、MS ヘルプが言うには 、デバイス セットアップ クラスまたはデバイス インターフェイス クラスの GUID へのポインターです。

インクルード ファイル devguid.h には、一連の GUID_DEVCLASS 値が含まれています。これらは、必要な GUID_DEVINTERFACE_* 値と同じではありません。

GUID_DEVINTERFACE_* 値を見つける ksuuids.h を含む #include <uuids.h> を使用します。

私の Web サイトには、USB デバイスを正しく列挙するのに役立ついくつかのソース コードを含む、より詳細な説明があります。

http://pixcl.com/SetupDiEnumInterfaces_Fail.htmを参照してください。

于 2012-11-30T13:56:39.860 に答える