1、编写目的
介绍
linux内核中 input 子系统的接口及使用方法,为 input 设备驱动的编写者提供参考。
2、子系统介绍
2.1 整体框架介绍
Linux 输入设备种类繁杂,常见的包括有按键、键盘、触摸屏、鼠标、摇杆等等,Linux 内核为了统一处理不同的输入设备,设计实现了一个对于上层应用统一的试图抽象层,即输入子系统。在 linux 中,输入子系统作为一个
模块存在,将输入子设备的共同性 抽象出来,向上提供统一的接口函数,这样,就能够使输入子设备的事件通过输入子系统 发给
用户层应用程序,用户层应用程序也可以通过输入子系统通知
驱动程序实现某项功能。
input 子系统属于内核空间,共分为三层,分别为:事件处理层(EventHandler)、核心层(InputCore)和设备驱动层(Input
driver)。如图所示:
其中每个层对应的意义如下:
• 驱动层:主要实现是驱动开发人员,主要负责的任务是针对不同的设备创建相应的input_dev,然后通过调用通用接口上报事件。
• 核心层:由内核实现,主要负责实现驱动所需要的各种调用接口,驱动层上报数据将经过核心层,核心层再将数据上报给事件层。
• 事件层:接收来自核心层的事件,并选择对应的 handler(处理程序)去处理,目的是将数据复制到用户空间,即在/dev/input/下生成相应的设备节点(设备文件)。
• 用户空间:Linux 系统中,用户空间将所有的设备都当文件来处理,即在用户空间访问设备节点,输入子设备节点为/dev/input/
device/event*。
input 子系统的三个层中,核心层和事件处理层都是内核已经完成的,对于设备驱动开发都集中在驱动层。
2.2 工作流程流程介绍
上图以 USB 键盘为例:当 USB 键盘连接上来后,USB 键盘的驱动程序(驱动层)把 相应的事件交给核心层,然后核心层再把事件交给输入事件驱动(事件处理层),输入事件驱动又把事件反馈到相应的设备文件中(/dev/input/*),最后应用程序就可以通过标准读写函数去操作这些设备文件了。
3、driver 编写流程
3.1 menuconfig 配置
打开输入子系统,menuconfig 需要进入 Device Driver->Input device
support 里面选中大概如下配置选项:
3.2 驱动编写步骤
注册输入设备驱动共分五步,且均是在驱动层中完成,如下所示:
1. 调用 input_allocate_device 函数:分配一个 input_dev 结构体。
2. 得到 input_dev 结构体
指针后还需要为这个结构体增加对应设备的特性:主要是事件类型和事件键值。
• 事件类型:表示该输入设备能上报的事件的具体类型,例如 TP 能上报绝对坐标类 型事件,按键能上报按键类型的事件等,另外输入设备都要支持同步事件类型,用于当某个事件上报完毕后,告诉系统事件上报完毕。具体的事件类型可以参照内核linux/
include/input.h,以下是系统支持的事件类型:
#define EV_SYN 0x00 //同步事件类型
#define EV_KEY 0x01 //按键事件类型
#define EV_REL 0x02 //相对坐标事件类型
#define EV_ABS 0x03 //绝对坐标事件类型
#define EV_MSC 0x04 //杂项事件类型
#define EV_SW 0x05 //开关事件类型
#define EV_LED 0x11 //按键/设备灯事件类型
#define EV_SND 0x12 //声音/警报事件类型
#define EV_REP 0x14 //重复事件类型
#define EV_FF 0x15 //力反馈事件类型
#define EV_PWR 0x16 //
电源事件类型
#define EV_FF_STATUS 0x17 //力反馈状态事件类型
#define EV_MAX 0x1f //事件类型最大个数和提供位掩码支持
#define EV_CNT (EV_MAX+1)
• 事件键值:表示具体的事件类型支持的具体键值,比如事件类型为 EV_KEY,可 以支持上报 BINT_0、KEY_A 等按键键值,如果事件类型为 EV_ABS,可以支持ABS_X、ABS_Y 坐标键值等,这些都需要初始化的时候告知系统,具体请参考include/uap1/linux/input.h。
3. 调用 input_register_device 函数:注册此输入设备到 input 子系统中;
4. 在 input 设备发生输入操作时,提交锁发生的时间以及对应的键值/坐标等状态。
5. 在驱动退出函数里面卸载 input 设备。
input 子系统中输入设备驱动的核心工作就是:向系统申请要上报的输入子事件类型 和输入子事件键值,并正确报告这个事件,而不用关心事件如何处理,因为事件处理由事件处理层来完成。
更多详细内容请下载附件查看