Linux input子系统input设备应用编程

Posted Oudeyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux input子系统input设备应用编程相关的知识,希望对你有一定的参考价值。

copy from :https://blog.csdn.net/weixin_42462202/article/details/100060675

文章目录
Linux input子系统(一)input设备应用编程
一、使用hexdump读取input设备
二、input事件分析
三、input设备应用编程

Linux内核提供input子系统给输入设备驱动使用,input子系统可以屏蔽硬件的差异,向应用层提供一套统一的接口,常见的input设备有触摸屏、鼠标、键盘等
一、使用hexdump读取input设备
在Linux下查看ls /dev/input,可以看到现在有的输入设备

比如我的结果是

# ls /dev/input/
event0 event1 event2 mice mouse0 mouse1
1
2
这些都是通过input子系统实现的输入设备驱动,遵循input子系统规范

其中event2为我的触摸屏设备节点,通过下面命令读取(hexdump读取的数是以16进制打印)

# hexdump /dev/input/event2
1
当我点击触摸屏然后松开,发现控制台打印了许多消息

0247 0000 00d3 000e 0003 0000 02c4 0000
0247 0000 00db 000e 0003 0001 0181 0000
0247 0000 00de 000e 0001 014a 0001 0000
0247 0000 00e0 000e 0003 0018 0001 0000
0247 0000 00e2 000e 0000 0000 0000 0000
0248 0000 c838 0002 0001 014a 0000 0000
0248 0000 c876 0002 0003 0018 0000 0000
0248 0000 c89f 0002 0000 0000 0000 0000

其中每一行都表示一个input事件,如果单纯这样子看是分析不出所以然的,我们需要先介绍input事件,然后再来分析

二、input事件分析
input事件结构体的定义如下,在Linux内核的includelinuxinput.h文件中

struct timeval {
__kernel_time_t tv_sec; /* seconds,32bit */
__kernel_suseconds_t tv_usec; /* microseconds,32bit */
};

struct input_event {
struct timeval time; //时间
__u16 type; //事件类型
__u16 code; //事件键值
__s32 value; //值
};

可以看到,每一个input事件都有一个时间,包含32位的秒,32位的微妙

此外还有16位的type(事件类型),16位的code(事件键值),32位的value(值)

好,现在又有疑惑,type、code、value具体是什么?

type

type是指事件类型,在includelinuxinput.h文件中定义了一系列的事件类型

#define EV_SYN 0x00 //同步事件,用于分隔事件
#define EV_KEY 0x01 //按键事件,例如按键、鼠标按键、触摸屏按键
#define EV_REL 0x02 //相对位置事件,常见于鼠标坐标
#define EV_ABS 0x03 //绝对位置事件,常见于触摸屏坐标
...

一个设备可以有多种类型的事件,例如鼠标点击按键时会上报按键事件,移动时会上报相对位置事件

code

code指事件的键值,在事件类型中的子事件,每一个事件类型都有其对应的一系列键值

例如按键事件,那么你这个按键表示按键1还是按键2还是鼠标左键

例如绝对位置事件,那么你上报的这个事件是指X轴还是Y轴

在includelinuxinput.h文件中定义了一系列的事件键值

按键事件的键值

#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
...
#define KEY_A 30
#define KEY_S 31
#define KEY_D 32
...

相对位置事件的键值

#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 ABS_X 0x00
#define ABS_Y 0x01
#define ABS_Z 0x02
...
#define ABS_PRESSURE 0x18
...

还有其他的事件类型这里就不详述了

value

value是code(键值)对应的值,其解释随code类型的变化而变化

例如在按键事件中,如果code表示按键1,那么value等于1表示按键1按下,等于0等于按键1未按下

在绝对位置事件中,如果code表示X轴坐标,那么value就表示触摸点在X轴坐标的位置

到这里应该就对input事件的理解很清除了,有了这些理解,下面我们来解析一下上面使用hexdump读取到的数据

由于前64位表示的是事件,所以这里就不解析了

s |us |type|code|value
1: 0247 0000 00d3 000e 0003 0000 02c4 0000 //EV_ABS、ABS_X、708
2: 0247 0000 00db 000e 0003 0001 0181 0000 //EV_ABS、ABS_Y、385
3: 0247 0000 00de 000e 0001 014a 0001 0000 //EV_KEY、BTN_TOUCH、1
4: 0247 0000 00e0 000e 0003 0018 0001 0000 //EV_ABS、ABS_PRESSURE、1
5: 0247 0000 00e2 000e 0000 0000 0000 0000 //EV_SYN
6: 0248 0000 c838 0002 0001 014a 0000 0000 //EV_KEY、BTN_TOUCH、0
7: 0248 0000 c876 0002 0003 0018 0000 0000 //EV_ABS、ABS_PRESSURE、0
8: 0248 0000 c89f 0002 0000 0000 0000 0000 //EV_SYN

1:绝对位置事件,X轴708处

2:绝对位置事件,Y轴385处

3:按键事件,触摸屏按键,1表示按下

4:绝对位置事件,绝对位置按压,压力为1(有些触摸屏是有压力检测的,这款触摸屏没有所以直接上报了1)

5:同步事件,用于分隔

6:按键事件,触摸屏按键,0表示松开

7:绝对位置事件,绝对位置按压,压力为0,表松开

8:同步事件

三、input设备应用编程
搞清除input事件后,编写一个应用其实非常简单,以触摸屏为例子,我们可以直接读取struct input_event对象,然后根据type、code、key来解析

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <linux/input.h>

int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("Usage: %s <input dev> ", argv[0]);
return -1;
}

int fd = open(argv[1], O_RDONLY);
if(fd < 0)
{
printf("failed to open %s ", argv[1]);
return -1;
}

struct input_event event;
int x = 0, y = 0;
while(1)
{
memset(&event, 0, sizeof(event));
read(fd, &event, sizeof(event));
if(event.type == EV_SYN)
continue;

if(event.type == EV_ABS)
{
if(event.code == ABS_X)
x = event.value;
else if(event.code == ABS_Y)
y = event.value;
}
else if(event.type == EV_KEY)
{
if(event.value == 1)
{
printf("touch press (%d,%d) ", x, y);
}
else if(event.value == 0)
{
printf("touch release (%d,%d) ", x, y);
x = 0;
y = 0;
}
}
else
continue;
}

close(fd);

return 0;
}
————————————————
版权声明:本文为CSDN博主「JT同学」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42462202/article/details/100060675

 

以上是关于Linux input子系统input设备应用编程的主要内容,如果未能解决你的问题,请参考以下文章

Linux input子系统应用编程(10)查看与/dev/input目录下的event对应的设备

Linux系统编程应用 Linux Input子系统

Linux input子系统编程分析与模板

Linux设备驱动之input子系统

input子系统

linux input输入子系统应用分析