哈喽,大家好,我是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
下期见~
2412
下载ECAD模型