通用Linux键盘驱动开发求助:拦截输入转发及扫描码获取遇阻
开发建议:Linux通用键盘拦截转发驱动
一、先解决usbhid编译失败问题
- 直接复制内核源码的
hid-core.c这类文件会依赖内核的其他模块和头文件,没法单独编译。正确的做法是基于当前系统的内核源码树来编译:- 先安装当前内核的开发包,比如执行
apt install linux-headers-$(uname -r)(Debian/Ubuntu系)或者对应发行版的内核头包。 - 要么把你的驱动代码放到内核源码树的
drivers/hid/usbhid/目录下,要么写个极简Makefile指定内核源码路径:obj-m += mykbd.o mykbd-objs := hid-core.o [其他依赖的.c文件] KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules - 注意内核版本兼容性,不同内核版本的函数签名、宏定义可能有变化,别直接把高版本内核的代码拿到低版本环境编译。
- 先安装当前内核的开发包,比如执行
二、修复无法接收扫描码的问题
- 能匹配设备但收不到扫描码,大概率是没正确注册输入设备或者没处理USB中断传输:
- 检查probe函数逻辑:必须调用
usb_alloc_intf_urb()分配中断URB,并且正确设置URB的回调函数来处理键盘输入数据,最后用usb_submit_urb()提交。 - 验证输入设备初始化:调用
input_register_device()前,要把struct input_dev的位掩码配置正确——比如set_bit(EV_KEY, dev->evbit)开启按键事件,input_set_capability(dev, EV_KEY, KEY_XXX)覆盖所有按键码,不然系统不认这是键盘设备。 - 确认USB端点:用
usb_find_int_endpoint()获取键盘的中断端点地址,别绑错成控制端点,这是常见的低级错误。 - 查内核日志:用
dmesg或者journalctl -k看驱动加载后的日志,有没有URB提交失败、端点地址无效这类错误提示。
- 检查probe函数逻辑:必须调用
三、实现拦截记录+转发的核心逻辑
- 没必要完全复制usbhid/usbkbd,基于现有驱动改更高效:
- 在URB的回调函数里,收到扫描码数据后,先把数据写到你指定的存储——比如内核环形缓冲区、sysfs节点,或者通过netlink发给用户态进程记录。
- 然后正常调用
input_report_key()、input_sync()把扫描码转发给输入子系统,这样就能实现正常输入显示。 - 要支持任意键盘,别硬编码Vendor ID和Product ID,改成匹配HID类的键盘设备(HID_USAGE_KEYBOARD),这样所有USB键盘都会被驱动捕获。
四、实用调试技巧
- 用
cat /proc/bus/input/devices查看你的驱动是否正确注册了输入设备。 - 安装
evtest工具,直接测试对应输入设备的事件,确认有没有按键事件产生。 - 内核里用
pr_info()打印关键节点的调试信息,比如URB回调是否触发、扫描码数据是什么,一步步排查数据流是否正常。
内容的提问来源于stack exchange,提问作者kurtag1
相关产品推荐
相关产品推荐

