HIDHuman Interface Device)是面向键盘、鼠标、触控板、游戏手柄、遥控器、扫描枪和控制面板等人机输入/控制设备的一类设备模型和协议体系。

工程上说 HID,通常不是泛指“所有能给人用的设备”,而是指主机能通过标准 HID 类驱动理解的一套设备描述、数据报告和用途语义。常见承载方式有 USB HID、Bluetooth Classic HID 和 HOGP(HID over GATT Profile)

核心问题

如果每个键盘、鼠标、手柄或扫描枪都要求操作系统安装厂商专用驱动,外设生态会非常脆弱。主机需要一种通用机制来回答:

  • 这个设备是键盘、鼠标、手柄,还是厂商自定义控制器?
  • 它会上报哪些输入字段,例如按键、坐标、滚轮、触点、摇杆轴?
  • 每个字段在字节流中的偏移、长度、单位和含义是什么?
  • 哪些数据是设备发给主机,哪些是主机发给设备?

HID 解决的是“设备如何自描述自己的输入/输出数据格式,让通用主机驱动不用为每个厂商重写”的问题。

核心对象

对象含义工程关注点
HID device真实外设或嵌入式设备中的 HID 接口键盘、鼠标、手柄、扫描枪、自定义控制板
HID host读取并解释 HID 数据的一方PC、手机、平板、主控系统、操作系统 HID 栈
HID Report Descriptor描述 report 字节布局和语义的结构usage、collection、report size/count、input/output/feature
Input report设备上报给主机的数据按键状态、鼠标位移、触点坐标、手柄轴值
Output report主机下发给设备的数据键盘 LED、震动马达、指示灯、简单控制
Feature report配置或状态类双向数据校准、模式、厂商自定义配置
Usage Page / Usage字段所属用途和具体含义键盘按键、鼠标按钮、X/Y 轴、Consumer Control
Report ID区分同一接口内多种 report多报告设备必须解析 ID 与长度
Transport承载 HID report 的链路USB、Bluetooth Classic、BLE GATT、I2C 等

HID 的关键思想是:设备不只发“字节”,还要先告诉主机这些字节如何解释。

核心机制

1. 设备先暴露描述信息

以 USB HID 为例,主机枚举设备时会读取设备、配置、接口、HID 类描述符和 report descriptor。report descriptor 告诉主机后续 report 的结构。流程可以简化为:

device connected
  -> host enumerates interface
  -> host reads HID descriptor
  -> host reads report descriptor
  -> host parses usages and report layout
  -> device and host exchange reports

Bluetooth HID 的承载方式不同,但也需要让主机知道设备支持的 HID service、report map 和 report 数据含义。

2. report 是运行时真正交换的数据

一个 HID 鼠标 input report 可以近似理解为:

byte 0: buttons bitmask
byte 1: dx
byte 2: dy
byte 3: wheel

这里 buttons bitmask 是多个按钮状态压缩成的位字段,dxdy 通常表示相对位移,不是屏幕绝对坐标;wheel 是滚轮增量。主机能正确解析这些字段,是因为 report descriptor 事先描述了字段长度、顺序、用途和取值范围。

3. Usage Page 和 Usage 给字段赋语义

HID 不只关心字段有几个 bit,还关心这些 bit 代表什么。可以把字段语义写成:

field_meaning = usage_page + usage + logical_range + report_offset
  • usage_page 是用途大类,例如 Generic Desktop、Keyboard/Keypad、Button、Consumer。
  • usage 是大类下的具体用途,例如 X、Y、Mouse、Keyboard a/A、Volume Up。
  • logical_range 描述上报值的逻辑范围,例如按钮是 0/1,轴值可能是 -127 到 127。
  • report_offset 是字段在 report 字节流中的位置。

这个表达式不是协议里的单个字段,而是解释主机如何把“某几个 bit”变成“鼠标 X 位移”或“音量加键”的工程模型。

4. HID 类驱动把 report 转成操作系统事件

运行时路径通常是:

physical action
  -> device firmware builds HID report
  -> transport sends report
  -> OS HID class driver parses report
  -> input subsystem produces key/mouse/gamepad event
  -> application receives event

对应用来说,它通常不直接读原始 HID 字节,而是通过操作系统输入事件、Raw Input、evdev、IOKit、hidraw 或游戏控制器 API 获取结果。只有调试自定义 HID、产测工具或嵌入式主机场景,才经常直接处理 HID report。

工程用途

  • 免驱外设:键盘、鼠标、触控板、手柄、扫描枪等用通用 HID 类驱动接入主机。
  • 嵌入式控制器:把旋钮、按钮、脚踏、遥控器或工控面板模拟成标准输入设备。
  • 厂商自定义通信:用 Vendor-defined Usage Page 做少量控制或配置,获得免驱优势。
  • BLE 输入设备:通过 HOGP(HID over GATT Profile) 实现低功耗键盘、遥控器、鼠标。
  • 测试和产线工具:用 HID feature/output report 读写简单配置或执行设备测试命令。

观察 HID 问题时,重点看枚举是否成功、report descriptor 是否能被主机解析、report 长度是否一致、Report ID 是否匹配、轮询/连接间隔是否满足延迟、权限是否允许应用访问 hidraw,以及操作系统是否把设备绑定到预期类驱动。

边界与常见坑

  • HID 不等于 USB:USB 只是最常见承载方式之一;HID 也可以跑在 Bluetooth、BLE GATT、I2C 等链路上。
  • HID 不等于键鼠:键鼠是典型 HID,但游戏手柄、触控屏、扫描枪、Consumer Control、厂商自定义控制器也可以是 HID。
  • 自定义 HID 不等于主机自动懂业务语义:免驱只说明类驱动能收发 report;应用仍要按 report descriptor 或约定解释厂商自定义字段。
  • report descriptor 错一点就会全局错:字段长度、Report ID、usage、padding 或 logical range 写错,会导致主机解析错位。
  • Boot Protocol 只覆盖简化键盘/鼠标:BIOS/UEFI 启动阶段可能只支持简单键鼠,不支持复杂自定义 report。
  • Output report 不是可靠控制总线:HID 适合低速控制和输入,不适合大吞吐流式数据。
  • 安全边界不能忽略:HID 键盘可以注入按键,USB/Bluetooth 配对、物理接入和主机授权必须纳入威胁模型。
  • 车灯语境的 HID 是另一件事:汽车照明里 HID 常指 High Intensity Discharge,高强度气体放电灯,不是 Human Interface Device。

相关术语

外部参考