HIDRAW、UHID、HIDDEV 用户接口

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_HIDRAWhidraw.c 合入 hid.o,创建 /dev/hidrawN

输入

1
2
3
4
hid_report_raw_event()
-> hidraw_report_event()
-> copy report into each open file queue
-> wake poll/read/fasync

每个 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
2
3
4
5
userspace UHID_CREATE2
-> hid_allocate_device()
-> set BUS_VIRTUAL + ll_driver
-> worker hid_add_device()
-> normal HID driver/input/hidraw appears

用户态发送 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
2
3
4
读取专有 USB/I2C 报告       -> hidraw
用户态 Bluetooth/网络 HID -> UHID
兼容旧 UPS/monitor 程序 -> HIDDEV
普通键鼠/触控 -> evdev/libinput

文章互动

阅读 --

留言

0 条留言

正在加载留言…