首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

GPIO、ADC、矩阵键盘与电源键

GPIO、ADC、矩阵键盘与电源键

1. GPIO keys

gpio_keys.c 支持 GPIO/IRQ键和仅 IRQ键:

1
2
3
4
5
IRQ
-> optional debounce timer/work
-> read GPIO
-> input_event(type, code, state)
-> input_sync()

DT属性包括 linux,codelabeldebounce-intervalwakeup-sourcelinux,input-type

2. Debounce

硬件 controller支持 debounce时优先使用;否则 timer/work延迟确认。过短产生抖动,过长增加按键延迟。IRQ thread、timer与work必须在 remove同步取消。

3. ADC keys

RK3588公共 DTS大量使用:

1
2
3
4
5
6
7
8
9
10
adc-keys {
compatible = "adc-keys";
io-channels = <&saradc 1>;
keyup-threshold-microvolt = <1800000>;
poll-interval = <100>;
key {
linux,code = <KEY_VOLUMEUP>;
press-threshold-microvolt = <17000>;
};
};

driver轮询 IIO processed voltage,在各按键标称电压中选择差值最小者;若当前值更接近 keyup-threshold,则判定为释放。该实现没有单独的容差属性,并报告上次 release/本次 press。

4. ADC设计

电阻 ladder受:

  • resistor tolerance;
  • Vref;
  • ADC噪声;
  • 按键并联;
  • 温漂;
  • source impedance。

标称电压应留足间隔;本驱动没有多次采样和显式滞回,抗噪能力主要取决于电阻梯、ADC和相邻电压中点。poll-interval=100ms意味着最坏检测延迟约一个周期,过短点击还可能完全漏采。

5. Matrix keyboard

行列扫描:

1
2
drive row -> sample columns -> matrix scan code
-> keymap -> KEY_*

matrix-keymap.c 解析 linux,keymap。需要处理 ghosting、diode方向、row/col数量、debounce和wakeup。

6. RK806/RK805 power key

RK3588常用 RK806 PMIC。MFD rk806-core.c 创建名为 rk805-pwrkey 的 child platform device,由:

1
2
drivers/input/misc/rk805-pwrkey.c
CONFIG_INPUT_RK805_PWRKEY

处理 fall/rise IRQ并报告 KEY_POWER。名称沿用 RK805,不表示板上 PMIC 是 RK805。

7. Wakeup

GPIO key可配置 IRQ wake和按下/释放触发动作。PMIC pwrkey IRQ由 MFD irq domain提供。系统 suspend时必须同时满足:

  • device may wakeup;
  • irq wake enabled;
  • pin/PMIC供电保持;
  • userspace接收 wake后事件。

8. 长按

Linux input通常只报告 press/release/repeat。PMIC硬件强制关机、bootloader长按和 userspace shutdown是不同层,不应混淆。

鼠标、手柄、力反馈与兼容接口

鼠标、手柄、力反馈与兼容接口

1. Mouse

鼠标通常报告:

  • EV_REL/REL_X/REL_Y
  • wheel/hwheel;
  • BTN_LEFT/RIGHT/MIDDLE/...

touchpad通常是 EV_ABS + MT,由 libinput转换为指针和手势。

2. Mousedev

mousedev.c 把 input事件转换为 PS/2兼容 byte stream:

1
2
/dev/input/mouseX
/dev/input/mice

这是 legacy接口。现代图形栈使用 evdev/libinput,避免丢失高分辨率和多点信息。

3. Joystick

手柄使用:

  • ABS_X/Y/RX/RY、triggers;
  • BTN_GAMEPAD系列;
  • hat axes;
  • EV_FF。

joydev.c 提供 /dev/input/jsN 旧 ABI,evdev保留更完整 event semantics。

4. 力反馈

ff-core.c

  • 分配 effect slots;
  • upload/erase;
  • ownership;
  • play/stop;
  • gain/autocenter;
  • cleanup on close。

设备通过 input_ff_create() 注册。

5. Memoryless FF

ff-memless.c 为只接受即时 motor level的设备模拟 effect时间和组合:

1
2
3
4
EV_FF play
-> timer/work computes magnitude
-> driver play_effect callback
-> set motors

driver callback可能睡眠时须选择正确异步语境。

6. HID边界

大多数 USB/Bluetooth gamepad在 drivers/hid 中解析 report并注册 input device;drivers/input/joystick 更多是非 HID、legacy或特定总线设备。

7. 校准

absolute axis需要正确:

  • min/max;
  • flat dead zone;
  • fuzz;
  • resolution;
  • center。

错误范围会造成漂移或触发器不满量程。用户态校准不能修复驱动持续报错。

