读取USB HID功能报告

时间:2015-04-13 18:11:52

标签: windows visual-c++ usb hid

我想从USB设备上读取HID功能报告,我有 VendorID DeviceID ,并且保证只有一个匹配该描述的设备。

这不难,但我在阅读MSDN文档时感到很困惑。

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

任何人都可以指出我正确的方向。

1 个答案:

答案 0 :(得分:1)

使用本机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] == '\0')
            return true;
        if (full_string[c] == '\0')
            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;
}