目录

一、输入设备

二、input 子系统

三、读取数据的流程

四、解析数据

具体事件

①按键类事件

②相对位移事件

③绝对位移事件

五、数据同步

六、编写代码之读取 struct input_event 数据

代码如下

验证

现象解释

七、编写按键APP


一、输入设备

输入设备其实就是能够产生输入事件的 设备就称为输入设备,常见的输入设备包括鼠标、键盘、触摸屏、按钮等等,它们都能够产生输入事件,产 生输入数据给计算机系统。 对于输入设备的应用编程其主要是获取输入设备上报的数据、输入设备当前状态等,譬如获取触摸屏当 前触摸点的 X、Y 轴位置信息以及触摸屏当前处于按下还是松开状态

二、input 子系统

Linux 系统为了统一管理这些输入设备,实现了一套能够兼容所有输入设备的框架,那么这个框架就 是 input 子系统。基于 input 子系统开发的输入设备的驱动程序,input 子系统可以屏蔽硬件的差 异,向应用层提供一套统一的接口,方便开发。

基于 input 子系统注册成功的输入设备,都会在/dev/input 目录下生成对应的设备节点(设备文件),设 备节点名称通常为 eventX(X 表示一个数字编号 0、1、2、3 等),譬如/dev/input/event0、/dev/input/event1、 /dev/input/event2 等,通过读取这些设备节点可以获取输入设备上报的数据。

三、读取数据的流程

假如要读取触摸屏的数据,假设触摸屏设备对应的设备节点为/dev/input/event0,那么数据读取流程如下:

①、应用程序打开/dev/input/event0 设备文件;
②、应用程序发起读操作(譬如调用 read),如果当前并没有去触碰触摸屏是没有数据可读,则会进入休眠(阻塞 I/O 情况下);
③、 用手指触摸触摸屏或者在屏上滑动时,此时就会产生触摸数据,当有数据可读时,应用程序会被唤醒,读操作获取到数据返回;
④、应用程序对读取到的数据进行解析。

对于其它输入设备亦是如此,无数据可读时应用程序会进入休眠状态(阻塞式 I/O 方式下), 当有数据可读时才会被唤醒。

四、解析数据

每一次 read 操作获取的都是一个 struct input_event 结构体类型数据, 该结构体定义在<linux/input.h>头文件中,它的定义如下:

struct input_event {
        struct timeval time;
        __u16 type;
        __u16 code;
        __s32 value;
};

 time 成员变量是一个 struct timeval 类型的变量, 内核会记录每个上报的事件其发生的时间,并通过变量 time 返回给应用程序,struct timeval 结构体如下

struct timeval {

long tv_sec; /* 秒 *

long tv_usec; /* 微秒 */ };

 type: type 用于描述发生了哪一种类型的事件(对事件的分类),分类宏定义也是在<linux/input.h>头文件中,下面列出其中几种

#define EV_SYN 0x00 //同步类事件,用于同步事件
#define EV_KEY 0x01 //按键类事件
#define EV_REL 0x02 //相对位移类事件(譬如鼠标)
#define EV_ABS 0x03 //绝对位移类事件(譬如触摸屏)
#define EV_MSC 0x04 //其它杂类事件

一种输入设备通常可以产生多种不同类型的事件,譬如点击鼠标按键(左键、右键,或鼠标上的其它按键)时会上报按键类事件,移动鼠标时则会上报相对位移类事件。

code: code 表示该类事件中的哪一个具体事件, 以上列举的每一种事件类型中都包含了一系列具体事件, 譬如一个键盘上通常有很多按键, 譬如字母 A、 B、 C、 D 或者数字 1、 2、 3、 4 等, 而 code变量则告知应用程序是哪一个按键发生了输入事件

具体事件

下面仅是列出几个常见的,可以自行浏览<linux/input.h>头文件,这些宏其实是定义在
input-event-codes.h 头文件中,该头文件被<linux/input.h>所包含了

