Linux驱动开发十六.input系统——2.input_event

news/2024/4/28 18:31:17/文章来源:https://www.cnblogs.com/yinsedeyinse/p/16631438.html

我们上一章完成了input子系统的设备构成,并且在用户空间通过hexdump命令拿到了一堆不知道是什么的信息。今天我们就要借助input_event这个结构体来了解内核怎么通过那个结构体了解输入事件。

可能有心人已经发现了,上一章我们在加载完模块以后在/dev/input路径下生成了一个新的event文件

 

 在按键被按下以后,驱动就会向内核上报一个输入事件,而不同的输入设备都会有不同的实际内容上报给内核。所以Linux内核就整定了一个通用的结构体来描述每个事件。我们在用户态的程序就可以通过上面图中的event1来了解按键的实际状态。

input_event结构

想要知道event1文件在按键按下时打印的内容

首先要知道input_event结构体的内容(include/uapi/linux/input.h,注意路径,不要搞错了!)

 1 /*
 2  * The event structure itself
 3  */
 4 
 5 struct input_event {
 6     struct timeval time;
 7     __u16 type;
 8     __u16 code;
 9     __s32 value;
10 };

input_event结构体的内容很简单,先是一个timval结构体,这个结构体也可以展开看看!

1 struct timeval {
2     __kernel_time_t        tv_sec;        /* seconds */
3     __kernel_suseconds_t    tv_usec;      /* microseconds */
4 };

一个秒,一个微秒,查到底两个变量都是long型的数据,也就是32位的数据。

type就是事件类型,在我们驱动中定义的是EV_KEY。16位

code,事件码,在按键驱动中就是我们定义的键值。16位

value,值,在驱动中用来描述按键是否被按下或松开。32位

可以注意到,这个input_event结构体里后三个成员跟前面input_event函数中后面三个参数是一样的。按照上面的数据结构可以分析一下打印出来的信息,可以发现是这种结构的

编号          timeval_sec    timeval_usec     type         code      value
0000000      2217 0000       d132 0005       0001         000b       0001 0000
0000010      2217 0000       d132 0005       0000         0000       0000 0000
0000020      2217 0000       e29b 0006       0001         000b       0000 0000
0000030      2217 0000       e29b 0006       0000         0000       0000 0000

上面的信息都是由16进制来表示的,所以每个0都表示了4个bit。

第一组是编号,表示

第2、3列表示秒,一共8个数字,对应32位

第4、5列表示微秒

第6列为事件类型,对应EV_KEY,第一行是0001,就是对应的EV_KEY的值,第2行的0000对应EV_SYN事件

#define EV_SYN            0x00
#define EV_KEY            0x01

就是说按键在按下的时候,会上报一个EV_KEY事件,然后在定时处理函数里还调用了一个同步函数

input_sync(dev->inputdev);

可以转到这个函数的定义看一下,这个函数会上报一个EV_SYN信号

1 static inline void input_sync(struct input_dev *dev)
2 {
3     input_event(dev, EV_SYN, SYN_REPORT, 0);
4 }

所以就会有第2行那个0000,对应的type就是EV_SYN。

第7列是code,对应我们定义的key_value,我们在初始化input_dev的时候定义的事件code是keybit,值为KEY_0,KEY_0是个宏
#define KEY_0            11

十进制值为11,对应的code就是000b。

最后是value的值,表示我们上报的按键值,1对应按键按下,0表示释放。但是在不松开的时候这个值是1和2来回变化,我不知道是怎么来的。(这个值我感觉是个小端模式,0001在左边,包括前面那个时间的数据,感觉也是左边4个数先跳,后面的再变)。所以打印出来的这4行数据分别表示了按键按下事件——同步事件——按键弹起事件——同步事件。

应用程序编写

在前面写驱动的时候我们把文件操作集合以及对应的函数都删掉了,通过input子系统操作的输入设备对应的文件就是前面我们关注的/dev/input/路径下的event文件,也就是如果我们想要获取按键的状态,就要在用户态程序中将前面通过hexdump命令打印出的数据解析出来。

先放代码

 1 /**
 2  * @file inputAPP.c
 3  * @author your name (you@domain.com)
 4  * @brief input子系统测试APP
 5  * @version 0.1
 6  * @date 2022-08-28
 7  * 
 8  * @copyright Copyright (c) 2022
 9  * 
10  */
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/ioctl.h>
18 #include <linux/input.h>
19 
20 /**
21  * @brief 
22  * 
23  * @param argc                      //参数个数 
24  * @param argv                      //参数
25  * @return int 
26  */
27 int main(int argc,char *argv[])
28 {
29     char *filename;                 //文件名
30     int ret = 0;                    //初始化操作返回值
31     int f = 0;                      //初始化文件句柄
32 
33     struct input_event inputevent;  //inputevent事件结构体
34 
35     if(argc != 2){
36         printf("format err!\r\n");
37         return -1;
38     }
39     
40     filename = argv[1];             //
41     f = open(filename, O_RDWR);     //打开文件
42     if(f < 0){
43     printf("file open error\r\n");
44     return -1;
45     }
46 
47     while(1){
48         ret = read(f,&inputevent,sizeof(inputevent));       //读取文集
49         if(ret<0){
50             //读取错误
51             printf("data read err\r\n");
52         }
53         else{
54             switch(inputevent.type) {
55                 case EV_SYN:
56                     break;
57                 case EV_KEY:
58                     printf("btn event\r\n");
59                     if(inputevent.code< BTN_MISC){
60                         //按键键值为KEY_xxx
61                         printf("key %d %s\r\n",inputevent.code,inputevent.value?"pressed":"released");
62                     }
63                     else{
64                         //按键键值为BTN_xxx
65                         printf("button %d %s\r\n",inputevent.code,inputevent.value?"pressed":"released");
66                     }
67                     break;
68                 case EV_REL:
69                     break;
70             }
71         }
72         }
73     close(f);                       //关闭文件
74     return 0;
75 }

整个应用程序的思路还是比较清晰度,主要就是在主程序里声明了一个inputevent结构体变量(教程里是按照全局变量的方法声明在主函数外部的)。打开文件什么的就不说了,我们要关注的就是从54行开始的switch结构,如果inputevent的type是EV_KEY的话,就按照键值读取。并且在case里做了一个判断,inputevent的value在0~255之间是对应的是键盘的键值,否则是button(如果我们只是当个按键使用不建议把按钮模拟成键盘,所以在写驱动的时候可以把bitkey的值放在btn区间)。

有意思的是即便我们并没有在驱动或应用程序中定义文件读写的阻塞或非阻塞的模式,但是我感觉实际状态下应该是按照阻塞模式读取的文件,可以在程序以后台模式运行以后通过top命令查询一下

/lib/modules/4.1.15 # ./inputAPP /dev/input/event1 &

 

可以看出来,程序并没有占用过多的资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_2849.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(0828)【vivado版本-对仿真工具版本要求】

(1)https://blog.csdn.net/Alonger1988/article/details/120506385 vivado,vsim版本兼容问题 (2)版本匹配:http://dengkanwen.com/567.html

Ingress

为什么需要Ingress Service是基于四层TCP和UDP协议转发的,而Ingress可以基于七层的HTTP和HTTPS协议转发,可以通过域名和路径做到更细粒度的划分,如下图所示。 图1 Ingress-ServiceIngress工作机制 要想使用Ingress功能,必须在Kubernetes集群上安装Ingress Controller。Ingr…

Rayman Mini for Mac(雷曼迷你跑酷游戏)中文

Rayman Mini for Mac是一款运行在MacOS平台上的经典跑酷类游戏,玩家在Rayman Mini可以看到经典的传统角色,与玩家一起在世界中探险,还有超多全新的角色出现。游戏包含动作横向跑酷和剧情解谜探索为一体,呈现了一个别样的世界。 详情:Rayman Mini for Mac(雷曼迷你游戏) 游…

Java09-继承,抽象类

继承:就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接 访问父类中的非私有的属性和行为。父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意…

IDEA配置方法注释

之前配置过,但是忘记了,再次记录下. IDEA版本(IntelliJ IDEA 2019.3.1 x64)类注释如下位置配置,创建类时自动生成注释.点击查看代码 /** * ${NAME} * *@author ${USER} *@version 1.0 *${DATE} ${TIME} **/效果如下:方法注释 如下位置建立tempalte group.1.新增add,这里add可以…

程序设计大赛

一开始可以分清楚板块1.背景2.基本功能介绍 + 难点功能 可以里面的内容串起来3.重难点+亮点 分清楚,难点,亮点 我们答辩时间是10分钟,背景大概是1分半,首先是整个系统爬取数据,经行一个总的说明,构建情况然后我是通过一首诗来进行串的,从知人论事开始说起,知人就…

ansible 001 ansible介绍 原理

