按键、鼠标、键盘、触摸屏等都属于输入(input)设备, Linux 内核为此专门做了一个叫做input子系统的框架来处理输入事件。输入设备本质上还是字符设备,只是在此基础上套上了input 框架,用户只需要负责上报输入事件,比如按键值、坐标等信息, input 核心层负责处理这些事件。
INPUT子系统
1、简介
input 就是输入的意思,因此 input 子系统就是管理输入的子系统,和 pinctrl、 gpio 子系统一样,都是 Linux 内核针对某一类设备而创建的框架。比如按键输入、键盘、鼠标、触摸屏等等这些都属于输入设备,不同的输入设备所代表的含义不同,按键和键盘就是代表按键信息,鼠标和触摸屏代表坐标信息,因此在应用层的处理就不同,对于驱动编写者而言不需要去关心应用层的事情,我们只需要按照要求上报这些输入事件即可。
为此 input 子系统分为 input 驱动层、 input 核心层、 input 事件处理层,最终给用户空间提供可访问的设备节点, input 子系统框架如图所示:
左边就是最底层的具体设备,比如按键、 USB 键盘/鼠标等,中间部分属于Linux 内核空间,分为驱动层、核心层和事件层,最右边的就是用户空间,所有的输入设备以文件的形式供用户应用程序使用。
input 子系统用到了我们前面讲解的驱动分层模型,我们编写驱动程序的时候只需要关注中间的驱动层、核心层和事件层,这三个层的分工如下:
驱动层:输入设备的具体驱动程序,比如按键驱动程序,向内核层报告输入内容。
核心层:承上启下,为驱动层提供输入设备注册和操作接口。通知事件层对输入事件进行处理。
事件层:主要和用户空间进行交互。
2、INPUT驱动编写流程
input 核心层会向 Linux 内核注册一个字符设备,在drivers/input/input.c 这个文件,input.c 就是 input 输入子系统的核心层,此文件里面有如下所示代码:
首先,会先向系统注册一个input类 ,系统启动后在/sys/class目录下会有一个名为input的子目录。
然后注册一个字符设备主设备号为 INPUT_MAJOR,定义如下:
定义在 include/uapi/linux/major.h 中
#define INPUT_MAJOR 13
因此, input 子系统的所有设备主设备号都为 13,我们在使用 input 子系统处理输入设备的时候就不需要去注册字符设备。
(1)、注册input_dev
input子系统其实也是使用结构体steuct input_dev来表示一个设备驱动,所以我们要使用input子系统我们只需要注册一个 input 设备即可。input_dev 结构体表示 input设备,此结构体如下:
定义在 include/linux/input.h 文件中
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; /* 事