c++ - 我的 SetupDiEnumDeviceInterfaces 不工作

标签 c++ device hid wdk

我很想知道我这样做是否正确:

//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。设备甚至可能不包含任何接口(interface)吗?

最佳答案

试一试。

我已尝试尽可能少地破解您的原始代码;以下代码(至少对我而言)通过内部 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 构造函数调用相同的设备(注意:我包含了一些其他有用的接口(interface) guid):

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

但我这样做是为了获取设备接口(interface):

// /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 因为根据文档:

A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet. This parameter is optional and can be NULL. If this parameter is specified, SetupDiEnumDeviceInterfaces constrains the enumeration to the interfaces that are supported by the specified device. If this parameter is NULL, repeated calls to SetupDiEnumDeviceInterfaces return information about the interfaces that are associated with all the device information elements in DeviceInfoSet. This pointer is typically returned by SetupDiEnumDeviceInfo.

编辑

根据要求附加说明。您的 USB 设备具有关联的设置接口(interface)类:

来自device setup classes documentation :

The device setup class defines the class installer and class co-installers that are involved in installing the device

来自device interface classes documentation :

A device interface class is a way of exporting device and driver functionality to other system components, including other drivers, as well as user-mode applications

所以:

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

这是在“USB”上检索所有设置类信息集和过滤

可以这样做:

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

这会检索支持任何 类的设备接口(interface) 的设备的类信息集。 (应用仿真器 ID s/a“USB”似乎没有影响)。

然而,至关重要的是:该函数向设备信息集添加一个表示此类设备的设备信息元素,然后向设备信息元素添加一个设备接口(interface)列表,其中包含该设备可以访问的所有设备接口(interface)支持。

(注意: SP_DEVINFO_DATA.ClassGuid 始终设备设置 类)

据我所知,您仍然需要在调用 SetupDiEnumDeviceInterfaces() 时提供 InterfaceClassGuid。老实说,我真的不明白如果调用者提供可选的 DeviceInfoData 为什么有必要这样做,但由于它都是封闭源代码,我怎么知道呢? :)

这里是 info regarding GUID_DEVINTERFACE_USB_DEVICE

免责声明:我不为 M$ 工作;请以怀疑的态度对待上述信息,当然也要进行自己的研究。

关于c++ - 我的 SetupDiEnumDeviceInterfaces 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10587914/

相关文章:

c++ - QT 对话框的样式不正确

c++ - std::make_shared()、std::weak_ptr 和循环引用

c++ - 在 C++ 中索引 linux 命令的输出

android - 尝试在 android 设备上调试我的应用程序时获取 "Launch error: Failed to connect to remote VM. Connection timed out"

iphone - 如何检测 iPhone 5(宽屏设备)?

c# - 阻止来自键盘 HID 的输入

keyboard - 从 USB HID 键盘发送语言布局

usb - HID 设备测试仪

c++ - 如何在Xlib应用程序中等待VSYNC?

ADB 设备在一台计算机上不显示我的设备,但在虚拟计算机上显示