IMX6ULL|input子系统(按键实验)

一.input子系统

input子系统是Linux对输入设备提供的统一驱动框架。如按键、键盘、触摸屏和鼠标等输入设备的驱动方式是类似的,当出现按键、触摸等操作时,硬件产生中断,然后CPU直接读取引脚电平,或通过SPI、I2C等通讯方式从设备的寄存器读取具体的按键值或触摸坐标,然后把这些信息提交给内核。使用input子系统
驱动的输入设备可以通过统一的数据结构提交给内核,该数据结构包括输入的时间、类型、代号以及具体的键值或坐标,而内则通过/dev/input目录下的文件接口传递给用户空间。

Linux内核源码/Documentation/input目录包含了input子系统相关的说明。

#在主机下执行如下命令
#安装evtest工具
sudo apt install evtest -y
#使用sudo权限运行evtest工具
sudo evtest
#根据自己主机的输出来选择某个设备测试,下图选择的是“6”,鼠标
#根据选择的设备测试,如选择的键盘就按键盘,选择鼠标就移植鼠标

在这里插入图片描述

上图的执行过程说明如下:

  • 运行evtest工具,它列出了系统当前可用的/dev/input/event0~6输入事件 文件,并且列出了这些事件对应的设备名。
  • 我们根据设备名的“VirtualBox mouse intergration”推猜它就是接入到电脑 的鼠标,所以输入了它对应的event6事件编号6,实验时请根据自己电脑的输出来选择。
  • 输入编号后它列出了event6的一些设备信息,包括驱动版本、设备ID、设备 名、支持的事件类型、事件代号以及输入值的取值范围。
  • 此时移动鼠标,可以看到它输出了详细的事件信息,如果移动后没有输出,说明 你选择的不是鼠标设备,请退出重新选择。输出信息中每一行包含了鼠标上报事件的具 体时间time、事件类型type 3(EV_ABS)、事件代号code 1或code0(ABS_Y或ABS_X)和具体的值value,该值就是鼠标X/Y的坐标。

二.input事件结构

在这里插入图片描述

可看到“/dev/input”目录下,有event*、js*、mouse*及mice文件,它们分别是 驱动层evdev(通用输入事件)、joydev(游戏杆)及遗留的mousedev(鼠标)设备暴露 到用户空间的访问接口文件,读取这些文件的内容可获取到设备上报的信息。

在前面LED、GPIO子系统中,brightness、direction等设备文件直接使用字符串来记 录具体的信息,所以使用cat命令输出文件的内容时,字符串的形式非常方便我们阅读。但是event文件包 含的信息较多,使用字符串不方便其它程序处理,它采用了纯粹的内核事件数据结构来记录内容,其它 程序使用时 应把读取到的内容按数据的结构进行格式化转换,该数据结构定义如下所示。

struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
  • time:该变量用于记录事件产生的时间戳,既evtest输出的time值。

  • type:输入设备的事件类型。系统常用的默认类型有EV_KEY、 EV_REL和EV_ABS,分别用 于表示按键状态改变事件、相对坐标改变事件及绝对坐标改变事件,特别地,EV_SYN用于分隔事件,无特别意义。如果选择鼠标(本章第一个图) evtest输出的type类型为EV_ABS。相关的枚举值可以参考内核文件include/uapi/linux/input-event-codes.h。

  • code:事件代号,它以更精确的方式表示事件。例如 在EV_KEY事件类型中,code的值常用于表 示键盘上具体的按键,其取值范围在0~127之间,例如按键Q对应的是KEY_Q,该枚举变量的 值为16。如果选择鼠标, evtest输出内容的code分别有ABS_X/ABS_Y,表示上报的是X或Y坐标。

  • value:事件的值。对于EV_KEY事件类型,当按键按下时,该值为1;按键松开时,该值为0。如果选择 鼠标,中evtest输出的内容里,ABS_X事件类型中的value值表示X坐标,ABS_Y类型中的value值表示Y坐标

如果同样使用cat命令查看事件文件,当事件出现时,cat把内容转化成字 符串,会看到乱码,使用这样的方式可以简单地查看设备是否上报了事件。

可使用以下方式可进行测试:

#根据自己主机上的事件号修改要查看的具体事件文件
#此处使用的event6是本主机的鼠标设备,注意要使用sudo权限
sudo cat /dev/input/event6
#输入命令后移动鼠标,会看到字符

如下图;

在这里插入图片描述

三.input事件设备名

“/dev/input/event*”的事件编号与设备的联系不是固定的,它通常按系统检测 到设备的先后顺序安排event文件的编号,这对编写应用程序控制不太方便,我们 可以通过“/dev/input/by-id”或“/dev/input/by-path”目录查看具体的硬件设备,如 下图所示。

在这里插入图片描述

图中列出了by-path目录下的内容,该目录下的文件实际上都是链接,如第 一行的“pci-0000:00:04.0-event-mouse -> …/event6”表示”pci-0000:00:04.0-event- mouse”文件就是event6的快捷方式,它就是本主机中使用的鼠标,也就是说访问该 文件就是访问该鼠标的事件设备,而且该文件名与硬件的关系是固定的,后面我们的实验就是采用这样的方式。

由于/dev下的设备都是通过/sys导出的,所以也可以通过“/sys/class/input”目 录查看,如下图所示。

在这里插入图片描述

“/sys/class/input”下包含了各个以事件命名的目录,其对应目录 下的device/name文件包含了事件对应的设备名,如本示例中 的“/sys/class/input/event6/device/name”文件的内容为”VirtualBox mouse integration”,evtest工具列出的事件与设备名的关系,就是从这里读取的。

四.开发板按键检测实验

在输入事件检测的应用中,通常使用主线程直接 循环读取“/dev/input/event*”设备文件获取事件的数据结构,然后通过消 息队列通知其它子线程,从而响应输入操作。

本实验的代码目录为:base_code/linux_app/input/c。

本实验仅使用了一个main.c文件,如下所示。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/input-event-codes.h>


//开发板上的KEY按键,请根据实际情况修改
const char default_path[] = "/dev/input/by-path/platform-gpio-keys-event";

//开发板上的ON_OFF按键,请根据实际情况修改
//const char default_path[] = "/dev/input/by-path/platform-ci_hdrc.1-usb-0:1.1:1.0-event-mouse";


int main(int argc, char *argv[])
{
   int fd;
   struct input_event event;
   char *path;

   printf("This is a input device demo.\n");

   //若无输入参数则使用默认事件设备
   if(argc > 1)
      path = argv[1];
   else
      path = (char *)default_path;

   fd = open(path, O_RDONLY);
   if(fd < 0){
      printf("Fail to open device:%s.\n"
            "Please confirm the path or you have permission to do this.\n", path);
      exit(1);
   }

   printf("Test device: %s.\nWaiting for input...\n", path);

   while(1){
      if(read(fd, &event, sizeof(event)) == sizeof(event)){

         //EV_SYN是事件分隔标志,不打印
         if(event.type != EV_SYN)
            printf("Event: time %ld.%ld, type %d, code %d,value %d\n",
                  event.time.tv_sec,event.time.tv_usec,
                  event.type,
                  event.code,
                  event.value);
      }
   }
   close(fd);

   return 0;
}

第12行:定义默认设备路径,此处使用的是开发板KEY按键
在“/dev/input/by-path”下的链接文件名,此处不使用“/dev/input/event*”只是
为了让程序不受其它输入设备而影响了事件编号。

第25~29行:检查main函数的输入参数,若程序执行时带输入参数,把第1个输入
参数作为要打开的事件设备文件路径,若程序不带参数,则使用上面的默认设备KEY按键的事件设备文件。

第31~36行:使用O_RDONLY模式打开事件设备文件,O_RDONLY模式默认是阻塞
型的,而且事件设备文件支持阻塞操作,也就是说,若后面使用read函数读取时,它会 等待事件上报,一直等待至读取成功或失败才会返回。

第41行:在while循环里通过read系统调用读取事件文件,读取到的内容存储在 “struct input_event”类型
的event变量中,“struct input_event”类型就是前面介绍的内核事件数据结构。
若成功读取,我们就可以通过该变量的结构体成员访问到事件的时间戳、类型、代号和值。

