按键、鼠标、键盘、触摸屏都属于输入设备,针对这些设备linux内核提供了一个叫做input的子系统框架来处理输入时间,本质上还是字符设备,只是在此基础上加上了input框架,用户只需要负责上报输入事件,input核心层负责处理这些事件。
一、input 子系统简
input 就是输入的意思,因此 input 子系统就是管理输入的子系统,和 pinctrl、gpio 子系统 一样,都是 Linux 内核针对某一类设备而创建的框架。比如按键输入、键盘、鼠标、触摸屏等 等这些都属于输入设备,不同的输入设备所代表的含义不同。
Input子系统分为input驱动层、input核心层、input事件处理层,最终给用户空间提供可访问的设备节点。采用了驱动分层模型,系统框图如下:
这三层的分工如下:
驱动层:输入设备的具体驱动程序,比如按键驱动程序,向内核层报告输入内容。
核心层:承上启下,为驱动层提供输入设备注册和操作接口。通知事件层对输入事件进行 处理。
事件层:主要和用户空间进行交互。
二、input 驱动编写流程
input核心层会向linux内核注册一个字符设备,drivers/input/input.c就是input输入子系统的核心层,系统启动后,会在sys/class下有一个input目录。
Input子系统所有的设备的主设备号是13。因此我们在使用input子系统处理输入设备就不需要注册字符设备了,我们只需要向系统注册一个input设备即可。
input_dev结构体表示input设备,需要先使用input_allocate_device函数申请一个input_dev结构体,
struct input_dev *input_allocate_device(void)
结构体定义如下:
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)]; /* 事件类型的位图 */
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; /* 按键值的位图 */
unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; /* 相对坐标的位图 */
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; /* 绝对坐标的位图 */
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; /* 杂项事件的位图 */
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; /*LED 相关的位图 */
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];/* sound 有关的位图 */
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; /* 压力反馈的位图 */
unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; /*开关状态的位图 */
bool devres_managed;
};
evbit 表示输入事件类型,可选的事件类型定义在 include/uapi/linux/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 /* LED */
#define EV_SND 0x12 /* sound(声音) */
#define EV_REP 0x14 /* 重复事件 */
#define EV_FF 0x15 /* 压力事件 */
#define EV_PWR 0x16 /* 电源事件 */
#define EV_FF_STATUS 0x17 /* 压力状态事件 */
要使用到按键,那么就需要注册 EV_KEY 事件,如果要使用连按功能还需要注册 EV_REP 事件。
本章要使用按键事件,因此要用到 keybit, keybit 就是按键事件使用的位图, Linux 内核定义了很多按键值,这些按键值定义在 include/uapi/linux/input.h 文件中,按键值如下
#define