HIDRAW、UHID、HIDDEV 用户接口
1. 三者不同
| 接口 | 方向 | 作用 |
|---|---|---|
| hidraw | kernel HID device ↔ userspace client | 访问真实设备原始报告 |
| UHID | userspace transport ↔ kernel HID Core | 用户态创建虚拟 HID |
| HIDDEV | USB HID ↔ userspace client | USB 专属旧式解析接口 |
2. hidraw
CONFIG_HIDRAW 将 hidraw.c 合入 hid.o,创建 /dev/hidrawN。
输入
1 | hid_report_raw_event() |
每个 open 有独立的 64 项 ring。ring 满时 hidraw_report_event() 跳过该 reader 的新 report,因此慢消费者会丢包;每个已入队项按实际 report 长度单独分配内存。
输出/ioctl
write():Output report;HIDIOCSFEATURE/HIDIOCGFEATURE;HIDIOCGRAWINFO;HIDIOCGRAWNAME/PHYS/UNIQ;HIDIOCGRDESCSIZE/HIDIOCGRDESC。
report ID 0 的首字节语义仍需遵循 hidraw ABI。
3. UHID
/dev/uhid 允许用户态实现 low-level transport:
1 | userspace UHID_CREATE2 |
用户态发送 UHID_INPUT2,内核调用 hid_input_report()。内核的 open/output/get_report/set_report 作为事件发给用户态,回复通过对应 reply event 返回。
4. UHID 并发
- create 在 worker 中执行,避免写 syscall 内发生复杂 driver bind;
- event queue + waitqueue;
- report request 使用 sequence ID 等待回复;
- destroy/release 唤醒 pending request;
- 用户态 daemon 崩溃时虚拟 HID 必须完整移除。
UHID 是“用户态传输”,不是让用户态编写 kernel HID driver;若只需访问真实 raw report,应使用 hidraw。
5. HIDDEV
CONFIG_USB_HIDDEV 构建进 usbhid,设备为 /dev/usb/hiddevN,传统主设备号 180 的区间。它暴露 report/field/usage 枚举与事件,主要服务 UPS、monitor controls 等旧应用。
限制:
- 仅 USB;
- ABI 较旧;
- 事件不是完全不解释的原始字节;
- 新应用通常优先 hidraw。
6. 权限
这些字符设备可:
- 注入键盘/鼠标(UHID);
- 读取安全密钥/输入;
- 修改 Feature report;
- 控制设备固件模式。
建议:
- udev 只授权明确 VID/PID;
- 不把
/dev/uhid、/dev/hidraw*无条件暴露给不可信容器; - 使用 cgroup device/SELinux/AppArmor;
- 守护进程 drop privileges;
- 验证 report 长度和 ID。
7. 选择
1 | 读取专有 USB/I2C 报告 -> hidraw |
正在加载留言…