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

news2024/11/25 18:25:04

一.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多路复用的操作达成目的。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【大数据精讲】全量同步与CDC增量同步方案对比

目录 背景 名词解释 问题与挑战 FlinkCDC DataX 工作原理 调度流程 五、DataX 3.0六大核心优势 性能优化 背景 名词解释 CDC CDC又称变更数据捕获&#xff08;Change Data Capture&#xff09;&#xff0c;开启cdc的源表在插入INSERT、更新UPDATE和删除DELETE活动时…

Linux: hardware: HP: DIMM

今天遇到一个问题是服务器上BIOS检查DIMM出现错误&#xff1a; 462-Uncorrectable Memory Error Threshold Exceeded(Processor 1, DIMM 14). The DIMM is mapped out and is currently not available. Action: Take corrective action for the failing DIMM. Re-map all DIMMs…

CentOS上安装Mellanox OFED

打开Mellanox官网下载驱动 Linux InfiniBand Drivers 点击下载链接跳转至 Tgz解压缩执行 ./mlnxofedinstall发现缺少模块 # ./mlnxofedinstall Logs dir: /tmp/MLNX_OFED_LINUX.11337.logs General log file: /tmp/MLNX_OFED_LINUX.11337.logs/general.log Verifying KMP rpm…

基于SpringBoot Vue求职招聘系统

大家好✌&#xff01;我是Dwzun。很高兴你能来阅读我&#xff0c;我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结&#xff0c;还为大家分享优质的实战项目&#xff0c;本人在Java项目开发领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#x…

抖音评论区链接,如何实现跳转到微信?-数灵通

在抖音发布带货视频后&#xff0c;如何有效地将用户吸引到我们的店铺呢&#xff1f;以微商为例&#xff0c;我们可以利用抖音评论区的评论置顶功能来达到这一目的。 评论置顶功能允许作者将一条评论置于评论区的顶部&#xff0c;使其成为评论区的焦点。我们可以利用这一功能来吸…

实现VLAN之间的路由

原理&#xff1a;路由器子接口 一个接口允许多个VLAN通过&#xff08;避免占用物理路由器接口&#xff09;。 目标 第 1 部分&#xff1a;单臂路由 第 2 部分&#xff1a;配置第三层交换机的路由端口 第 3 部分&#xff1a;带SVI的VLAN间路由 第 4 部分&#xff1a;补充知…

书生·浦语大模型实战营-学习笔记5

LMDeploy 大模型量化部署实践 大模型部署背景 LMDeploy简介 轻量化、推理引擎、服务 核心功能-量化 显存消耗变少了 大语言模型是典型的访存密集型任务&#xff0c;因为它是decoder-by-decoder 先把数据量化为INT4存起来&#xff0c;算的时候会反量化为FP16 AWQ算法&a…

WINCC 7.5SP2安装过程

最近在群里有人问WINCC的安装问题&#xff0c;而且费了好大功夫就是安装不上&#xff0c;不管WINCC哪个版本&#xff0c;安装过程都差不多&#xff0c;于是昨天用虚拟机做了个WIN10系统&#xff0c;安装了7.5SP2版本&#xff0c;先在把安装的详细过程说一下 1、系统要求 很多…

webpack如何把dist.js中某个模块js打包成一个全局变量,使得在html引入dist.js后可以直接访问

webpack可以通过使用expose-loader来将模块中的一个js文件暴露为全局可以访问的变量。下面是一个示例代码&#xff1a; 1、安装expose-loader npm install expose-loader --save-dev 2、webpack.config.js配置文件 值得注意的是&#xff1a;我在本地使用16.14.2版本的node打包…

[docker] 关于docker的面试题

docker命名空间 docker与虚拟机的区别 容器虚拟机所有容器共享宿主机的内核每个虚拟机都有独立的操作系统和内核通过namespace实现资源隔离&#xff0c;通过cgroup实现限制资源的最大使用量完全隔离。每个虚拟机都有独立的硬件资源秒级启动速度分钟级启动速度容器相当于宿主机…

leetcode---Z字形变换

题目&#xff1a; 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a;之后&#xff0c;你的输出需要从左往右逐行读取&#xff0c;产生…

第十二讲_ArkUI相对布局(RelativeContainer)

ArkUI相对布局&#xff08;RelativeContainer&#xff09; 1. 相对布局概述2. 相对布局的使用3. 子组件位置偏移量 1. 相对布局概述 RelativeContainer 为相对布局的容器组件&#xff0c;支持容器内部的子元素设置相对位置关系。子元素支持指定兄弟元素作为锚点&#xff0c;也…

聊聊Git中的引用

一. 引言 什么是Git引用和分支&#xff1f;比如我在 Github 上一个项目的 .git/refs目录下&#xff1a; ├─heads │ dev │ master │ ├─remotes │ └─origin │ master │ └─tagsrefs 目录下包含了 heads、remote、tags 三个子目录&#xff0c;…

9. UE5 RPG创建UI(下)

在上一篇文章里&#xff0c;制作了显示血量和蓝量的ui&#xff0c;并且还将ui和获取数据使用的控制器层创建出来并初始化成功。现在只有主用户控件上面被添加了控制器层&#xff0c;还未给每个用户控件赋予控制器层。接下来要实现对属性的广播功能&#xff0c;在属性值变化的时…

时限挑战——深度解析Pytest插件 pytest-timeout

在软件开发中,测试用例的执行时间通常是一个关键考虑因素。Pytest插件 pytest-timeout 提供了一个强大的插件,允许你设置测试用例的超时时间。本文将深入介绍 pytest-timeout 插件的基本用法和实际案例,助你精确掌控测试用例的执行时限。 什么是pytest-timeout? pytest-tim…

实现AVL树

王有志&#xff0c;一个分享硬核Java技术的互金摸鱼侠 加入Java人的提桶跑路群&#xff1a;共同富裕的Java人 上一篇我们学习了平衡二分搜索树的理论知识&#xff0c;并学习了AVL树是如何保持二分搜索树的平衡的&#xff0c;今天我们一起来实现AVL树。Tips&#xff1a; AVL树和…

操作系统-进程控制(如何实现进程控制 如何实现原子性 相关进程控制原语)

文章目录 什么是进程控制总览如何实现进程控制&#xff1f;如何实现原语的“原子性”&#xff1f;进程控制相关的原语创建原语撤销原语子进程与父进程阻塞与唤醒原语切换原语 小结 什么是进程控制 控制进程的状态变换 总览 如何实现进程控制&#xff1f; 原语实现 假设不是原…

使用DockerFile构建镜像与镜像上传

目录 前言&#xff1a;为什么要使用Dockerfile &#xff1f; DockerFile构建镜像 1、构建基础对象 2、Dockerfile文件结构 3、构建Dockerfile文件镜像 二、镜像上传&#xff08;阿里云&#xff09; 前言&#xff1a;为什么要使用Dockerfile &#xff1f; 首先Dockerfile …

Linux系统Shell脚本 ----- 编程规范和变量详细解读

一、Shell脚本概述 1、什么是Shell Linux系统中运行的一种特殊程序在用户和内核之间充当“翻译官”用户登录Linux系统时&#xff0c;自动加载一个Shell程序Bash是Linux系统中默认使用的Shell程序 2、Shell的作用 Linux系统中的shell是一个特殊的应用程序&#xff0c;它介于操…

Ansys Lumerical|如何将Klayout Cell动态导入Lumerical Multiphysics

附件下载 联系工作人员获取附件 说明 在本例中&#xff0c;演示了如何将KLayout Library Cell动态导入 Lumerical 以执行设计扫描和表征。该功能支持动态导入到Lumerical FDTD、MODE以及Multiphysics的所有工具&#xff0c;包括CHARGE、HEAT、FEEM、MQW、DGTD。本例适用于&am…