读取 USB HID 功能报告

Reading a USB HID feature report

我想从 USB 设备读取 HID 功能报告,我有 VendorIDDeviceID,并且可以保证只有一台设备符合该描述。

这个应该不难,但是看了MSDN文档感觉很迷茫。

我在几个小时内就在 linux 上运行了,感谢 libudev :)。但我需要一个原生 windows 实现(最好是 VC++,并且可能使用 Hidsdi.h 和/或 Setupapi.h)

谁能给我指出正确的方向。

它与本机 windows 库一起使用,它可能不是完成此任务的正确方法,但它有效。我建议不要直接使用这段代码,因为它很糟糕,但请随意阅读它以获取任何有用的信息。

找到设备 ID 为 0021 且供应商 ID 为 2833 的 HID 然后读取功能报告 0x0F;

#include <Windows.h>
#include <iostream>
#include <Setupapi.h>
#include <Hidsdi.h>

using namespace std;

// returns true if full_string contains the substring
BOOL findSubstring(WCHAR *full_string, const char *substring){
    unsigned int c = 0, d = 0;
    while (true) {
        if (substring[d] == '[=10=]')
            return true;
        if (full_string[c] == '[=10=]')
            return false;
        d = (full_string[c] == substring[d]) ? d + 1 : 0;
        if (c++ > MAX_PATH)
            return false;
    }
}

int main()
{
    GUID guid;
    HDEVINFO hDeviceInfo;
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail;
    DWORD i = 0;
    WCHAR *devicePath = NULL;

    // Obtain a handle to the connected HID devices
    HidD_GetHidGuid(&guid);
    hDeviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (hDeviceInfo == INVALID_HANDLE_VALUE) {
        cerr << "Failed to get Device Handle" << endl;
        return 1;
    }

    i = 0;
    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    // Enumerate through all the HID devices
    while (SetupDiEnumDeviceInterfaces(hDeviceInfo, NULL, &guid, i++, &deviceInterfaceData)) {
        ULONG requiredSize;

        // Get the details with null values to get the required size of the buffer
        SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, NULL, 0, &requiredSize, 0);

        deviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(requiredSize);
        deviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

        // Fill the buffer with the device details
        if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &deviceInterfaceData, deviceDetail, requiredSize, &requiredSize, NULL)) {
            cerr << "Could not obtain the HID device for some reason" << endl;
            SetupDiDestroyDeviceInfoList(hDeviceInfo);
            free(deviceDetail);
            return 1;
        }

        // Check that the device path contains two strings, which are our vendorID and pathID.
        if (findSubstring(deviceDetail->DevicePath, "vid_2833") && findSubstring(deviceDetail->DevicePath, "pid_0021")) {
            devicePath = deviceDetail->DevicePath;
        }
    }

    if (devicePath != NULL) {
        // Open the HID
        HANDLE HIDfile = CreateFile(devicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        DWORD err = GetLastError();
        if (err != 0) {
            cerr << "unable to obtain read permissions for the HID device, error: " << err << endl;
        } else {

            // Allocate buffer for the feature report
            BYTE buffer[30];
            memset(buffer, 0, sizeof(buffer[0]));
            buffer[0] = 0x0FU; // Feature report 0x0F

            if (!HidD_GetFeature(HIDfile, buffer, sizeof(buffer))){
                cout << "Feature report failed" << endl;
            }
            else {
                cout << "Feature report successful" << endl;
                for (int i = 0; i < 30; i++)
                    cout << hex << (int)buffer[i];
            }
            cout << endl;
        }

    }
    // probably small memory leak
    // free(deviceDetail);
    SetupDiDestroyDeviceInfoList(hDeviceInfo);
    return 0;
}