第45~49行:输出读取到的event变量的各个成员值,在上报 的事件中,通常会有很多类型为EV_SYN的事件,这种事件是用于分隔的,无特别
意义,所以代码中不输出这类型事件的内容。

值得思考的是,若没有上报事件,第42行的read读取事件设备文件操作会被阻塞,简单来说就是即使第52行的printf代码不注释掉,它也不会在持续地在循环里输出,而只有当出现了事件,触发read退出,后面的printf函数才有机会被执行一次,然后重新read事件再次阻塞。在这种阻塞的过程中,进程会休眠 ,释放它对CPU的占用。

假如我们使用的是GPIO子系统框架来编写按键驱动程序,在应用层的操作中,需要使用“/sys/class/gpio/gpio*/direction”文件配置为输入方向,然后使用循环读取“/sys/class/gpio/gpio*/value”文件的值来获得按键的状态,但由于对value文件的read读 取操作不会阻塞,所以进程会不停地读取文件内容来判断按键值,占用CPU宝贵的运算资源。

由于read事件文件操作会阻塞,那么采用这种方式就无法同时检测两个输入设备了,这种时候可以通过select或poll等IO多路复用的操作达成目的。

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

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

相关文章

C#,入门教程(35)——哈希表(Hashtable)的基础知识与用法

上一篇&#xff1a; C#&#xff0c;入门教程(34)——关于函数的参数之引用&#xff08;ref&#xff09;的一点知识与源程序https://blog.csdn.net/beijinghorn/article/details/125411351 有一段故事&#xff1a; King Log The frogs in the lake had an easy life doing ex…

npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED

npm install时报错code CERT_HAS_EXPIRED 一、报错情况二、解决方案 一、报错情况 一直用的好好的&#xff0c;突然今天发现npm install 出问题了&#xff0c;具体报错如下&#xff1a; npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to…

不要为了学习而学习

经常有朋友问我&#xff1a; 老师&#xff0c;从您这里学了很多方法&#xff0c;也一直想要改变自己&#xff0c;但总是没办法坚持下去&#xff0c;怎么办&#xff1f; 这个问题&#xff0c;我也很无奈啊。毕竟我也没办法飞到你身边&#xff0c;手把手把每一步都教给你。&…

MySQL-B-tree和B+tree区别

B-tree&#xff08;平衡树&#xff09;和Btree&#xff08;平衡树的一种变种&#xff09;是两种常见的树状数据结构&#xff0c;用于构建索引以提高数据库的查询性能。它们在一些方面有相似之处&#xff0c;但也有一些关键的区别。以下是B-tree和Btree的主要区别&#xff1a; …

你知道Mysql的架构吗?

