简体   繁体   English

阅读USB HID功能报告

[英]Reading a USB HID feature report

I want to read a HID feature report from a USB device, I have the VendorID and the DeviceID , and it's guaranteed that there will be only one device matching that description. 我想从USB设备读取HID功能报告,我有VendorIDDeviceID ,并且可以保证只有一个与该描述匹配的设备。

This shouldn't be difficult, but I feel so confused reading the MSDN documentation. 这应该并不困难,但是我很困惑阅读MSDN文档。

I got it working on linux in a couple hours, thanks to libudev :). 感谢libudev :),我在几个小时内就可以在linux上工作了。 But I need a native windows implementation (preferably VC++, and likely using Hidsdi.h and or Setupapi.h) 但是我需要一个本机Windows实现(最好是VC ++,并且可能使用Hidsdi.h和/或Setupapi.h)

Can anyone please point me in the right direction. 谁能给我指出正确的方向。

Got it working with native windows libraries, it's probably not the right way to accomplish this task, but it works. 可以与本机Windows库一起使用,这可能不是完成此任务的正确方法,但它可以工作。 I'd advice against using this code directly, since it's terrible, but feel free to read it for anything useful. 我建议不要直接使用此代码,因为它很糟糕,但是请随时阅读以获取有用的信息。

It finds the HID with device ID: 0021 and vendor ID: 2833 then reads the feature report 0x0F; 它找到设备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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM