Linux 应用篇 学习笔记:输入设备应用编程

一、输入类设备编程

1.1 什么是输入设备

常见的输入设备包括鼠标、键盘、触摸屏、按钮等,它们都能产生输入事件,产生输入数据给计算机系统。

1.2 input 子系统

Linux 系统为了统一管理输入设备,实现了一套能够兼容所有输入设备的框架,这个框架就是input 子系统。驱动开发人员基于input 子系统开发输入设备的驱动程序,input 子系统可以屏蔽硬件的差异,向应用层提供一套统一的接口。

1.3 查看input 子系统注册的输入设备

基于input 子系统注册成功的输入设备,都会在/dev/input 目录下生成对应的设备节点(设备文件),设备节点名称通常为eventX( X 表示一个数字编号0、1、2、3 等),例如/dev/input/event0, /dev/input/event1,/dev/input/event2 等,通过读取这些设备节点可以获取输入设备上报的数据。

1.4 查看输入设备对应的设备节点

 cat  /proc/bus/input/devices

二、读取数据的流程

如果我们要读取触摸屏的数据,假设触摸屏设备对应的设备节点为/dev/input/event0 , 那么数据读取流程如下:

  1. 应用程序打开/dev/input/event0 设备文件;
  2. 应用程序发起读操作(例如调用read),如果没有数据可读则会进入休眠(阻塞I/O 情况下;
  3. 当有数据可读时,应用程序会被唤醒,读操作获取到数据返回;
  4. 应用程序对读取到的数据进行解析。

三、应用程序如何解析数据

3.1 获取到的数据格式

应用程序打开输入设备对应的设备文件,向其发起读操作,那么这个读操作获取到的数据是什么样的数据呢?其实每一次read 操作获取的都是一个struct input_event 结构体类型数据,该结构体定义在 头文件中,它的定义如下:

struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};

3.2 结构体成员

  • time :内核记录每个上报的事件其发生的时间,并通过变量time返回给应用程序。
  • type
  • code
  • value
    各个成员具体值代表的含义,参考文件

3.2.1 type

type 用于描述发生了哪一种类型的事件(对事件的分类),Linux 系统所支持的输入事件类型如下:

类型 代码中的值 描述
EV_SYN 0x00 同步类事件,用于同步事件
EV_KEY 0x01 按键类事件
EV_REL 0x02 相对位移类事件(例如鼠标)
EV_ABS 0x03 绝对位移类事件(例如触摸屏)
EV_MSC 0x04 其他杂类事件
EV_SW 0x05
EV_LED 0x06
EV_SND 0x07
EV_REP 0x08
EV_FF 0x09
EV_PWR 0x0A
EV_FF_STATUS 0x0B
EV_MAX 0x1F
EV_CNT (EV_MAX+1)

一种输入设备通常可以产生多种不同类型的事件。例如点击鼠标按键(左键,右键)时会上报按键类事件,移动鼠标时,则会上报位移类事件。

3.2.1.2 用于数据同步的type

同步事件(EV_SYN)用于实现同步操作、告知接收者本轮上报的数据已经完整。应用程序读取输入设备上报的数据时,一次read 操作只能读取一个struct input_event 类型数据。例如对于触摸屏来说,一个触摸点的信息包含了X 坐标、Y坐标以及其他信息,对于这样的情况,应用程序需要执行多次read 操作才能把一个触摸点的信息全部读取出来,这样才能得到触摸点的完整信息。
那么应用程序如何得知本轮已经读取到完整的数据呢?其实这就是通过同步事件来实现的,内核将本轮需要上报、发送给接收者的数据全部上报完毕后,接着会上报一个同步事件,以告知应用程序本轮数据已经完整、可以进行同步了。

同步事件 代码中的值 描述
SYN_REPORT 0 数据上报
SYN_CONFIG 1
SYN_MT_REPORT 2
SYN_DROPPED 3
SYN_MAX 4 最大同步事件
SYN_CNT 5 同步事件的数量

3.2.2 code

表示该类事件中的哪一个具体事件,每一种事件类型都包含多种不同的事件。

