资讯动态

【Linux驱动开发】input子系统详解

发布时间:2026/10/21 11:36:34 来源:尧图企业网站定制
文章目录前言一、相关概念二、input子系统相关函数接口三、key驱动实现步骤3.1 驱动drv端3.2 用户APP端3.3 input_event成员解释type 事件大类code 事件子编号value 状态数值只对 EV_KEY 有效总结前言在 Linux2.4 内核之前键盘、鼠标、摇杆等输入设备驱动相互独立接口不统一驱动重复冗余应用适配麻烦。为了解决该问题Vojtech Pavlik 实现 input 子系统并合入 Linux2.4 内核。它将各类输入硬件抽象成统一事件模型底层驱动只上报事件由 input-core 分发handler 负责向用户空间提供接口后期 evdev 成为了主流。在这篇文章中将对input子系统进行详细的了解并将以按键为例通过input子系统实现按键驱动编写。一、相关概念Linux input 子系统的作用是统一管理所有输入设备把键盘、鼠标、触摸屏、摇杆、按键、编码器等五花八门的硬件抽象成一套统一接口。上层应用不用区分是键盘还是触摸屏直接读取/dev/input/eventX事件即可驱动开发者只需要向 input 核心上报事件不用关心应用层怎么读。Linux input 子系统采用三层分工架构最上层的用户空间程序X-Windows、Qt、gpm 或自定义程序只需通过统一的设备节点 /dev/input/mice、/dev/input/eventX、/dev/input/js 读取事件无需关心底层硬件差异中间的内核空间由输入核心input core作为唯一枢纽向上提供设备文件接口向下把设备侧上报的原始事件分发给事件驱动层mousedev、evdev、joydev、键盘其中键盘事件还可经虚拟终端直达控制台最下层是输入设备驱动程序它屏蔽了 Serio、USB Hid、蓝牙 Hidp、SPI/I2C、ISA/LPC、GPIO 等硬件接口驱动的实现细节这些接口驱动再通过各自的总线连接到 PS/2 键鼠、串行触摸屏、USB 键鼠、蓝牙键鼠、SPI/I2C 触摸屏控制器、加速计和滚轮等具体输入硬件从而实现了「设备驱动负责采集、input core 负责统一抽象、事件驱动负责向上呈现」的解耦设计。可以把它想成一家「快递公司」你应用程序只管到楼下的快递柜/dev/input/… 设备节点取件不管这包裹是飞机运来的还是三轮车拉来的。中间的「输入核心」就是分拣中心所有包裹都要先送到这里登记、统一格式分拣中心往下有两拨人——一边是「收件员」输入设备驱动程序负责从各家快递网点Serio、USB、蓝牙、SPI/I2C 等接口驱动把件收上来另一边是「派件员」输入事件驱动程序如 evdev、mousedev负责把件整理好放进快递柜键盘这类特殊件还会直接送到控制台。最下面的各种鼠标、键盘、触摸屏、加速计就是发货的商家它们通过不同的交通工具PS/2、USB、蓝牙、I2C 总线送到网点。所以这套框架解决的核心问题就是商家千奇百怪但收件人只需要面对一个快递柜。​ 硬件厂商只管写自己的驱动往 input core 里报事件写程序的人只管从设备节点读事件两边互不认识也能配合——这就是为什么一块从没见过的触摸屏插上就能用。二、input子系统相关函数接口函数名功能devm_input_allocate_device输入设备分配函数自动分配 input_dev 结构体内存并在设备注销时自动释放资源input_allocate_device输入设备分配函数input_register_device注册输入设备到 Linux 输入子系统input_unregister_device注销输入设备从输入子系统中移除设备input_mt_init_slots初始化多点触控的槽位。设置设备支持的触摸点数量并配置 MT 协议类型input_mt_slot指定当前上报的触摸点槽位 IDinput_mt_report_slot_state报告 slot 的状态触摸 / 抬起和工具类型手指、笔等input_mt_report_pointer_emulation处理指针模拟状态当追踪的触摸点多余上报数量时可以通知用户层。用于优化触摸板的多点手势处理。input_report_abs上报绝对坐标事件如触摸点的 X/Y 坐标input_set_abs_params配置绝对坐标轴的参数如范围、精度设置轴的最小值、最大值、模糊值和平坦值input_sync上报同步事件标志一组事件上报结束input_set_capability声明输入设备支持的事件类型和具体事件码如按键、坐标等input_event向输入子系统核心层上报一个原始输入事件input_report_key封装 input_event专用于上报按键事件按下 / 释放 / 长按__set_bit位图设置位非原子操作建议 set_bit ()__clear_bit位图清除位注加粗为常用函数。三、key驱动实现步骤3.1 驱动drv端基本字符设备框架删除不需要misc_dev, 和fops了。输入子系统是一个字符设备了在模块初始化 中 input_allocate_device 获得 struct input_dev 类型的指针 input_dev初始化重要的成员 input_dev-name并设置输入设备的能力。按键类型键值等input_register_device 把自定义的输入设备注册到内核中of_find_node_by_path, 从设备树找到节点获得GPIO申请并配置of_irq_get, 通过gpio 获得对应的中断号并进行申请初始化定时器并注册服务函数为延时消抖做好前期工作当外部中断来临定时器开始计时到达设定时间后定时器中断触发在定时器中断服务函数中判断按键是否按下并进行上报完善错误处理并对驱动出口函数进行完善。3.2 用户APP端打开文件并定义input子系统时间结构体#includelinux/input.hstructinput_event{structtimevaltime;// 事件的事件__u16 type;// 事件的类型__u16 code;// 对应的 键值__s32 value;// 按键按下或释放};清零结构体并读取状态打印在交互界面上最后关闭文件。3.3 input_event成员解释type 事件大类0: EV_SYN同步包一组按键动作结束的分隔标记每次完整按键按下/松开后面必定带一条type0 code0 val0对应驱动里的input_sync()。1: EV_KEY 按键类事件code11就是按键其他常见EV_REP (2) 长按重复、EV_ABS (3) 触摸屏坐标等code 事件子编号typeEV_KEY (1)时code 对应按键宏定义KEY_0 11正好对应驱动里注册的KEY_0所以打印code:11value 状态数值只对 EV_KEY 有效1按键按下0按键松开总结成员含义说明type事件大类EV_SYN(0)同步包EV_KEY(1)按键EV_REP(2)长按重复EV_ABS(3)绝对坐标code事件子编号EV_KEY下代表按键编号KEY_011value状态数值EV_KEY1按下0松开

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