①按键类事件

#define KEY_RESERVED 0
#define KEY_ESC 1     //ESC 键
#define KEY_1 2       //数字 1 键
#define KEY_2 3       //数字 2 键
#define KEY_TAB 15    //TAB 键
#define KEY_Q 16      //字母 Q 键
#define KEY_W 17      //字母 W 键
.....

②相对位移事件

#define REL_X 0x00 //X 轴
#define REL_Y 0x01 //Y 轴
#define REL_Z 0x02 //Z 轴
#define REL_MISC 0x09
#define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1)
.....

③绝对位移事件

触摸屏设备是一种绝对位移设备,它能够产生绝对位移事件; 譬如对于触摸屏来说,一个触摸点所包含的信息可能有多种,譬如触摸点的 X 轴坐标、 Y 轴坐标、 Z 轴坐标、按压力大小以及接触面积等, 所以 code变量告知应用程序当前上报的是触摸点的哪一种信息(X 坐标还是 Y 坐标、亦或者其它)

#define ABS_X 0x00 //X 轴
#define ABS_Y 0x01 //Y 轴
#define ABS_Z 0x02 //Z 轴
#define ABS_PRESSURE 0x18
#define ABS_DISTANCE 0x19
#define ABS_TILT_X 0x1a
#define ABS_TILT_Y 0x1b
....

value: 内核每次上报事件都会向应用层发送一个数据 value, 对 value 值的解释随着 code 的变化而变化。

譬如对于按键事件(type参数=1) 来说, 假如code的值=2(2代表是键盘上的数字键 1,也就是 KEY_1), 那么如果 value 等于 1,则表示 KEY_1 键按下; value 等于 0 表示 KEY_1 键松开,如果 value 等于 2则表示 KEY_1 键长按

再比如, 在绝对位移事件中(type参数=3),如果 code=0 (触摸点 X 坐标 ABS_X),那么 value 值就等于触摸点的 X 轴坐标值; 同理, 如果 code=1(触摸点 Y 坐标 ABS_Y),此时
value 值便等于触摸点的 Y 轴坐标值; 所以对 value 值的解释需要根据不同的 code 值而定

五、数据同步

上面类型中有同步事件类型 EV_SYN,同步事件用于实现同步操作、告知接收者本轮上报的数据已经完整。应用程序读取输入设备上报的数据时,一次 read 操作只能读取一个 struct input_event 类型数据

譬如对于触摸屏来说,一个触摸点的信息包含了 X 坐标、 Y 坐标以及其它信息, 对于这样情况,应用程序需要执行多次 read 操作才能把一个触摸点的信息全部读取出来, 这样才能得到触摸点的完整信息。

内核将本轮需要上报、发送给接收者的数据全部上报完毕后,接着会上报一个同步事件,以告知应用程序本轮数据已经完整、 可以进行同步了。

同步类事件中也包含了多种不同的事件,所有的输入设备都需要上报同步事件, 上报的同步事件通常是 SYN_REPORT, 而 value 值通常为 0

六、编写代码之读取 struct input_event 数据

对输入设备调用 read()会读取到一个 struct input_event 类型数据,下面利用按下按键来看一下获取到的数据

         13行,先定义一个 struct input_event 类型并初始化成员值为0,16行判断传参是否正确,21行打开传递进来的文件路径,然后一直循环读取,28行,将读取到的数据存在结构体中并判断读取的数据量是否相等,最后打印成员的值

程序中使用了阻塞式 I/O 方式读取设备文件,所以当无数据可读时 read 调用会被阻塞,知道有数据可读时才会被唤醒。设备文件不同于普通文件,读写设备文件之前无需设置读写位置偏移量

