哈喽,大家好,我是LittleG。
如果将 Linux 比作一个人,那么Linux input子系统就好比我们的眼睛,手,脚,以及到大脑的神经网络,可以通过它们获取和传递信息,感知外围世界。回到 Linux/Android 世界,像手机设备中,按键、触摸屏、各种sensor,数据流一般也是走的input子系统上报给上层的,所以学习和理解input子系统很重要。
正文
#include <linux/input.h>
在这个文件中,我们可以找到这个结构体:
描述一个输入事件 /* * The event structure itself */ struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value; };
先来解读下这个结构体的含义:
struct timeval结构体在time.h中的定义为:
struct timeval { __time_t tv_sec; /* Seconds. */ __suseconds_t tv_usec; /*Microseconds. */ };
【time】
域的 tv_sec 为Epoch到创建struct timeval时的秒数,tv_usec为微秒数,即秒后面的零头。
【type】
域显示了被报告事件的类型,例如,一个 key press或者 button press, relative motion(比如移动鼠标 ) 或者 absolute motion(比如移动游戏杆 ); 常用的事件类型 type
有 EV_KEY , EV_REL , EV_ABS , EV_SYN ;分别对应keyboard事件,相对事件,绝对事件,同步事件;EV_SYN 则表示一组完整事件已经完成,需要处理;
【code】
域根据type
的不同而含义不同,上报是哪一个key或者哪一个坐标轴在被操作; 例如,type
为 EV_KEY 时,code表示键盘code或者鼠标Button值;type
为 EV_REL 时,code表示操作的是哪个坐标轴,如:REL_X,REL_Y (因为鼠标有x,y两个轴向,所以一次鼠标移动,会产生两个input_event);type
为 EV_ABS 时,code表示绝对坐标轴向。
【value】
域也是根据type
的不同而含义不同,上报现在的状态或者运动情况是什么。例如:type
为EV_KEY时,value:0表示按键抬起,1表示按键按下;(4表示持续按下等?)type
为EV_REL时,value: 表明移动的值和方向(正负值);type
为EV_ABS时,value: 表示绝对位置;
那么,最主要的事件有以下三种:相对事件(鼠标),绝对事件(触摸屏),键盘事件。
例如:
我们说鼠标,我们在移动鼠标的时候鼠标就是一个相对事件,所以type的类型也就是底层上报给用户的事件为相对事件类型,那么code表示的就是相对于鼠标当前的位置的X或者Y的坐标,value也就是相对于当前的位置偏移多少。
事件类型(type)在 input.h 主要有以下:
/* * Event types */ #define EV_SYN 0x00 //同步事件,就是将结果上报给系统的过程 #define EV_KEY 0x01 //按键事件,如 KEY_VOLUMEDOWN 事件 #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 //声音 #define EV_REP 0x14 //Repeat #define EV_FF 0x15 //力反馈 #define EV_PWR 0x16 //电源 #define EV_FF_STATUS 0x17 //状态 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1)
以鼠标为例,涉及鼠标的事件读取/控制相关的code有:
/* * Relative axes */ //在这里,我们暂时只会用来REL_X和REL_Y这两个参数 #define REL_X 0x00 //相对X坐标 #define REL_Y 0x01 //相对Y坐标 #define REL_Z 0x02 //相对Z坐标 #define REL_RX 0x03 #define REL_RY 0x04 #define REL_RZ 0x05 #define REL_HWHEEL 0x06 #define REL_DIAL 0x07 #define REL_WHEEL 0x08 #define REL_MISC 0x09 #define REL_MAX 0x0f #define REL_CNT (REL_MAX+1)
最后value,就是选择具体的type、具体的code以后所反应出来的值,鼠标就是相对于当前X或者相对于当前Y的值。
接下来,我们来看一下如何来读取鼠标事件,写一段代码测试一下:
#include <stdio.h> #include <linux/input.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> /* struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value; }; */ /* Event types #define EV_SYN 0x00 #define EV_KEY 0x01 #define EV_REL 0x02 #define EV_ABS 0x03 */ /* Relative axes #define REL_X 0x00 #define REL_Y 0x01 #define REL_Z 0x02 #define REL_RX 0x03 #define REL_RY 0x04 #define REL_RZ 0x05 #define REL_HWHEEL 0x06 #define REL_DIAL 0x07 #define REL_WHEEL 0x08 #define REL_MISC 0x09 #define REL_MAX 0x0f #define REL_CNT (REL_MAX+1) */ //event8 mouse //event9 keyboard int main(void) { //1、定义一个结构体变量用来描述input事件 struct input_event event_mouse ; //2、打开input设备的事件节点 我的电脑鼠标事件的节点是event3 int fd = open("/dev/input/event3",O_RDWR); int value ; int type ; int buffer[10]={0}; if(-1 == fd){ printf("open mouse event fair!n"); return -1 ; } while(1){ //3、读事件 read(fd ,&event_mouse ,sizeof(event_mouse)); //4、判断事件类型,并打印键码 switch(event_mouse.type){ case EV_SYN: printf("sync!n"); break ; case EV_REL: //鼠标事件,XY相对位移 //code表示相对位移X或者Y,当判断是X时,打印X的相对位移value //当判断是Y时,打印Y的相对位移value if(event_mouse.code == REL_X){ printf("event_mouse.code_X:%dn",event_mouse.code); printf("event_mouse.value_X:%dn",event_mouse.value); } if(event_mouse.code == REL_Y){ printf("event_mouse.code_Y:%dn",event_mouse.code); printf("event_mouse.value_Y:%dn",event_mouse.value); } defalut: break ; } } return 0 ; }
附:在Linux系统下通过如下命令可以看到所有的input设备
cat /proc/bus/input/devices
I: Bus=0000 Vendor=0000 Product=0000 Version=0000 N: Name="qpnp_pon" P: Phys=qpnp_pon/input0 S: Sysfs=/devices/platform/soc/c440000.qcom,spmi/spmi-0/spmi0-00/c440000.qcom,spmi:qcom,pm8150@0:qcom,power-on@800/input/input0 U: Uniq= H: Handlers=event0 cpufreq B: PROP=0 B: EV=3
B: KEY=600000000000000 0 14000000000000 0
............
I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="light"
P: Phys=
S: Sysfs=/devices/virtual/input/input3
U: Uniq=
H: Handlers=event3
B: PROP=0
B: EV=5
B: REL=3
......
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="gpio-keys"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/platform/soc/soc:gpio_keys/input/input6
U: Uniq=
H: Handlers=event6 cpufreq
B: PROP=0
B: EV=3
B: KEY=8000000000000 0
下期见~