8. Grab

游戏程序可能 grab event device。Grab影响整个 input_dev到其它 handlers的分发,桌面按键或 daemon可能收不到事件,应谨慎使用并保证异常退出释放。

9. RK3588

板载通常没有 gameport/PS2;USB/Bluetooth手柄取决于 HID/USB/BT配置。主配置禁用 SERIO和PS2 mouse符合这一硬件现实。

Serio、Gameport、HID 与 Uinput 边界

Serio、Gameport、HID 与 Uinput 边界

1. Serio

Serio是低速串行输入端口抽象,典型 PS/2 i8042、UART keyboard/mouse:

1
2
serio port driver -> serio core -> protocol driver(atkbd/psmouse)
-> input_dev

RK3588主配置 # CONFIG_SERIO is not set,因此传统 AT keyboard/PS2 mouse路径不可用。

2. Gameport

Gameport服务老式模拟 joystick/MIDI gameport。现代 ARM板通常无此硬件,源码存在主要为跨平台兼容。

3. HID

USB HID:

1
USB -> usbhid -> HID Core -> hid-input -> input_dev

Bluetooth HIDP/HOGP也最终注册 input device。Input Core只看到统一 capability/event,不负责 HID report descriptor解析。

4. Native touchscreen vs HID touch

  • I2C芯片专用 protocol:drivers/input/touchscreen
  • HID over I2C:drivers/hid/i2c-hid
  • USB HID touch:drivers/hid/usbhid

排查 eventX时应沿 sysfs parent device判断上游。

5. Uinput

drivers/input/misc/uinput.c 允许用户态:

1
2
3
4
5
6
open /dev/uinput
-> UI_SET_EVBIT/UI_SET_KEYBIT/...
-> UI_DEV_SETUP
-> UI_DEV_CREATE
-> write input_event
-> virtual input_dev

也支持FF上传请求的双向交互。

6. 用途

  • 输入代理;
  • 测试;
  • 用户态协议驱动;
  • 远程桌面;
  • 无障碍;
  • 合成组合键。

7. 安全

拥有 /dev/uinput 写权限通常可注入键盘/鼠标,接近控制登录会话。只授权专用服务,不应加入宽泛用户组或透传给不可信容器。

8. Input与IIO sensor

加速度、光感等新 driver通常应使用 IIO,不应作为 input ABS事件。Rockchip厂商 drivers/input/sensors 是历史 Android sensor stack,接口选择需结合用户空间HAL。

9. 设备识别

1
2
udevadm info /dev/input/eventN
readlink -f /sys/class/input/eventN/device

父链出现 hid/USB/I2C/platform/MFD,可判断实际传输和驱动。

Rockchip 遥控器与传感器输入

Rockchip 遥控器与传感器输入

1. PWM IR遥控

RK3588板级 DTS可见:

1
compatible = "rockchip,remotectl-pwm";

对应 remotectl/rockchip_pwm_remotectl.c,主配置启用 ROCKCHIP_REMOTECTLROCKCHIP_REMOTECTL_PWM

2. 数据路径

1
2
3
4
5
6
7
PWM capture IRQ
-> decode pulse timing/state machine
-> lookup usercode + scancode
-> Linux keycode
-> input_report_key()
-> input_sync()
-> release timer

厂商驱动使用 tasklet/timer分离捕获和解析。

3. DT keymap

driver解析多个 remote key table:

  • usercode;
  • scancode/keycode pairs;
  • power key;
  • PWM channel/IRQ;
  • wake配置。

遥控器协议、地址码和键码必须匹配实际遥控器。

4. Power wake

driver支持将 power key信息配置到 secure firmware/硬件 pwrmatch,suspend/resume通过 SIP SMC保持遥控唤醒。普通运行时解码成功不代表深度休眠唤醒一定可用。

5. Repeat/release

IR协议可能持续发送 repeat frame。driver需:

  • 维持按下;
  • 处理 repeat;
  • timeout合成 release;
  • 避免丢 IRQ后 stuck key。

6. drivers/input/sensors

这是 Rockchip厂商 sensor框架,包含:

  • accelerometer;
  • gyroscope;
  • compass;
  • light/proximity;
  • pressure;
  • hall/angle/temperature。

许多 driver面向旧 Android HAL,通过 input events或私有接口上报。

7. 与 IIO 的关系

上游新 sensor更倾向 IIO。两套框架同时绑定同一芯片会冲突。选择依据:

  • 产品 Android HAL预期;
  • DTS compatible;
  • Kconfig;
  • buffer/trigger需求;
  • 用户 ABI兼容。

