Fixing a Physically Broken P Key with udev hwdb
拯救一个物理损坏的 P 键:udev hwdb 改键实战
症状
笔记本(ThinkPad X230 Tablet,Ubuntu 24.04,GNOME Wayland)的 P 键突然完全无响应,其他按键一切正常。P 是英文里最高频的字母之一,这个键坏了基本没法打字。
排查:先排除软件原因
单键失效的”凶手”很多时候不是硬件,而是软件层拦截。逐项排查:
- 改键守护进程:keyd / kanata / kmonad / input-remapper / interception 等,一个都没在跑,也没有它们的配置文件
- udev hwdb 覆盖:
/etc/udev/hwdb.d/为空,udevadm info里没有任何针对 P 键的KEYBOARD_KEY_*属性 - XKB 选项:GNOME 的
xkb-options是空的 - 无障碍功能:Slow Keys / Bounce Keys 都是关闭状态
- 输入法:ibus 运行的是 passthrough 的 “simple” 引擎,布局就是普通 us
全部排除后,进入硬件验证。
事件捕获:确认按键是否产生任何事件
Wayland 下没有 root 权限读不了 /dev/input/eventX(需要 input 组),常见的 xev 又依赖 XWayland 焦点转发,实测不可靠(窗口反复拿到 KeymapNotify,却一个 KeyPress 都没有)。换用 GTK3 原生窗口直接监听 key-press-event,这是 Wayland 原生路径,和平时打字走的是同一条链路:
1 | # 关键部分:窗口上直接打印 keyval / hardware_keycode |
测试结果:
1 | O 键 → keyval=111(o) hwcode=32 ✓ 正常上报 |
O 和 P 走完全相同的路径(键盘 → 内核 → evdev → compositor → 应用),O 正常而 P 连内核层都没到,结论就是 P 键的机械开关/导电膜物理损坏。
选一个”替身”键
改键的候选键需要满足两个条件:
- 硬件上可用:键盘矩阵断线通常是一整列坏掉。P 所在的列是
P ; / Right Shift,所以必须先用上面的捕获窗口验证候选键本身是好的 - hwdb 能干净处理:udev hwdb 的
KEYBOARD_KEY_<scancode>对非扩展扫描码最可靠。AT 键盘(Set 1 转译)里:- CapsLock =
0x3a,Right Shift =0x36—— 都是非扩展码 ✓ - Right Ctrl(
E0 1D)、Right Alt(E0 38)—— 扩展码,hwdb 处理起来很别扭 ✗
- CapsLock =
最终选择 Right Shift:打字时右手小指本来就停在 P 键下方这一列,往下滑一格就是它,几乎不改变肌肉记忆。代价是大写全部改用 Left Shift(左右手交替按 Shift 本来就是标准指法,影响不大)。
修复:一条 hwdb 规则
新建 /etc/udev/hwdb.d/61-p-remap.hwdb:
1 | # Make Right Shift emit P (broken P key replacement) |
匹配块直接复用 /lib/udev/hwdb.d/60-keyboard.hwdb 里本机已有的 ThinkPad 条目,保证规则精确落在内部 AT 键盘上。KEYBOARD_KEY_36=p 的含义:扫描码 0x36(Right Shift)现在上报为 KEY_P。
生效:
1 | sudo cp 61-p-remap.hwdb /etc/udev/hwdb.d/ |
不需要重启。原理:/lib/udev/rules.d/60-evdev.rules 对非 remove 的设备事件都会重新导入 hwdb 属性并运行 keyboard builtin,后者通过 EVIOCSKEYCODE ioctl 现场改写键码映射。
验证:按 Right Shift 直接打出 p,Left Shift + Right Shift 打出大写 P。
撤销方法
如果键盘换新了,想恢复原样:
1 | sudo rm /etc/udev/hwdb.d/61-p-remap.hwdb |
小结
- 单键失灵先查软件层(改键工具、hwdb、xkb、无障碍、输入法),再上事件捕获
- Wayland 下抓键事件用 GTK 原生窗口比 xev 靠谱
- 改键前先验证”替身”键本身可用(矩阵断线往往是一整列)
- hwdb 改键无需额外守护进程,开机、登录界面、TTY 全部生效,持久且可随时撤销