1.Getevent工具使用及参数说明
当用户触摸屏幕或者按下按键时,首先触发的是硬件驱动,硬件驱动会将事件写入设备节点(/dev/input),这便是内核的原始输入事件,getevent指令的作用便是读取内核中的原始输入事件。
1.1 getevent指令的使用
首先adb shell进入机器后,输入 getevent -h
130|1:/ $ getevent -h
Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]
-t: show time stamps //添加按键发生的时间戳信息
-n: don't print newlines //不要打印换行符
-s: print switch states for given bits
-S: print all switch states //打印所有开关状态
-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)//打印硬件的基本信息
-d: show HID descriptor, if available
-p: show possible events (errs, dev, name, pos. events) //显示所有的事件,如果是按键,则会显示所有key,如果是触摸屏,则会显示绝对坐标系的值
-i: show all device info and possible events
-l: label event types and names in plain text //用纯文本标记事件类型和名称
-q: quiet (clear verbosity mask)//去除所有设备信息和节点信息,只有按键信息
-c: print given number of events then exit //打印给定数量的事件,然后退出
-r: print rate events are received
1.1.1 getevent
不带任何参数显示如下:
130|:/ $ getevent
add device 11: /dev/input/event1 //设备节点
name: "pmic_pwrkey" //设备名称 手机上的power电源按键
/dev/input/event1: 0001 0074 00000001 //按键按下信息
/dev/input/event1: 0000 0000 00000000 /同步事件信息
/dev/input/event1: 0001 0074 00000000 //按键抬起信息
/dev/input/event1: 0000 0000 00000000 /同步事件信息
1.1.2 getevent -t
携带事件发生的时间戳
add device 11: /dev/input/event1 //设备节点
name: "pmic_pwrkey" //设备名称 手机上的power电源按键
[ 63641.462544] /dev/input/event1: 0001 0074 00000001 //按键按下信息
[ 63641.462544] /dev/input/event1: 0000 0000 00000000 //同步事件信息
[ 63641.547853] /dev/input/event1: 0001 0074 00000000 //按键抬起信息
[ 63641.547853] /dev/input/event1: 0000 0000 00000000 //同步事件信息
1.1.3 getevent -n
没有换行符
/dev/input/event1: 0001 0074 00000001/dev/input/event1: 0000 0000 00000000/dev/input/event1: 0001 0074 00000000/dev/input/event1: 0000 0000 00000000
1.1.4 getevent -v
显示硬件的一些供应商等信息
add device 11: /dev/input/event1
bus: 0000
vendor 0000
product 0000
version 0000
name: "pmic_pwrkey"
location: "pmic_pwrkey/input0"
id: ""
version: 1.0.1
1.1.5 getevent -p
add device 4: /dev/input/event8
name: "touchpanel"// 触摸屏
events:
KEY (0001): 003e 008e 0145 014a
ABS (0003): 0000 : value 0, min 0, max 19840, fuzz 0, flat 0, resolution 0
0001 : value 0, min 0, max 44352, fuzz 0, flat 0, resolution 0
0018 : value 0, min 0, max 0, fuzz 0, flat 0, resolution 0
0021 : value 924, min 0, max 0, fuzz 0, flat 0, resolution 0
0022 : value 148, min 0, max 0, fuzz 0, flat 0, resolution 0
0023 : value 117, min 0, max 0, fuzz 0, flat 0, resolution 0
002f : value 0, min 0, max 9, fuzz 0, flat 0, resolution 0
0030 : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
0031 : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
0032 : value 0, min 0, max 0, fuzz 0, flat 0, resolution 0
0035 : value 0, min 0, max 19840, fuzz 0, flat 0, resolution 0
0036 : value 0, min 0, max 44352, fuzz 0, flat 0, resolution 0
0037 : value 0, min 0, max 0, fuzz 0, flat 0, resolution 0
0039 : value 0, min 0, max 65535, fuzz 0, flat 0, resolution 0
003a : value 0, min 0, max 0, fuzz 0, flat 0, resolution 0
add device 11: /dev/input/event1
name: "pmic_pwrkey" //手机的电源按键
events:
KEY (0001): 0074 //电源按键对应的值
1.1.6 getevent -i
相当于-v和-p的合体
add device 11: /dev/input/event1
bus: 0000
vendor 0000
product 0000
version 0000
name: "pmic_pwrkey"
location: "pmic_pwrkey/input0"
id: ""
version: 1.0.1
events:
KEY (0001): 0074
input props:
1.1.7 getevent -l
/dev/input/event1: EV_KEY KEY_POWER DOWN
/dev/input/event1: EV_SYN SYN_REPORT 00000000
/dev/input/event1: EV_KEY KEY_POWER UP
/dev/input/event1: EV_SYN SYN_REPORT 00000000
1.1.8 getevent -q
去除了所有设备信息,只有event事件
130|:/ $ getevent -q
/dev/input/event1: 0001 0074 00000001
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0074 00000000
/dev/input/event1: 0000 0000 00000000
1.1.9 getevent -c
输入指定条数的信息
130|:/ $ getevent -c 3
add device 11: /dev/input/event1
name: "pmic_pwrkey"
/dev/input/event1: 0001 0074 00000001
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0074 00000000
1.1.10 getevent - r
输出信息产生的速度,例如:按下或抬起的速度很快 rate值就越高
/dev/input/event1: 0001 0074 00000001
/dev/input/event1: 0000 0000 00000000 rate 7
/dev/input/event1: 0001 0074 00000000
/dev/input/event1: 0000 0000 00000000 rate 0
1.2 事件类型格式分析
格式是 :/dev/input/eventX type code value
例如:/dev/input/event1: 0001 0074 00000001
1.2.1 type
其中type的内容如下:
#define EV_SYN 0x00 //代表同步事件
#define EV_KEY 0x01 //按键事件
#define EV_REL 0x02 //相对坐标,用来描述相对坐标轴上数值的变化,例如:鼠标向左方移动了5个单位。
#define EV_ABS 0x03 //绝对坐标,用来描述相对坐标轴上数值的变化,例如:描述触摸屏上坐标的值。
#define EV_MSC 0x04 //杂项事件,当不能匹配现有的类型时,使用该类型进行描述。
#define EV_SW 0x05 //开关事件, 用来描述具备两种状态的输入开关。
#define EV_LED 0x11 //EV_LED事件类型通常与设备上的物理LED指示灯相关,例如键盘背光灯、通知LED等
#define EV_SND 0x12 //描述声音事件
#define EV_REP 0x14 //用于可以自动重复的设备
#define EV_FF 0x15 //强力回馈事件,如打游戏时的震动事件
#define EV_PWR 0x16 //特别用于电源开关的输入
1.2.2 code
code事件会跟随type事件的不同而代表不同的含义
1.当type是EV_KEY,则code KEY_POWER代表电源按键。
详情可以看下列网址指向的地点
http://aospxref.com/android-14.0.0_r2/xref/bionic/libc/kernel/uapi/linux/input-event-codes.h
1.3 key事件类型分析
声明:由于本人之前是在安卓9进行蓝牙手柄的开发,所以此篇分析是当时基于安卓9进行的分析,而上面的指令是笔者用安卓14的手机进行内容获取。其中笔者发现按键的信息发生了变化。为何不用安卓9?因为本人最近整理的时候没有安卓9的环境。
1.3.1 安卓9 按键消息和安卓14 按键消息的差异?
安卓9:
按下和抬起一共6条消息
按下:
/dev/input/event4: 0004 0004 00090001
/dev/input/event4: 0001 0130 00000001
/dev/input/event4: 0000 0000 00000000
抬起:
/dev/input/event4: 0004 0004 00090001
/dev/input/event4: 0001 0130 00000000
/dev/input/event4: 0000 0000 00000000
安卓14:
按下和抬起是4条消息
/dev/input/event1: 0001 0074 00000001
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0001 0074 00000000
/dev/input/event1: 0000 0000 00000000
1.3.2 安卓9 蓝牙手柄按键消息分析
按下:
/dev/input/event4: 0004 0004 00090001 //第一条消息
/dev/input/event4: 0001 0130 00000001 //第二条消息
/dev/input/event4: 0000 0000 00000000 //第三条消息
抬起:
/dev/input/event4: 0004 0004 00090001 //第四条消息
/dev/input/event4: 0001 0130 00000000 //第五条消息
/dev/input/event4: 0000 0000 00000000 //第六条消息
参数说明:
/dev/input/event4:代表产生事件的设备节点
0004:代表事件类型
0004:代表事件代码
00090001:事件的值
使用getevent -l指令如下:
第一条数据包分析:
/dev/input/event4: 0004 0004 00090001
0004=EV_MSC,004=MSC_SCAN value=00090001
EV_MSC代表是杂项事件,MSC_SCAN代表是杂项事件中的扫描事件,Value代表值是00090001,说明扫描到BTN_GAMEPAD这个按键有变化
第二条数据包分析:
是一个按键事件,并表示按了什么键,是否按下
/dev/input/event4: 0001 0130 00000001
0001=EV_KEY 0130=BTN_GAMEPAD 00000001=DOWN
EV_KEY代表这是按键类型事件,BTN_GAMEPAD代表手柄注册中的按键是BTN_GAMEPAD,DOWN表示按下
第三条数据包分析:
/dev/input/event4: 0000 0000 00000000
0000= EV_SYN 0000= SYN_REPORT value=00000000
同步包,在应用层和驱动层做信息同步,标识一个独立的事件的发生,它与另一个同步包夹中间的一组的打印就是一个事件的发生
EV_SYN代表,是同步类型,
SYN_REPORT:当多个输入数据在同一时间发生变化时,SYN_REPORT用于把这些数据进行打包和包同步。例如,一次鼠标的移动可以上报REL_X和REL_Y两个数值,然后发出一个SYN_REPORT。
Value就是扫描到的值。
第四条数据包分析:
/dev/input/event4: 0004 0004 00090001
也是一个扫描事件,同第一条
第五条数据包分析:
/dev/input/event4: 0001 0130 00000000
0001=EV_KEY 0130=BTN_GAMEPAD 00000000=UP
表示是一个按键事件,是BTN_GAMEPAD键,00000000表示抬起
第六条数据包分析:
也是一个同步事件
1.4 motion事件类型分析
一次触摸产生的motion事件其实是三个动作
1.手指按下
2.手指移动
3.手指抬起
此时需要先了解Linux的多点触摸协议
1.4.1 多点触摸协议A
主要用于匿名的设备,,硬件对于触摸点不能被区分和追踪,(大多已经淘汰,故此处不再赘述)
type A设备的驱动程序,需要一次性将当前触摸屏上的所有触摸点的信息全部上报。
1.4.2 多点触摸协议B
硬件有能力追踪并区分触摸点,type B协议和type A协议相比,最大的区别是能够识别某一个触摸点,因此能够减少发送给用户空间的数据。协议B使用的是slot来区分触摸点,要使用ABS_MT_TRACKING_ID消息,此消息不为-1,代表是一个可用的触摸点,如果是-1则代表此触摸点销毁(即手指离开屏幕)
1.4.2.1 变量含义
ABS_MT_POSITION_X //触摸中心位置的X轴坐标
ABS_MT_POSITION_Y ///触摸中心位置的X轴坐标,ABS_MT_POSITION_X 和ABS_MT_POSITION_Y 是多点触摸协议的最小事件集,是最基本的事件,也是必须的事件。
ABS_MT_TOOL_TYPE //触摸工具类型。如手指,触摸笔等
ABS_MT_TRACKING_ID //用来追踪和识别压下到提起期间的某一个触摸点
ABS_MT_TOUCH_MAJOR //触摸点椭圆形最长的那个方向的直径
ABS_MT_TOUCH_MINOR //触摸点椭圆形短一点的那个方向的直径,如果是圆形,ABS_MT_TOUCH_MINOR可以省略
ABS_MT_WIDTH_MAJOR //触摸工具的椭圆的最长的那个方向的直径
ABS_MT_WIDTH_MINOR //触摸工具的圆形短一点的那个方向的直径
ABS_MT_PRESSURE //触摸点的压力大小
此处,应该会有读者疑问ABS_MT_TOUCH_MAJOR和ABS_MT_WIDTH_MAJOR 的区别是什么呢?
答:假定我们的手指按在玻璃上,那么ABS_MT_TOUCH_MAJOR描述的是我们真正手指接触的面积,而ABS_MT_WIDTH_MAJOR代表我们手指头的面积,随着我们按压玻璃用力的加深,ABS_MT_TOUCH_MAJOR会接近于ABS_MT_WIDTH_MAJOR。
问:那么为什么要设置这两个参数呢?
答:这两个参数的可以反应触摸点压力的大小。
ABS_MT_PRESSURE =ABS_MT_TOUCH_MAJOR/ABS_MT_WIDTH_MAJOR。
设备的压力值大小计算方法由设备本身决定。并不相同。只是提供一种可能。
1.4.2.2 协议B举例
手指按下
此时有两个手指触摸屏幕,表示按下,即产生两个触摸点
ABS_MT_SLOT 0 //用slot 0表示第一个触摸点
ABS_MT_TRACKING_ID 45 //记录触摸点ID,用于区分触摸点
ABS_MT_POSITION_X x[0] //第一个触摸点按下的x位置。ABS_MT_POSITION_X和ABS_MT_POSITION_Y是多点触摸协议的最小事件集,
ABS_MT_POSITION_Y y[0] //第一个触摸点按下的y的位置。
ABS_MT_SLOT 1 //用slot 0表示第二个触摸点
ABS_MT_TRACKING_ID 46 //记录触摸点ID,用于区分触摸点
ABS_MT_POSITION_X x[1] //第二个触摸点按下的x位置。
ABS_MT_POSITION_Y y[1] //第二个触摸点按下的y位置。
SYN_REPORT //上报消息
手指移动
情况1:只有第一个触点45 移动x方向,如何报告?
ABS_MT_SLOT 0 //表示第一个触摸点
ABS_MT_POSITION_X x[0] //表示此时x的位置
SYN_REPORT //事件上报
情况2:两个触点都移动了x方向,如何报告?
ABS_MT_SLOT 0 //表示第一个触摸点
ABS_MT_POSITION_X x[0] //表示此时第一个触点x的位置
ABS_MT_SLOT 1 //表示第二个触摸点
ABS_MT_POSITION_X x[0] //表示此时第二个触点x的位置
SYN_REPORT //事件上报
此时可以看出,协议A是所有触点都上报,而协议B只上报变化的触点,因此减少了许多消息
手指抬起
情况1:第一跟手指抬起,第二根手指仍在滑动,如何报告?
ABS_MT_SLOT 0 //表示第一个触摸点
ABS_MT_TRACKING_ID -1 //表示第一个触点销毁
SYN_REPORT //事件上报
ABS_MT_SLOT 1
ABS_MT_POSITION_X x[0]
SYN_REPORT
情况二:两根手指都抬起,如何报告?
ABS_MT_SLOT 0 //表示第一个触摸点
ABS_MT_TRACKING_ID -1 //表示第一个触点销毁
SYN_REPORT //事件上报
ABS_MT_SLOT 1 //表示第二个触摸点
ABS_MT_TRACKING_ID -1 //表示第二个触点销毁
SYN_REPORT //事件上报
1.4.3 getevent -l motion事件分析
此处基于笔者手机获取信息如下:
1.4.3.1 当两根手指按下时
/dev/input/event8: EV_ABS ABS_MT_SLOT 00000000 //第一个触摸点 00000000
/dev/input/event8: EV_ABS ABS_MT_TRACKING_ID 00000010 //第一个触摸点 对应的id
/dev/input/event8: EV_KEY BTN_TOUCH DOWN // 当设备驱动报告了BTN_TOUCH键值,Android系统将认为BTN_TOUCH总是被用于指示触摸工具是否真正地接触触摸屏或仅仅在上方盘旋。
/dev/input/event8: EV_KEY BTN_TOOL_FINGER DOWN //BTN_TOOL_FINGER表示的是按键类型为手指
/dev/input/event8: EV_ABS ABS_MT_WIDTH_MAJOR 00000005 //触摸工具的主轴
/dev/input/event8: EV_ABS ABS_MT_TOUCH_MINOR 00000005 //触摸点最小轴
/dev/input/event8: EV_ABS ABS_MT_PRESSURE 00000005 //触摸压力大小
/dev/input/event8: EV_ABS ABS_MT_POSITION_X 000010fc //触摸点的x坐标
/dev/input/event8: EV_ABS ABS_MT_POSITION_Y 000075cc //触摸点的y坐标
/dev/input/event8: EV_ABS ABS_PROFILE 0000084e //ABS_PROFILE在多指触控协议中主要用于描述输入设备(如触摸屏)的一些物理特性。它可能包括设备的分辨率、尺寸、形状等参数
/dev/input/event8: EV_SYN SYN_REPORT 00000000 //事件上报
/dev/input/event8: EV_ABS ABS_MT_SLOT 00000001 //第二个触摸点 00000001
/dev/input/event8: EV_ABS ABS_MT_TRACKING_ID 00000011 //第二个触摸点 对应的id
/dev/input/event8: EV_ABS ABS_MT_TOUCH_MINOR 00000009 //触摸点最小轴
/dev/input/event8: EV_ABS ABS_MT_PRESSURE 00000009 //触摸压力大小
/dev/input/event8: EV_ABS ABS_MT_POSITION_X 000011f7 //触摸点的x坐标
/dev/input/event8: EV_ABS ABS_MT_POSITION_Y 000085d8 //触摸点的y坐标
/dev/input/event8: EV_ABS ABS_PROFILE 0000046a //ABS_PROFILE在多指触控协议中主要用于描述输入设备(如触摸屏)的一些物理特性。它可能包括设备的分辨率、尺寸、形状等参数
/dev/input/event8: EV_SYN SYN_REPORT //事件上报
1.4.3.2 当两根手指移动时
/dev/input/event8: EV_ABS ABS_MT_SLOT 00000000 //第一个触摸点
/dev/input/event8: EV_ABS ABS_MT_POSITION_X 0000110f //触摸点的x坐标
/dev/input/event8: EV_ABS ABS_MT_POSITION_Y 000075d4 //触摸点的y坐标
/dev/input/event8: EV_ABS ABS_MT_SLOT 00000001 //第二个触摸点
/dev/input/event8: EV_ABS ABS_MT_POSITION_X 00001237 //触摸点的x坐标
/dev/input/event8: EV_ABS ABS_MT_POSITION_Y 000085f6 //触摸点的y坐标
/dev/input/event8: EV_SYN SYN_REPORT 00000000 //事件上报
1.4.3.2 当两根手指抬起时
/dev/input/event8: EV_ABS ABS_MT_SLOT 00000000 //第一个触摸点
/dev/input/event8: EV_ABS ABS_MT_TRACKING_ID ffffffff //值为-1,代表第一个触摸点销毁
/dev/input/event8: EV_SYN SYN_REPORT 00000000
/dev/input/event8: EV_ABS ABS_MT_SLOT 00000001 //第二个触摸点
/dev/input/event8: EV_ABS ABS_MT_TRACKING_ID ffffffff //值为-1,代表第二个触摸点销毁
/dev/input/event8: EV_KEY BTN_TOUCH UP //当设备驱动报告了BTN_TOUCH键值,Android系统将认为BTN_TOUCH总是被用于指示触摸工具是否真正地接触触摸屏或仅仅在上方盘旋。
/dev/input/event8: EV_KEY BTN_TOOL_FINGER UP //表示按键类型为手指
/dev/input/event8: EV_SYN SYN_REPORT 00000000 //同步事件
后续
那么这些消息,input是如何处理的呢?后续的篇幅会根据源码进行逐行分析。欢迎关注。