HID Report Descriptor(HID 报告描述符)是 HID 设备用来描述 report 字节布局、字段用途、取值范围和集合结构的自描述数据结构。

它是 HID 的机制核心:设备运行时发给主机的是 input/output/feature report 字节,而 report descriptor 告诉主机这些字节中每一位、每个字段应该如何解释。

核心问题

键盘、鼠标、触控板、游戏手柄和厂商自定义控制器的输入形态差异很大。主机不能只按固定结构解析所有设备,否则每增加一种设备就要新增驱动。

HID Report Descriptor 解决的是“设备如何在连接时声明自己未来会发送或接收什么格式的数据”的问题。它让通用 HID 类驱动能跳过未知字段、解析已知 usage,并把 report 转成系统输入事件或暴露给应用。

核心对象

对象含义工程关注点
Usage Page字段或集合所属用途大类Generic Desktop、Button、Keyboard、Consumer、Vendor-defined
Usage具体用途X、Y、Mouse、Keyboard A、Volume Up
Collection一组相关字段的逻辑分组Application、Physical、Logical
Report Size单个字段占多少 bit和字节对齐、padding 密切相关
Report Count连续字段数量多按钮、多轴、多触点常用
Logical Minimum / Maximum字段逻辑取值范围有符号/无符号、轴范围、按钮 0/1
Physical Minimum / Maximum字段物理量范围,可选单位换算、真实量纲
Input / Output / Feature声明字段方向和属性主机读取、主机写入、配置状态
Report ID同一接口中区分多种 report多 report 设备必须处理

可以把一个字段的定义理解为:

field = usage + bit_layout + value_range + direction
  • usage 给字段语义。
  • bit_layout 由 Report Size、Report Count 和字段顺序决定。
  • value_range 由 Logical/Physical Minimum/Maximum 决定。
  • direction 由 Input、Output 或 Feature 决定。

核心机制

1. descriptor 是一串 item,不是普通 JSON

HID Report Descriptor 是紧凑的二进制 item 序列。每个 item 可能设置全局状态、局部 usage,或声明一个主项目。主机解析时维护一个当前上下文:

set Usage Page
set Usage
set Logical Min/Max
set Report Size
set Report Count
declare Input / Output / Feature

声明 Input/Output/Feature 时,当前上下文会被用于生成一个或多个字段。后续 item 可以改变上下文,再声明下一组字段。

2. 主机用 descriptor 解析 runtime report

运行时关系是:

report_descriptor -> parser builds field table
runtime_report_bytes -> parser slices bits -> typed HID fields

例如 descriptor 声明了 3 个按钮 bit、5 个 padding bit、两个 8-bit 相对坐标轴,那么主机就会按这个布局切分每个 input report。如果固件实际发送的字节顺序和 descriptor 不一致,主机不会自动纠正,只会按 descriptor 错误解析。

3. Report ID 让一个接口承载多种 report

如果设备有多种 report,例如键盘 report、媒体键 report 和厂商 feature report,可以使用 Report ID。运行时 report 的第一个字节通常是 ID:

report = report_id || payload

这里 || 表示字节拼接,不是逻辑或。report_id 告诉主机后面的 payload 应按哪一套字段表解析。没有使用 Report ID 的简单设备通常直接发送 payload。

4. Usage 决定主机是否能映射成标准输入事件

如果字段使用标准 Usage Page 和 Usage,主机更容易把它映射成键盘、鼠标、手柄或媒体键事件。如果使用 Vendor-defined Usage Page,主机仍可搬运 report,但通常不会自动生成标准输入事件,需要专用应用解释。

工程用途

  • 定义标准输入设备:键盘、鼠标、手柄、触控板等。
  • 定义自定义控制器:用 Vendor-defined Usage Page 暴露自定义命令和状态。
  • 跨平台免驱:让不同操作系统通用 HID 栈能理解 report 布局。
  • 调试 HID 设备:确认 report 长度、Report ID、usage、padding 和 logical range 是否匹配固件。
  • 生成工具支持:用 descriptor composer 或解析器减少手写二进制描述符错误。

边界与常见坑

  • report descriptor 不是 runtime report:前者描述格式,后者是运行时实际数据。
  • Report Size 以 bit 为单位:不是字节;padding 少算或多算会让后续字段错位。
  • Logical range 影响符号解释-127..1270..255 都可能占 8 bit,但语义完全不同。
  • Usage 写错会导致系统映射异常:例如鼠标 X/Y、滚轮、按钮或媒体键 usage 错,会让主机产生错误事件。
  • Report ID 会改变 report 长度:启用 Report ID 后,运行时数据通常多一个 ID 字节。
  • Vendor-defined 不是万能免驱协议:它只让主机能访问 HID report,不保证系统或应用知道业务命令。
  • descriptor 能被解析不代表设备行为正确:固件还必须按同一布局发送长度、时序和取值都正确的 report。

相关术语

外部参考