代码如下

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <linux/input.h>int main(int argc,char *argv[])
{struct input_event in_ev={0};int fd = -1;if(argc != 2){fprintf(stderr,"usage:%s <input-dev>\r\n",argv[0]);exit(-1);}if((fd = open(argv[1],O_RDONLY))<0){perror("open error");exit(-1);}for(;;){if(sizeof(struct input_event) != read(fd,&in_ev,sizeof(struct input_event))){perror("read error");exit(-1);}printf("type:%d code:%d value:%d\n",in_ev.type,in_ev.code,in_ev.value);}
}

验证

在开发板上通过查看/proc/bus/input/devices 文件可以得知系统中注册的所有输入设备相关的信息,如下

根据自己开发板的实际情况选择设备测试,N后面的表示名字,H后面表示设备节点文件,比如这里使用的按键,通过看名字可以知道对应就是gpio_keys,那么H就是event1文件,驱动基于 input 子系统而实现的, 在/dev/input 目录下存在 KEY0 的设备节点,具体设备是event1,如下

把文件从ubantu传到开发板,从上面得知按键设备节点路径就是 /dev/input/event1,测试1如下

运行app时,把设备节点路径作为传参,接着按一下按键,就能看到结构体对应的数据打印出来了

现象解释

根据前面的介绍,第一行中 type 等于 1,表示上报的是按键事件 EV_KEY, code=114, 打开 input-event-codes.h 头文件进行查找,可以发现 cpde=114 对应的是键盘上的 KEY_VOLUMEDOWN 按键,如下,这个是开发板出厂系统配置好的

value=1 表示按键按下,所以整个第一行的意思就是按键 KEY_VOLUMEDOWN被按下。

第二行, 表示上报了 EV_SYN 同步类事件(type=0)中的 SYN_REPORT 事件(code=0), 表示本轮数据已经完整、报告同步

第三行, type 等于 1,表示按键类事件, code 等于 114、而value 等于 0,所以表示按键 KEY_VOLUMEDOWN被松开

第四行上报同步事件

所以整个上面 4 行的打印信息就是开发板上的 KEY0 按键被按下以及松开这个过程, 内核所上报的事件以及发送给应用层的数据 value

试试长按按键 KEY0, 按住不放, 如下所示:

可以看到上报按键事件时,对应的 value 等于 2,表示长按状态

七、编写按键APP

编写一个获取按键状态的APP, 判断按键当前是按下、松开或长按状态。

从上面可知,对于按键来说,如果是按下,则上报 KEY 事件时, value=1;如果是松开,则 value=0;如果是长按,则 value=2,代码和上面的差不多,简单修改一下

35行判断具体事件是不是按键事件EV_KEY,然后37行根据value值来打印具体按键状态

测试如下

除了测试开发板的按键,也可以用开发板接上一个键盘,驱动会自动设别到键盘的,然后查看该键盘对应的设备节点,再用app测试即可,和上面操作同理

