Report 描述符解析与报告处理

Report 描述符解析与报告处理

1. HID 报告模型

HID descriptor 描述数据的位级布局,而不是固定 C 结构:

1
2
3
4
Report Type
└─ Report ID
└─ Field
└─ Usage(s)

类型:

  • Input:设备到 host;
  • Output:host 到设备;
  • Feature:双向配置状态。

2. Item

短/长 item 按 type 分为:

  • Main:Input/Output/Feature/Collection/End Collection;
  • Global:Usage Page、Logical/Physical Min/Max、Report Size/Count/ID、Unit;
  • Local:Usage、Usage Min/Max、Designator、String、Delimiter。

parser 使用 global stack、local usage list 和 collection stack。

3. 解析链

1
2
3
4
5
6
7
8
hid_open_report()
-> optional driver->report_fixup()
-> hid_parse_report()
-> fetch_item()
-> hid_parser_main/global/local()
-> hid_add_field()
-> hid_register_field()
-> hid_apply_multiplier()

传输在 hid_add_device() 前读取 dev_rdesc;专用驱动可在正式 parse 前修复错误字节。

4. 结构

hid_report 包含 report ID、type、bit size、field array。
hid_field 包含:

  • report offset/size/count;
  • logical/physical min/max;
  • unit/exponent;
  • flags;
  • value array;
  • usages。

hid_usage 保存 HID usage code、collection index、input code/type 映射。

5. 收包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
hid_input_report(type, data, size, interrupt)
-> driver->raw_event() # 可修改/消费原始包
-> hid_report_raw_event()
-> locate report by ID
-> clamp/zero-pad to expected size
-> hidraw copy
-> hid_process_report()
-> extract signed/unsigned bit fields
-> variable/array handling
-> hid_process_event()
-> driver->event()
-> hidinput_hid_event()
-> driver->report()
-> hidinput_report_event()

raw_event 只有负值会中止本次处理;零和正值都会继续进入通用 report 解析。按 usage 调用的 event() 则在返回非零时停止该 usage 的通用 input/hiddev 处理,其中负值还会记录错误。

6. 数组与变量

  • Variable:每个 field element 对应一个 usage/value;
  • Array:value 是 usage selector,如键盘按键数组;
  • Relative:产生相对事件;
  • Absolute:产生绝对坐标;
  • Null state:允许无有效 selector。

键盘数组需比较前后 report,生成 press/release。

7. Report ID

若 descriptor 声明任一 report ID,传输数据首字节通常是 ID。Core 的 report_enum->numbered 控制偏移。编号和非编号 report 混用或长度错误是常见固件问题。

8. 输出编码

1
2
3
4
5
hid_set_field()
-> field->value[]
-> hid_output_report()
-> implement() write bit fields
-> ll_driver request/raw_request/output_report

调用者必须遵守 report type、ID、长度和 logical range。

9. 安全边界

报告描述符和输入报告都来自外设,属于不可信输入。Core 限制 descriptor/report 大小、collection 深度、usage 数量并检查位偏移。专用 report_fixup 也必须验证 rsize 后再访问固定 offset。

10. 可观测

1
2
3
4
cat /sys/bus/hid/devices/*/report_descriptor > rdesc.bin
hid-decode rdesc.bin
mount -t debugfs none /sys/kernel/debug
ls /sys/kernel/debug/hid/

debugfs 节点依赖 CONFIG_DEBUG_FS

文章互动

阅读 --

留言

0 条留言

正在加载留言…