获取 HID 设备的功能报告描述符的本机方法?

san*_*iso 4 windows usb hid

我们有一些与内部研发工具通信的HID 设备(触摸数字化仪)。该工具解析来自设备的原始功能报告,以绘制触摸报告以及原始功能报告中存在但被 Windows 7 的 HID 驱动程序过滤掉的一些附加数据(例如,消息中不存在压力数据WM_TOUCH)。

然而,我们已经开始使用一些可能具有不同固件变体的设备,因此它们不共享相同的字段顺序或字节长度,我需要修改我们的研发工具,以便它能够透明地适应所有设备。

这些设备来自同一制造商(我们自己)并共享相同的设备信息,因此不能使用这些字段来区分不同的固件。我想要做的是获取设备发送的HID 功能报告描述符,并根据此信息动态更新我们的功能报告解析方法。

但是,在浏览 Windows API 时,我没有找到正确的调用方法来获取此描述符。到目前为止我发现的是MSDN 上的原始输入页面,但我不知道下一步该怎么做。我可以在RID_DEVICE_HID结构中找到所需的信息吗?或者我需要调用一个完全不同的 API 吗?

在此先感谢您的帮助!

san*_*iso 5

好吧,我终于得到了一些(几乎完全)可用的东西。正如mcoill推断的那样,我使用了该HidP_xxx()函数系列,但它首先需要一些数据准备。

我的解决方案基于此针对USB 操纵杆的示例代码,并将其改编为触摸数字化仪设备。如果其他人也对在线文档感到困惑,以下是该过程中涉及的所需步骤:

  1. 在启动时为原始输入设备注册应用程序。这是通过调用函数 来完成的RegisterRawInputDevice(&Rid, 1, sizeof(Rid)),其中Rid是 设置了以下属性的 a RAWINPUTDEVICE(为了获得触摸数字转换器):

    Rid.usUsage = 0x04;
    Rid.usUsagePage = 0x0d;
    Rid.dwFlags = RIDEV_INPUT_SINK;
    
    Run Code Online (Sandbox Code Playgroud)
  2. OnInput(LPARAM lParam)注册事件回调WM_INPUT,因为Rid设备将生成此类事件;

  3. OnInput(LPARAM lParam)方法将分两步从该事件中获取数据:

    // Parse the raw input header to read its size.
    UINT bufferSize;
    GetRawInputData(HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));
    
    // Allocate memory for the raw input data and retrieve it
    PRAWINPUT = (PRAWINPUT)HeapAlloc(GetProcessHeap(), 0, bufferSize);
    GetRawInputData(HRAWINPUT)lParam, RID_INPUT, rawInput /* NOT NULL */, &bufferSize, sizeof(RAWINPUTHEADER));
    
    Run Code Online (Sandbox Code Playgroud)
  4. 然后它调用一个解析方法来创建HIDP_PREPARSED_DATA查找函数所需的结构:

    // Again, read the data size, allocate then retrieve
    GetRawInputDeviceInfo(rawInput->header.hDevice, RIDI_PREPARSEDDATA, NULL, &bufferSize);
    PHIDP_PREPARSED_DATA preparsedData = (PHIDP_PREPARSED_DATA)HeapAlloc(heap, 0, bufferSize);
    GetRawInputDeviceInfo(rawInput->header.hDevice, RIDI_PREPARSEDDATA, preparsedData, &bufferSize);
    
    Run Code Online (Sandbox Code Playgroud)

准备好的数据分为功能

    // Create a structure that will hold the values
    HidP_GetCaps(preparsedData, &caps);
    USHORT capsLength = caps.NumberInputValueCaps;
    PHIDP_VALUE_CAPS valueCaps = (PHIDP_VALUE_CAPS)HeapAlloc(heap, 0, capsLength*sizeof(HIDP_VALUE_CAPS));
    HidP_GetValueCaps(HidP_Input, valueCaps, &capsLength, preparsedData);
Run Code Online (Sandbox Code Playgroud)

可以询问能力的价值:

    // Read sample value
    HidP_GetUsageValue(HidP_Input, valueCaps[i].UsagePage, 0, valueCaps[i].Range.UsageMin, &value, preparsedData, (PCHAR)rawInput->data.hid.bRawData, rawInput->data.hid.dwSizeHid);
Run Code Online (Sandbox Code Playgroud)