8. 维护风险

厂商目录常包含:

  • 私有 ioctl/sysfs;
  • 固件 blobs;
  • Android wakelock兼容;
  • 老 timer/tasklet API;
  • 全局变量;
  • 非标准 DT properties。

修改时需做并发、remove、suspend和越界安全审查。

9. 调试

1
2
3
4
cat /proc/bus/input/devices
evtest
dmesg | grep -Ei 'remote|pwm|key'
cat /sys/kernel/debug/pwm 2>/dev/null

IR raw waveform问题应结合示波器/逻辑分析仪和 IRQ计数判断。

并发、Grab、热插拔与电源管理

并发、Grab、热插拔与电源管理

1. Core locks

  • input_mutex:全局 devices/handlers注册匹配;
  • input_dev.mutex:open/close/flush、handles;
  • event_lock:事件状态、frame和grab,spinlock;
  • RCU grab pointer;
  • handler/client自身锁。

锁顺序不能随意反转,event callback不能睡眠。

2. IRQ路径

input_report_*() 可从 IRQ调用。Core在 event_lock下更新状态并调用 handler,因此 handler event/events/filter 必须快速且不可睡眠。evdev只入 ring并唤醒。

3. Filter

filter handler先看到事件,可消耗/修改分发决策。普通 handlers随后接收批量 values。filter不是用户态安全过滤机制,而是内核 handler语义。

4. Grab

grab使一个 handle成为唯一事件接收者。Core用 RCU访问 grab。释放、disconnect和close必须确保悬空引用不可发生。

5. 热拔

USB/HID或 I2C设备 remove:

  1. 停止 IRQ/URB/poll;
  2. 标记/注销 input device;
  3. Core释放仍按下 keys并 disconnect handlers;
  4. evdev clients唤醒并看到设备消失;
  5. 等待 refcount后释放。

用户打开 fd不会保证硬件永远存在。

6. Inhibit

sysfs inhibited 可停用 device:

  • close driver;
  • Core忽略新事件;
  • uninhibit时重新 open。

适合 temporarily disable设备,不等于解绑 driver。

7. Suspend

Input device PM根据 may_wakeup/inhibited/users切换:

  • non-wakeup device可 close;
  • wakeup key保留 IRQ;
  • resume恢复 open和状态;
  • freeze/poweroff路径不同。

具体 bus driver还要处理 regulator、reset、pinctrl和 IRQ wake。

8. 残留状态

disconnect/reset时 Core可释放按下 keys。触摸 driver还应清空所有 slots。否则 userspace可能保持 stuck key/contact。

9. Timer/work

常见:

  • key debounce timer;
  • ADC poller;
  • IR release timer/tasklet;
  • touch ESD work;
  • FF timer。

remove必须使用同步 cancel/delete,且不在持有回调所需锁时等待。

10. Latency

链路延迟来自采样周期、IRQ thread、bus transaction、Core、evdev wakeup和 userspace调度。仅提高应用优先级无法消除 100ms ADC poll周期。

RK3588 输入拓扑与设备树

RK3588 输入拓扑与设备树

1. 典型拓扑

1
2
3
4
5
6
7
SARADC ch1 -> adc-keys -> volume/menu/back
RK806 IRQ -> MFD rk805-pwrkey -> KEY_POWER
I2C5 + GPIO IRQ/reset -> GT1X/Hyn/FocalTech touch
PWM capture -> rockchip remotectl -> IR keys
USB host -> usbhid -> keyboard/mouse/gamepad
Bluetooth -> HIDP/HOGP -> input_dev
userspace -> uinput -> virtual event device

2. ADC keys

rk3588s-evb.dtsi 等公共文件定义 adc-keys、SARADC channel 1、1.8V key-up和四档键值。对应 CONFIG_KEYBOARD_ADC=y

不同板 resistor ladder可能不同,不应复制阈值而不核对原理图。

3. Touch

多个 EVB定义 goodix,gt1x,例如 I2C地址 0x14、reset/IRQ GPIO和 LCD 3.3V supply。部分板还并列 Hynitron/FocalTech候选。

验证:

1
2
3
i2cdetect -y <bus>   # 仅确认安全时
cat /proc/interrupts
evtest

不要对未知 I2C地址盲扫或强制 bind。

4. PMIC power key

RK806通过 MFD创建 rk805-pwrkey platform child。Input driver不直接匹配 RK806 DT compatible;其 probe依赖 parent MFD、regmap irq和资源名称。

5. IR

若板 DTS有 rockchip,remotectl-pwm,驱动读取 remote key tables并配置 power wake。需要 PWM capture pinmux、IRQ和 secure firmware共同支持。

