Linux下struct input_event结构体详解

4.4 触控屏应用接口

4.4.1 输入子系统简介

连接操作系统的输入设备,可不止一种,也许是一个标准 PS/2 键盘,也许是一个 USB鼠标,或者是一块触摸屏,甚至是一个游戏机摇杆,Linux 在处理这些纷繁各异的输入设备的时候,采用的办法还是找中间层来屏蔽各种细节,请看下图:
在这里插入图片描述
在 Linux 的内核中,对输入设备的使用,实际上运用了 3 大块来管理,他们分别是所谓的输入设备驱动层输入子系统核心层,以及事件触发层。他们各自的工作分别是:

1,输入设备驱动层:

每一种设备都有其特定的驱动程序,他们被妥当地装载到操作系统的设备模型框架内,封装硬件所提供的功能,向上提供规定的接口。

2,核心层:

此处将收集由设备驱动层发来的数据,整合之后触发某一事件。
3,事件触发层:
这一层是我们需要关注的,我们可以通过在用户空间读取相应设备的节点文件来获知某设备的某一个动作。在最靠近应用程序的事件触发层上,内核所获知的各类输入事件,比如键盘被按了一下,触摸屏被滑了一下等,都将被统一封装在一个叫做 input_event 的结构体当中,这个结构体定义如下:

(/usr/inlucde/linux/input.h)
vincent@ubuntu:/usr/inlucde/linux/$ cat input.h -n
1 #ifndef _INPUT_H
2 #define _INPUT_H
3……
20
21 struct input_event {
22 struct timeval time;
23 __u16 type;
24 __u16 code;
25 __s32 value;
26 };
27……

该结构体有 4 个成员,其含义分别如下:
一、time:输入事件发生的时间戳,精确到微秒。时间结构体定义如下:

struct timeval
{ __time_t tv_sec; // 秒
long int tv_usec; // 微秒(1 微秒 = 10-3毫秒 = 10-6秒)
};

二、type:输入事件的类型。比如:
EV_SYN:事件间的分割标志,有些事件可能会在时间和空间上产生延续,比如持续按住一个按键。为了更好地管理这些持续的事件,EV_SYN 用以将他们分割成一个个的小的数据包。
EV_KEY:用以描述键盘,按键或者类似键盘的设备的状态变化。
EV_REL:相对位移,比如鼠标的移动,滚轮的转动等。
EV_ABS:绝对位移,比如触摸屏上的坐标值。
EV_MSC:不能匹配现有的类型,这相当于当前暂不识别的事件。比如在 Linux系统中按下键盘中针对 Windows 系统的“一键杀毒”按键,将会产生该事件。
EV_LED:用于控制设备上的 LED 灯的开关,比如按下键盘的大写锁定键,会同时产生 ”EV_KEY” 和 ”EV_LED” 两个事件。

三、code:这个“事件的代码”用于对事件的类型作进一步的描述。比如:当发生 EV_KEY事件时,则可能是键盘被按下了,那么究竟是哪个按键被按下了呢?此时查看 code 就知道了。当发生 EV_REL 事件时,也许是鼠标动了,也许是滚轮动了。这时可以用 code 的值来加以区分。

四、value:当 code 都不足以区分事件的性质的时候,可以用 value 来确认。比如由EV_REL 和 REL_WHEEL 确认发生了鼠标滚轮的动作,但是究竟是向上滚还是向下滚呢?
再比如由由 EV_KEY 和 KEY_F 确认了发生键盘上 F 键的动作,但究竟是按下呢还是弹起呢?这时都可以用 value 值来进一步判断。
以下代码,展示了如何从触摸屏设备节点/dev/event0 中读取数据,并显示当前触摸屏的实时原始数据:

vincent@ubuntu:~/ch04/4.5$ cat ts_raw.c -```
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <strings.h>
7 #include <errno.h>
8
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <fcntl.h>
12 #include <Linux/input.h>
13
14 int main(int argc, char **argv)
15 {
16 int ts = open("/dev/event0", O_RDONLY);
17
18 struct input_event buf;
19 bzero(&buf, sizeof(buf));
20
21 while(1)
22 {
23 read(ts, &buf, sizeof(buf));
24
25 switch(buf.type)
26 {
27 case EV_SYN:
28 printf("--------------------- SYN ------------------\n");
29 break;
30 case EV_ABS:
31 printf("time: %u.%u\ttype: EV_ABS\t", 32 buf.time.tv_sec, buf.time.tv_usec);
33 switch(buf.code)
34 {
35 case ABS_X:
36 printf("X:%u\n", buf.value);
37 break;
38 case ABS_Y:
39 printf("Y:%u\n", buf.value);
40 break;
41 case ABS_PRESSURE:
42 printf("pressure:%u\n", buf.value);
43 }
44 }
45 }
46 return 0;
47 }

注意,以上代码打印出来的是直接从触摸屏读取的原始数据(raw data),没有经过任何校正,也没有任何滤波、去抖、消噪,因此这些数据是不能直接给应用层程序使用的,但是不用担心,这些繁琐复杂的工作已经有了很成熟的库支持了,但是有一个TSLIB 库,就是这样一个开源的、能为触摸屏获得的原始数据提供诸如滤波、去抖、消噪和校正功能的库,TSLIB 作为触摸屏驱动的适配层,为上层的应用提供了一个统一的编程接口,将使得我们编写基于触摸屏的应用更加简便。

  • 13
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 内核中,input_dev 结构体表示一个输入设备。它的定义在 `<linux/input.h>` 头文件中,包含了以下成员: - `char *name`:输入设备的名称。 - `struct bus_type *bus`:输入设备所连接的总线类型。 - `unsigned int id.bustype`:输入设备所连接的总线类型。 - `unsigned int id.vendor`:输入设备供应商 ID。 - `unsigned int id.product`:输入设备产品 ID。 - `unsigned int id.version`:输入设备版本号。 - `unsigned long evbit[EV_MAX/32 + 1]`:标志设备支持的事件类型,例如 EV_KEY、EV_REL、EV_ABS、EV_LED、EV_SND、EV_SW 和 EV_MSC 等。 - `unsigned long keybit[KEY_MAX/32 + 1]`:标志设备支持的键位,例如 KEY_ESC、KEY_ENTER、KEY_A 等。 - `unsigned long relbit[REL_MAX/32 + 1]`:标志设备支持的相对坐标事件,例如 REL_X、REL_Y 等。 - `unsigned long absbit[ABS_MAX/32 + 1]`:标志设备支持的绝对坐标事件,例如 ABS_X、ABS_Y 等。 - `unsigned long mscbit[MSC_MAX/32 + 1]`:标志设备支持的杂项事件,例如 MSC_SERIAL、MSC_PULSELED 等。 - `unsigned long key_len`:键位数组的长度。 - `unsigned long rel_len`:相对坐标事件数组的长度。 - `unsigned long abs_len`:绝对坐标事件数组的长度。 - `unsigned long msc_len`:杂项事件数组的长度。 - `unsigned long key_cnt`:键位个数。 - `unsigned long rel_cnt`:相对坐标事件个数。 - `unsigned long abs_cnt`:绝对坐标事件个数。 - `unsigned long msc_cnt`:杂项事件个数。 - `int (*open)(struct input_dev *dev)`:设备打开函数指针。 - `void (*close)(struct input_dev *dev)`:设备关闭函数指针。 - `int (*flush)(struct input_dev *dev, struct file *file)`:设备刷新函数指针。 - `int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value)`:设备事件处理函数指针。 - `int (*set_keycode)(struct input_dev *dev, const struct input_keymap_entry *ke, unsigned int *old_keycode)`:设备设置键位函数指针。 - `int (*getkeycode)(struct input_dev *dev, struct input_keymap_entry *ke)`:设备获取键位函数指针。 - `int (*set_drvdata)(struct input_dev *dev, void *data)`:设备设置私有数据函数指针。 - `void *driver_data`:设备私有数据指针。 这些成员描述了输入设备的基本属性,支持的事件类型和事件处理函数等。在注册输入设备时,需要设置这些成员的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值