3.2.2.1 按键类事件的code
按键类事件 代码中的值 描述
KEY_RESERVED 0 保留
KEY_ESC 1 ESC 键
KEY_1 2 数字键1
KEY_2 3 数字键2
KEY_TAB 15 TAB键
KEY_Q 16 字母Q
KEY_W 17 字母W
3.2.2.2 相对位移事件的code
相对位移事件code 代码中的值 描述
REL_X 0x00 X 轴
REL_Y 0x01 Y轴
REL_Z 0x02 Z 轴
REL_RX 0x03
REL_RY 0x04
REL_RZ 0x05
3.2.2.3 绝对位移事件的code

触摸屏设备是一种绝对位移设备,它能够产生绝对位移事件。例如对于触摸屏来说,一个触摸点所包含的信息可能有很多种,例如触摸点的x轴坐标,Y轴坐标,按压力大小以及触控面积等。所以code 变量告知应用程序,当前上报的是触摸点的哪一种信息(x 坐标还是Y轴坐标,亦或其它)。

绝对位移事件code 代码中的值 描述
ABS_X 0x00 X 轴
ABS_Y 0x01 Y轴
ABS_Z 0x02 Z 轴
ABS_RX 0x03
ABS_RY 0x04
ABS_RZ 0x05

3.2.3 value

内核每次上报事件都会向应用层发送一个数据value。对value 值的解释随着code 的变化而变化。

例如对于按键事件(type = 1)来说,如果code = 2 (键盘上的数字键1,也就是KEY_1),那么如果value 等于1,则表示KEY_1键按下;value 等于0表示KEY_1 键松开;如果value 等于2,则表示KEY_1 键长按。

例如在绝对位移事件中(type = 3),如果code = 0 (触摸点x 坐标ABS_X),那么value 值就等于触摸点的X 轴坐标值;同理,如果code = 1 (触摸点Y轴坐标ABS_Y),此时value 值便等于触摸点的Y轴坐标值。

type code value 说明
1 2 1 键盘上的数字键1,按下
1 2 0 键盘上的数字键1,松开
1 2 2 键盘上的数字键1,长按
3 0 val 触摸点X轴坐标:val
3 1 val 触摸点Y轴坐标:val

四、触摸屏应用编程

4.1 单点触摸

单点触摸设备只支持单点触摸,一轮完整的数据值包含一个触摸点信息。单点触摸设备以ABS_XXX 事件承载、上报触摸点信息。

4.2 多点触摸

多点触摸设备可支持多点触摸,一轮完整的数据可能包含多个触摸点的信息。多点触摸设备则是以ABS_MT_XXX 事件承载、上报触摸点的信息。

触摸屏设备除了上报绝对位移事件之外,还可以上报按键类事件和同步类事件。

4.3 多点触摸协议

在Linux 内核中,多点触摸设备使用多点触摸(MT)协议上报各个触摸点的数据,MT协议分为两种类型:Type A 和Type B。Type A 协议实际使用中用得比较少,几乎处于淘汰的边缘。

4.3.1 slot

能够追踪并区分触摸点的设备通常在硬件上能够区分不同的触摸点,例如对于5点触摸设备来说,硬件能够为每个识别到的触摸点与一个slot 进行关联,这个slot 就是一个编号,用来区分触摸点0,触摸点1,触摸点2.

4.3.2 ABS_MT_SLOT

Type B协议适用于能够追踪并区分触摸点的设备,协议重点是通过ABS_MT_SLOT 事件上报各个触摸点信息的更新。ABS_MT_SLOT 事件中对应的value 数据存放的便是一个slot,以告知应用层当前正在更新的slot 关联的触摸点对应的信息。

4.3.3 ABS_MT_TRACTKING_ID

ABS_MT_TRACTKING_TD 事件用于触摸点的创建、替换和销毁工作,它携带的value 表示一个ID,一个非负数的ID表示一个有效的触摸点,如果ID等于-1 表示该触摸点已经不存在、被移除了;一个以前不存在的ID 表示这是一个新的触摸点。

4.3.4 触摸坐标

Type B 协议可以减少发送到用户空间的数据,只发生了变更的数据才会上报,例如某个触摸点发生了移动,但仅仅只改变了X 轴坐标、而未改变Y轴坐标,那么内核只会将改变后的X 坐标值通过ABS_MT_POSITION_X 事件发送给应用层。

你可能感兴趣的:(Linux,读书笔记,linux,input子系统)