6. GPIO keys

主配置已启用 interrupt和 polled GPIO keyboard,但具体 RK3588公共板更多使用 ADC keys。是否有 GPIO button必须按目标 DTS核对。

7. USB/Bluetooth

这两类不在 RK3588 SoC DTS中枚举具体键鼠:

  • USB runtime enumeration;
  • Bluetooth pairing/SDP/GATT;
  • HID Core生成 input device。

需同时启用 USB host、BT、HID和对应 transport。

8. 配置事实

主配置:

  • evdev、ADC/GPIO keyboard、touch、IR、uinput、RK805 pwrkey启用;
  • AT keyboard、PS/2 mouse、serio禁用;
  • FF memless启用;
  • mouse touchpad drivers CYAPA/ELAN I2C启用。

最终产品还会叠加 fragment,必须以 /proc/config.gz 为准。

9. Android

Android InputReader按 .idc/.kl/.kcm 和 device identity映射:

  • Linux keycode到 Android key;
  • touch orientation/size;
  • virtual keys;
  • wake policy。

内核事件正确不代表 Android层映射一定正确。

10. 验证链

1
2
3
4
5
6
7
8
原理图
-> DTS node/status/pinctrl
-> final config
-> bus/MFD probe
-> input device in proc/sysfs
-> eventX capability
-> evtest
-> libinput/Android mapping

Input 调试、性能、安全与部署建议

Input 调试、性能、安全与部署建议

1. 识别设备

1
2
3
4
cat /proc/bus/input/devices
ls -l /dev/input/by-{id,path}/
udevadm info --query=all --name=/dev/input/event0
cat /sys/class/input/event0/device/{name,phys,uniq}

优先使用 by-path/by-id或 udev属性,不写死 eventN。

2. 事件

1
2
3
evtest /dev/input/eventN
libinput list-devices
libinput debug-events

确认 capability、press/release、SYN边界、MT slots、timestamp、repeat。

3. 分层排查

1
2
3
4
5
无设备 -> config/module -> DTS/MFD/bus -> probe error
有设备无事件 -> IRQ/poll -> pinctrl/polarity -> hardware protocol
有事件映射错 -> scancode/keymap -> capability -> userspace map
触摸错位 -> abs range -> DT transform -> display transform
唤醒失败 -> wakeup-source -> irq wake -> power domain -> firmware

4. IRQ

1
2
cat /proc/interrupts
watch -n1 cat /proc/interrupts

按键/触摸时 IRQ应增长。持续高速增长提示极性、清中断或硬件噪声问题。

5. Dynamic debug

1
2
3
mount -t debugfs none /sys/kernel/debug
echo 'file drivers/input/keyboard/adc-keys.c +p' \
> /sys/kernel/debug/dynamic_debug/control

敏感键值日志只在受控环境启用。

6. 性能

  • ADC key降低 poll interval会增加 IIO访问和功耗;
  • touch IRQ thread的 I2C transfer应批量且有上限;
  • 每帧只发变化和一个 SYN_REPORT;
  • 估算合理 events_per_packet;
  • 避免 ESD work与 IRQ同时重置;
  • 检查 evdev SYN_DROPPED

7. 安全

/dev/input/event* 可记录密码,/dev/uinput 可注入控制。建议:

  • seat ACL;
  • 最小 group权限;
  • 容器不透传整目录;
  • 禁用 INPUT_EVBUG
  • 调试日志脱敏;
  • 校验触摸 firmware/update输入;
  • 厂商 ioctl严格检查 length和 copy_from_user。

8. 稳定性测试

  • 快速按键和长按;
  • 多指全屏、边缘、slot churn;
  • suspend/resume循环;
  • 热插拔/拔线;
  • display rotation;
  • 高 CPU/I2C负载;
  • IR repeat/wakeup;
  • ADC电压边界和温漂;
  • 异常退出后 grab释放。

9. 常见误判

  • eventX变化不是驱动丢失;
  • evtest正常但 GUI无反应常是 capability/seat/映射;
  • USB键鼠源码主要在 HID;
  • RK806 power key driver名仍为 rk805;
  • DTS中候选触摸节点不代表全部硬件同时存在;
  • input sensor与 IIO sensor不可按目录名混为一谈。

10. 生产建议

保存 device identity、能力 bitmap和内核日志基线;升级 kernel/DT后自动比较 event设备、keycodes、ABS范围、wakeup和 latency,避免用户空间依赖隐式 probe顺序。

Input 子系统架构与源码总览

Input 子系统架构与源码总览

1. 架构

