8. input子系统

触摸屏和用户按键属于input输入子系统的设备, 更多基于input输入子系统的设备也可以通过本章节的方法来分析。

8.1. input子系统

input子系统是Linux对输入设备提供的统一驱动框架。 如按键、键盘、触摸屏和鼠标等输入设备的驱动方式是类似的, 使用input子系统驱动的输入设备可以通过统一的数据结构提交给内核, 该数据结构包括输入的时间、类型、代号以及具体的键值或坐标, 内核通过/dev/input目录下的文件接口传递给用户空间。

在Linux内核源码的“Documentation/input”目录包含了input子系统相关的说明。

本章以触摸进行讲解input子系统的使用。

8.1.1. input事件目录

event文件包含的信息采用内核事件数据结构来记录内容, 当其它程序使用时需要把读取到的内容按数据的结构进行格式化转换, 该数据结构定义如下所示。

1
2
3
4
5
6
 struct input_event {
 struct timeval time;
 __u16 type;
 __u16 code;
 __s32 value;
 };
  • time: 该变量用于记录事件产生的时间戳。

  • type: 输入设备的事件类型。系统常用的默认类型有EV_KEY、 EV_REL和EV_ABS, 分别用 于表示按键状态改变事件、相对坐标改变事件及绝对坐标改变事件,特别地, EV_SYN用于分隔事件,无特别意义。 相关的枚举值可以参考内核文件include/uapi/linux/input-event-codes.h。

  • code: 事件代号,它以更精确的方式表示事件。 例如 在EV_KEY事件类型中,code的值常用于表示键盘上具体的按键, 其取值范围在0~127之间, 例如按键Q对应的是KEY_Q,该枚举变量的值为16。 如果选择鼠标,evtest输出内容的code分别有ABS_X/ABS_Y,表示上报的是X或Y坐标。

  • value: 事件的值。对于EV_KEY事件类型,当按键按下时,该值为1; 按键松开时,该值为0。 如果选择鼠标,中evtest输出的内容里, ABS_X事件类型中的value值表示X坐标,ABS_Y类型中的value值表示Y坐标。

8.2. evtest

先使用evtest命令获取屏幕的驱动设备,然后选择我们的设备

1
2
3
4
5
6
7
8
#执行evtest命令
sudo evtest

No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:      sgpio-keys
/dev/input/event1:      goodix-ts
Select the device event number [0-1]:
  • sgpio-keys为用户按键和pwr按键,对应事件event0

  • goodix-ts为屏幕触摸,对应事件event1

输入0测试按键,分别按下用户按键和pwr按键,将会有相应的信息打印。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  cat@lubancat:~$ sudo evtest
  No device specified, trying to scan all of /dev/input/event*
  Available devices:
  /dev/input/event0:      sgpio-keys
  /dev/input/event1:      goodix-ts
  Select the device event number [0-1]: 0
  Input driver version is 1.0.1
  Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100
  Input device name: "sgpio-keys"
  Supported events:
    Event type 0 (EV_SYN)
    Event type 1 (EV_KEY)
      Event code 11 (KEY_0)
      Event code 116 (KEY_POWER)
  Properties:
  Testing ... (interrupt to exit)
  Event: time 1721267952.440426, type 1 (EV_KEY), code 11 (KEY_0), value 0
  Event: time 1721267952.440426, -------------- SYN_REPORT ------------
  Event: time 1721267952.623806, type 1 (EV_KEY), code 11 (KEY_0), value 1
  Event: time 1721267952.623806, -------------- SYN_REPORT ------------
  Event: time 1721268015.798035, type 1 (EV_KEY), code 116 (KEY_POWER), value 0
  Event: time 1721268015.798035, -------------- SYN_REPORT ------------
  Event: time 1721268015.978048, type 1 (EV_KEY), code 116 (KEY_POWER), value 1
  Event: time 1721268015.978048, -------------- SYN_REPORT ------------
  • 第17行,按键事件(EV_KEY),按键代码为(KEY_0),其值(value)为0,表示按下了用户按键。

  • 第18行,输入事件同步报告,表示前面的输入事件已经结束。

  • 第19行,按键事件(EV_KEY),按键代码为(KEY_0),其值(value)为1,表示松开了用户按键。

  • 第21行,按键事件(EV_KEY),按键代码为电源键(KEY_POWER),值为0。表示按下了电源键。

  • 第23行,按键事件(EV_KEY),按键代码为电源键(KEY_POWER),值为1。表示松开了电源键。

注意

按下pwr按键会系统重启,因为该按键绑定了系统电源事件。

用户按键绑定了键盘上的0事件,如果使用qt输入框,则按下用户按键和按下键盘上的0效果一样,输入框将会出现0。

如果需要测试触摸屏触摸,可参考屏幕与触摸章节进行测试。