输入设备之按键(键盘)相关推荐

  1. 重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop...

    重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop 原文:重新想象 Window ...

  2. C# 多输入设备识别 扫码枪键盘区分RAWINPUT原始输入简易开发笔记

    工作需要写了一个小程序,结合cefsharp利用erp软件的api进行二次开发,实现定制功能.软件会用到扫码枪扫描快递单号发货.会用到蓝牙电子称称重.还会遇到快递拆单快速新建订单并打印订单,也需要用到 ...

  3. 41 linux标准输入设备之矩阵键盘驱动的实现

    准备知识点: 原子位操作 , linux输入设备的应用程序编程 在linux内核里用struct input_dev的一个对象来表示一个输入设备. 用一位二进制表示是否支持相应的功能, 多种功能需要多 ...

  4. 鼠标和键盘属于计算机系统的输入设备,鼠标和键盘是电脑系统输入设备,Win10收到数据和指令后开始处理...

    哈喽,大家晚上好,我是一天不写点什么就感觉浑身不舒坦的沐沐君说软件.书接上回,今天小编将为小伙伴们介绍Windows 10操作系统如何设置鼠标和键盘.2021年1月20日是二十四节气大寒又恰逢腊八节, ...

  5. 通过替换音效文件,实现在安卓手机上使用wp/nokia/wm10按键键盘声音

    wp/wm10手机的上的输入法"哒哒哒"的音效非常棒,换了安卓手机后google输入法的按键音就简直太糟糕了,于是我们可以通过提取wp的键盘音效替换安卓的音效来实现在安卓手机上使用 ...

  6. android 重映射按键,键盘重映射的终极教程 | MOS86

    许多电脑用户认为电脑键盘上不同按键提供的功能固定在石头上,根本无法改变.大多数人可能会惊讶地发现可以重新映射Windows中的电脑键盘上的所有键. 但是为什么有人想要更改键盘上的特定键,以便它们具有不 ...

  7. android平板对接扫码枪,切换输入设备弹出键盘问题

    本来可以切换成虚拟串口,但是已经有另外一个设备对接串口了,再加上usb转串口模式调试起来费时费力,项目赶就用了简单的输入输入方式,就等于扫码枪类似一个外接键盘,但是应用效果希望无感,所以用了一个比较取 ...

  8. php键盘按键,键盘常用15个功能键

    电脑操作的熟练程度决定了你电脑办公的效率,而效率的高低又一定程度决定了你运用信息技术的能力. 你是否知道,电脑刚发明的时候是没有鼠标的? (推荐学习:web前端视频教程) 如今的程序员几乎也是不用鼠标 ...

  9. kernel:driver_learn_summary

    Sysfs以及设备模型 Sysfs被加载在 /sys/目录下,它的子目录包括 1)Block:在系统中发现的每个块设备在该目录下对应一个子目录.每个子目录中又包含一些属性文件,它们描述了这个块设备的各 ...

最新文章

  1. 【舒工强烈推荐】命令添加Git远程仓库
  2. 过滤请求绝技,布隆过滤器与布谷鸟过滤器
  3. Nutanix企业云助力广播传媒的融合媒体发展之路
  4. Visual Studio 2017错误:无法启动程序,在当前状态下操作不合法
  5. fastcgi pass php-fpm,Nginx中fastcgi_pass的配置问题
  6. python 读取geotiff_科学网—利用python GDAL库读写geotiff格式的遥感影像方法 - 张伟的博文...
  7. 程序员的大恩人永远地离开了
  8. powerdesigner数据字典导出模板设置
  9. 公司装了cofax传真服务器真的解决了收发传真时存在的诸多不便
  10. 电脑如何设置u盘启动,u盘启动项设置方法
  11. android dlna uri,android DLNA投屏
  12. mysql 三门课程平均分_平均分
  13. acwing.回文质数
  14. 平安人寿“内鬼”泄露近4万条公民信息
  15. 大容量U盘计算机会不识别吗,电脑无法识别大容量U盘,怎么处理
  16. 手机虚拟化--人人都只用手机了
  17. Python 打造基于有道翻译的命令行翻译工具(命令行爱好者必备)
  18. 看了必懂的并查集原理(转载)
  19. Kafka Eagle
  20. linux系统分区加密,Linux系统的几种加密

热门文章

  1. 06 系统建模语言SysML——内部模块图
  2. JUnit单元测试%MODULE_WORKING_DIR%' does not exist
  3. 高等数学——反常积分的收敛法
  4. 关于最近的感想以及贴些图论模板
  5. 纪录一年多来项目管理的经历
  6. 如何下载西城区卫星地图高清版大图?
  7. Ubuntu搭建pptp服务器(保姆级)
  8. 基于QCustomPlot的实时曲线图
  9. 定义长方体类,数据成员有长、宽、高,成员函数有带默认形参值的构造函数(默认长宽高分别为2.5、3.4、2)、计算体积函数,分别构造默认对象和长宽高分别为6.25、4.8、5.2的对象,输出各对象的体积
  10. TYVJ1288 飘飘乎居士取能量块