1
2
3
4
5
6
7
8
9
10
11
hardware: GPIO/IIO/I2C/SPI/USB/PMIC/PWM IR
|
device driver -> input_dev
|
Input Core
|
input_handle connects device and handler
| | |
evdev mousedev joydev
|
/dev/input/eventN -> libinput/Android/Linux application

2. 核心对象

  • input_dev:能力、状态、坐标、回调与事件缓存;
  • input_handler:evdev 等消费者;
  • input_handle:device-handler连接;
  • input_valuetype/code/value
  • input_mt:多点触控 slot 状态;
  • ff_device:力反馈 effect。

3. 构建

input-core.o 由:

1
input.o input-compat.o input-mt.o input-poller.o ff-core.o touchscreen.o

组成。evdev/mousedev/joydev是独立 handler module。

4. 设备注册

1
2
3
4
5
6
7
8
9
10
11
probe
-> devm_input_allocate_device()
-> set name/phys/id/parent
-> set evbit/keybit/absbit
-> input_set_abs_params()
-> input_register_device()
-> cleanse capabilities
-> allocate event values
-> device_add()
-> append input_dev_list
-> match all handlers

5. Handler 注册

1
2
3
4
5
input_register_handler()
-> append input_handler_list
-> match all input devices
-> handler->connect()
-> input_register_handle()

设备和 handler 无论谁先注册,Core都可完成匹配。

6. 事件

1
2
3
4
5
6
7
8
9
10
IRQ/poll
-> input_report_key/abs/rel()
-> input_event()
-> state validation/filter
-> queue input_value
-> input_sync()
-> input_pass_values()
-> handler->events()
-> evdev client ring buffer
-> read(eventN)

7. 用户接口

  • evdev:主通用 ABI;
  • mousedev:PS/2 mouse兼容流;
  • joydev:旧 joystick ABI;
  • sysfs:能力、ID、name、phys、properties;
  • procfs:devices/handlers;
  • uinput:用户态创建虚拟 input device。

8. 事件类型

主要 EV_KEYEV_RELEV_ABSEV_MSCEV_SWEV_LEDEV_SNDEV_REPEV_FFEV_SYN

9. RK3588

本树常见来源:

  • SARADC adc-keys
  • RK806 MFD创建的 rk805-pwrkey
  • I2C GT1X/Hynitron/FocalTech touch;
  • Rockchip PWM IR remotectl;
  • USB/Bluetooth HID经 drivers/hid
  • GPIO keys(具体板 DTS);
  • uinput虚拟设备。

10. 边界

drivers/input 提供 Input Core和许多 native driver;USB/Bluetooth键鼠触控主要先由 HID解析,再注册 input_dev。因此 eventX 的上游不一定在本目录。

Linux 6.1 Input 子系统文档索引

Linux 6.1 Input 子系统文档索引

源码:rk3588/kernel-6.1/drivers/input/
目标平台:RK3588,Rockchip Linux 6.1 厂商树

文档

文档 内容
Input子系统架构与源码总览.md 分层、对象和端到端路径
源码目录与驱动索引.md Kconfig/Makefile、驱动族
01-Input-Core设备Handler与生命周期.md input_dev/handler/handle
02-输入事件模型状态同步与时间戳.md EV_*、SYN、过滤、repeat
03-Evdev字符设备缓冲与IOCTL.md eventX、read/poll/grab/uAPI
04-多点触控坐标与触摸屏框架.md MT slots、Protocol B、properties
05-GPIO-ADC矩阵键盘与电源键.md keys、debounce、wakeup
06-鼠标手柄力反馈与兼容接口.md REL、joydev、mousedev、FF
07-Serio-Gameport-HID与Uinput边界.md 传输边界和虚拟设备
08-Rockchip遥控器与传感器输入.md PWM IR、厂商 sensor 目录
09-并发Grab热插拔与电源管理.md 锁、disconnect、inhibit、PM
10-RK3588输入拓扑与设备树.md ADC keys、GT1X、RK806、USB
11-调试性能安全与部署建议.md evtest、权限、延迟、排障

推荐顺序

1
2
3
4
5
6
总览 -> 01 Core -> 02 事件 -> 03 evdev
├-> 04 触摸
├-> 05 键盘
├-> 06 鼠标/手柄
└-> 08 遥控
-> 09 并发PM -> 10 RK3588 -> 11 调试

快速查看

1
2
3
4
5
6
cat /proc/bus/input/devices
ls -l /dev/input/
for e in /sys/class/input/event*; do
echo "$e: $(cat "$e/device/name")"
done
evtest

eventN 编号受 probe 顺序影响,应用应通过 udev 属性、设备名、物理路径和能力匹配。