msyql分为server曾和存储引擎层 server层包括了连接器(管理连接&#xff0c;权限验证)、查询缓存&#xff08;命中直接返回结果&#xff09;、分析器&#xff08;词法分析&#xff0c;语法分析&#xff09;、优化器&#xff08;执行计划生成&#xff0c;索引选择&#xff09;、…

【揭秘】ScheduledThreadPoolExecutor全面解析

内容摘要 ScheduledThreadPoolExecutor能够高效地管理和复用线程资源&#xff0c;避免了大量线程的创建和销毁开销&#xff0c;从而提升了系统性能&#xff0c;同时&#xff0c;它提供了灵活的任务调度机制&#xff0c;支持延迟执行和固定频率执行&#xff0c;满足了各种复杂场…

idea创建公用依赖包项目

创建parent项目 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/…

linux之安装配置VM+CentOS7+换源

文章目录 一、centos07安装二、CentOS 07网络配置2.1解决CentOS 07网络名不出现问题此博主的论文可以解决2.2配置&#xff08;命令: 【ip a】也可查看ip地址&#xff09; 三、使用链接工具链接CentOS进行命令控制四、换软件源 一、centos07安装 1、在vmvare中新建虚拟机 2、下…

【K8S 云原生】K8S之HPA自动扩缩容、命名空间资源限制、容器抓包

目录 一、HPA概述 1、概念 2、两个重要的组件&#xff1a; 3、HPA的规则&#xff1a; 4、pod的副本数扩容有两种方式&#xff1a; 4.1、手动扩缩容&#xff0c;修改副本数&#xff1a; 4.2、自动扩缩容HPA 二、实验部署&#xff1a; 1、部署HPA 2、实现自动扩缩容 三…

【多商户开源-BSD- Fecmall 电商平台】

关于Fecmall Fecmall 关于&#xff0c;Fecmall介绍 Fecbbc开源BSD多商户系统&#xff0c;真正开源&#xff0c;商用免费授权的多商户系统 Fecmall系统简介&#xff1a; 全称为Fancy ECommerce Shop&#xff0c; 着重于电商架构的研发优化&#xff0c;全新定义商城的架构体系&…

【RF FILTER 仿真】滤波器 Ansys Electronics not ADS

第一&#xff0c;声明 全网搜索&#xff0c;用这个HFSS继承的介绍非常少&#xff0c;并且没有什么指导意义。所以有必要写一下&#xff0c;就像之前的xpedition,总要挑战一下吧。本文仅仅和大家学习研究&#xff0c;对比ADS体会一下差别。 第二&#xff0c;记录直接开始&…

【Maven从入门到如土】Maven 核心程序解压和配置

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

算法题解析与总结(二)

题目要求 路径 被定义为一条从树中任意节点出发&#xff0c;沿父节点-子节点连接&#xff0c;达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根…

抖音哪些方法不违规还能导流到微信?

抖音作为当前最热门的短视频应用之一&#xff0c;其日活跃用户已经超过6亿。仅仅在抖音上玩乐是不够的&#xff0c;如果你想通过抖音赚钱&#xff0c;你需要掌握如何有效地引流。目前&#xff0c;微信是私域流量的最佳载体&#xff0c;因为它是一个成熟且庞大的生态系统&#x…

【工具】使用ssh进行socket5代理,ssh端口转发

文章目录 shellssh命令详解正向代理&#xff1a;反向代理&#xff1a;本地 socks5 代理 ssh端口转发开启 shell ssh -D 3333 root192.168.0.11 #输入密码 #3333端口已经使用远程机进行转发设置Windows全局代理转发 socks127.0.0.1 3333如果远程机为公网ip&#xff0c;可通过…

消息中间件之RocketMQ事务消息流程(二)

所谓事务消息就是基于消息中间件模拟的两阶段提交(2PC)&#xff0c;属于对消息中间件的一种特殊利用。总体思路如下: 1.系统A先向消息中间件发送一条预备消息(Half Message)&#xff0c;消息中间件在保存好消息之后向系统A发送确认消息 2.系统A执行本地事务 3.系统A根据本地事务…

CPU 如何识别用户空间不同进程的虚拟地址

前言 一个疑问&#xff1a;CPU 运行两个 test.out 进程&#xff0c;使用的是各自进程的虚拟地址&#xff0c;那 CPU 是如何识别出当前这个虚拟地址是属于哪个进程的&#xff1f;带着这个疑问&#xff0c;我们一起开始今天的探索 如上图&#xff0c;CPU 是如何知道 0x4785c4 这…

docker设置代理解决内网pull外网镜像

目录 Docker 配置代理的缘由 通过dockerd配置实现代理 通过container配置实现代理 参考文献 Docker 配置代理的缘由 如何在内网环境内环境内Pull外网registry&#xff0c;或者反过来想要Pull公司Registry镜像&#xff1f;存在上述需求的朋友可以尝试以下方法进行docker代理…

《小学生作文辅导》期刊投稿邮箱

《小学生作文辅导》是国家新闻出版总署批准的正规教育类期刊&#xff0c;适用于全国各小学语文老师事业单位及个人&#xff0c;具有原创性的学术理论、工作实践、科研成果和科研课题及相关领域等人员评高级职称时的论文发表&#xff08;单位有特殊要求除外&#xff09;。 栏目…

OpenHarmony 鸿蒙使用指南——概述

简介 OpenHarmony采用多内核&#xff08;Linux内核或者LiteOS&#xff09;设计&#xff0c;支持系统在不同资源容量的设备部署。当相同的硬件部署不同内核时&#xff0c;如何能够让设备驱动程序在不同内核间平滑迁移&#xff0c;消除驱动代码移植适配和维护的负担&#xff0c;…