ansible 自动化运维 ansible 部署应用程序 (在操作系统层面之上) 系统初始化过程 主机名,yun源,网络,服务,时间同步,内核参数 (可以在pxe这里完成) ansible可以方便100多台服务器来变更,不至于pxe重新安装 PXE 预启动的执行环境 PXE (Pre-boot Execution Enviro…

使用小乌龟来更新代码-02

小乌龟更新代码使用的是pull 右击项目文件,TortoiseGit--->pull来更新代码,从远程仓库拉取最新的代码,拉取后。 点击OK 然后点击Pulled Diff,点击Show log看看当前版本和最新版本相比哪里有修改,是否有冲突: 例如,我把一个压缩文件给删除了,还有修改了Default里的一…

【Prometheus+Grafana系列】监控MySQL服务

前言 前面的一篇文章已经介绍了 docker-compose 搭建 Prometheus + Grafana 服务。当时实现了监控服务器指标数据,是通过 node_exporter。Prometheus 还可用来监控很多服务,比如常见的 MySQL。本文就介绍如何通过 mysqld_exporter 来监控 MySQL 指标。 下载安装包 cd /opt w…

CrystalDiskMark 磁盘读写性能测试 All In One

CrystalDiskMark 磁盘读写性能测试 All In OneCrystalDiskMark 磁盘读写性能测试 All In One https://crystalmark.info/en/software/crystaldiskmark/macOS ❌ 不支持 Windows 系统 ✅ 支持 U盘,移动固态硬盘,硬盘refs©xgqfrms 2012-2020www.cnblogs.com/xgqfrms 发布文…

彻底理解线程

操作系统支持多个应用程序同时执行,每个应用至少对应一个进程,彼此之间的操作和数据不受干扰。当一个进程需要磁盘IO的时候,CPU就切换到另外的进程,提高了CPU利用率。有了进程,为什么还要线程?因为进程的成本太高了。启动新的进程必须分配独立的内存空间,建立数据表维护…

软件质量保障流程

一. 软件质量保障流程 1.1 微服务产品的特点 微服务架构下,一个大型复杂软件系统不再是一个单体,而是一系列相互独立的微服务,特点鲜明:每个服务独立,开发技术栈独立 每个服务可以独立开发、部署、发布 服务之间通过轻量级通信机制沟通,常用的是 RESTful APIMicro Servic…

JavaScript实现栈结构(Stack)

Js实现栈结构 一、前言 1.1 什么是数据结构 数据结构就是在计算机中,存储和组织数据的方式。 例如:图书管理,怎样摆放图书才能既能放很多书,也方便取? 常见的数据结构:栈(Stack) 队列(Queue) 链表(Linked List) 集合(Set) 哈希(Hash) 树(Tree) 图(Graph)1.…

Jenkins设置中文

Jenkins是一个持续集成的平台,但是初次安装Jenkins之后,是英文的状态。下面给大家介绍如何将Jenkins设置为中文语言。一、下载Locale插件1点击【Manage Jenkins】选项。2点击【Manage Plugins】选项。 点击【可选插件】选项。 右侧搜索栏输入【Locale】选项。 勾选【插件选项…

URL重定向及绕过方法

1 概述 URL重定向漏洞也称URL任意跳转漏洞,是由于网站信任了用户的输入导致恶意跳转。URL重定向主要用来钓鱼,比如URL跳转中最常见的跳转在登录口、支付口,也就是一旦登录将会跳转任意自己构造的网站,如果设置成指定的URL,则会造成钓鱼等危害。 2 详情 2.1 跳转常用参数 在…

js删除css样式

js删除css样式_百度知道 https://zhidao.baidu.com/question/680409425108037292.html1、如果使用class加的样式的话,可以使用document.getElementById("objid").className=""来清空样式;  2、如果是直接加的style="***"属性的话,可以使用…

ArcGIS API forJavaScript4.x去除地图获取焦点的黑色边框

ArcGIS API forJavaScript4.x去除地图获取焦点的黑色边框CSS /* 去掉地图聚焦边框 */ .esri-view-surface--inset-outline:focus::after {outline: none !important; }箴言:因为这些东西是非常简单的。不要抱怨自己学不会,那是因为你没有足够用心。

NetCDF库编译安装

1. 准备 系统环境,全部是deepin系统自带,并无单独安装deepin 20.6 gcc 8.3.0 g++ 8.3.0 cmake 3.22.1 netcdf安装版本:此次使用最新4.9.0,系统为deepin 20.6,大于4.3.0 源码下载地址,下载netcdf-c-4.9.0.tar.gz: https://downloads.unidata.ucar.edu/netcdf/ netCDF-C S…

el-button点击了按钮会出现保留点击的状态

问题 el-button点击了按钮之后,将鼠标移出按钮,会出现保留点击的状态 再查看它的css样式后,可以看到官方默认设置有:focus的状态规则解决办法 在el-button的css里自定义或者复制原有的color、border-color、background-color三条样式, 然后再重写:hover方法就可以了, 其实…

SpringBoot日志系统——logback

logback是SpringBoot内置的日志处理框架,你会发现spring-boot-starter其中包含了spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 logback。而spring-boot-starter-web包含了spring-boot-starter,可通过引入spring-boot-starter-web后的项目JAR依赖关…