Linux输入设备应用编程(键盘,按键,触摸屏,鼠标)
目录
一 输入设备编程介绍
1.1 什么是输入设备呢?
1.2 什么是输入设备的应用编程?
1.3 input子系统
1.4 数据读取流程
1.5 应用程序如何解析数据
1.5.1 按键类事件:
1.5.2 相对位移事件
1.5.3 绝对位移事件
二 读取 struct input_event数据
一 输入设备编程介绍
本章学习Linux输入设备的应用编程。
1.1 什么是输入设备呢?
输入设备其实就是能够产生输入事件的 设备就称为输入设备,常见的输入设备包括鼠标、键盘、触摸屏、按钮等等,它们都能够产生输入事件,产 生输入数据给计算机系统。
1.2 什么是输入设备的应用编程?
输入设备的应用编程其主要是获取输入设备上报的数据、输入设备当前状态等,譬如获取触摸屏当 前触摸点的 X、Y 轴位置信息以及触摸屏当前处于按下还是松开状态,然后根据获取到的数据做出对应的操作。
1.3 input子系统
输入设备种类非常多,每种设备上报的数据类型又不一样,那么 Linux 系统如何管 理呢?
Linux 系统为了统一管理这些输入设备,实现了一套能够兼容所有输入设备的框架,那么这个框架就 是 input 子系统。驱动开发人员基于 input 子系统开发输入设备的驱动程序,input 子系统可以屏蔽硬件的差 异,向应用层提供一套统一的接口。 基于 input 子系统注册成功的输入设备,都会在/dev/input 目录下生成对应的设备节点(设备文件),设 备节点名称通常为 eventX(X 表示一个数字编号 0、1、2、3 等),如/dev/input/event0、/dev/input/event1、 /dev/input/event2 等,通过读取这些设备节点可以获取输入设备上报的数据。

1.4 数据读取流程
我们要读取触摸屏的数据,假设触摸屏设备对应的设备节点为/dev/input/event0,那么数据读取流程 如下:
①、应用程序打开/dev/input/event0 设备文件;
②、应用程序发起读操作(譬如调用 read),如果没有数据可读则会进入休眠(阻塞 I/O 情况下);
③、当有数据可读时,应用程序会被唤醒,读操作获取到数据返回;
④、应用程序对读取到的数据进行解析。
当无数据可读时,程序会进入休眠状态(也就是阻塞),譬如应用程序读触摸屏数据,如果当前并没有 去触碰触摸屏,自然是无数据可读;当我们用手指触摸触摸屏或者在屏上滑动时,此时就会产生触摸数据、 应用程序就有数据可读了,应用程序会被唤醒,成功读取到数据。那么对于其它输入设备亦是如此,无数据 可读时应用程序会进入休眠状态(阻塞式 I/O 方式下),当有数据可读时才会被唤醒。
1.5 应用程序如何解析数据
应用程序打开输入设备对应的设备文件,向其发起读操作,那么这个读操作获取到的是什么样的数据呢?其实每一次 read 操作获取的都是一个 struct input_event 结构体类型数据,该结构体定 义在头文件中,它的定义如下:
struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value;
};
time :内核会记 录每个上报的事件其发生的时间
type:type 用于描述发生了哪一种类型的事件(对事件的分类),Linux 系统所支持的输入事件类 型如下所示:
#define EV_SYN 0x00 //同步类事件,用于同步事件 #define EV_KEY 0x01 //按键类事件 #define EV_REL 0x02 //相对位移类事件(譬如鼠标) #define EV_ABS 0x03 //绝对位移类事件(譬如触摸屏) #define EV_MSC 0x04 //其它杂类事件 #define EV_SW 0x05 #define EV_LED 0x11 #define EV_SND 0x12 #define EV_REP 0x14 #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1)以上这些宏定义也是在头文件中,所以在应用程序中需要包含该头文件;一种输入设备 通常可以产生多种不同类型的事件,譬如点击鼠标按键(左键、右键,或鼠标上的其它按键)时会上报按键 类事件,移动鼠标时则会上报相对位移类事件。
code:code 表示该类事件中的哪一个具体事件,以上列举的每一种事件类型中都包含了一系列具 体事件,譬如一个键盘上通常有很多按键,譬如字母 A、B、C、D 或者数字 1、2、3、4 等,而 code 变量则告知应用程序是哪一个按键发生了输入事件。每一种事件类型都包含多种不同的事件,譬如
1.5.1 按键类事件:
#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 KEY_E 18 //字母 E 键
#define KEY_R 19 //字母 R 键
1.5.2 相对位移事件
#define REL_X 0x00 //X 轴
#define REL_Y 0x01 //Y 轴
#define REL_Z 0x02 //Z 轴
#define REL_RX 0x03
#define REL_RY 0x04
#define REL_RZ 0x05
#define REL_HWHEEL 0x06
#define REL_DIAL 0x07
#define REL_WHEEL 0x08
#define REL_MISC 0x09
#define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1)
1.5.3 绝对位移事件
触摸屏设备是一种绝对位移设备,它能够产生绝对位移事件;
对于触摸屏来说,一个触摸点所包含的信息可能有多种,譬如触摸点的 X 轴坐标、Y 轴坐标、Z 轴坐标、按压力大小以及接触面积等,所以 code变量告知应用程序当前上报的是触摸点的哪一种信息(X 坐标还是 Y 坐标、亦或者其它);
#define ABS_X 0x00 //X 轴
#define ABS_Y 0x01 //Y 轴
#define ABS_Z 0x02 //Z 轴
#define ABS_RX 0x03
#define ABS_RY 0x04
#define ABS_RZ 0x05
#define ABS_THROTTLE 0x06
#define ABS_RUDDER 0x07
#define ABS_WHEEL 0x08
#define ABS_GAS 0x09
#define ABS_BRAKE 0x0a
#define ABS_HAT0X 0x10
#define ABS_HAT0Y 0x11
#define ABS_HAT1X 0x12
#define ABS_HAT1Y 0x13
#define ABS_HAT2X 0x14
#define ABS_HAT2Y 0x15
#define ABS_HAT3X 0x16
#define ABS_HAT3Y 0x17
#define ABS_PRESSURE 0x18
#define ABS_DISTANCE 0x19
#define ABS_TILT_X 0x1a
#define ABS_TILT_Y 0x1b
#define ABS_TOOL_WIDTH 0x1c
value:内核每次上报事件都会向应用层发送一个数据 value,对 value 值的解释随着 code 的变化而 变化。
- 如对于按键事件(type=1)来说,如果 code=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 值而定!
二 读取 struct input_event数据
根据前面的介绍可知,对输入设备调用read()会读取到一个struct input_event类型数据,现写一个简单地应用程序,将读取到的struct input_event类型数据中的每一个元素打印出来、并对它们进行解析。
2.1 开发板的按键测试
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/input.h>void main(int argc,char *argv[])
{struct input_event in_ev = {0};int fd = -1; //打开设备文件返回的句柄if(argc != 2){fprintf(stderr,"格式:%s <input-dev> \n <input-dev>为设备文件路径\n",argv[0]);exit(-1);}fd = open(argv[1],O_RDONLY);if(fd < 0){perror("");exit(-1);}while(1){if (sizeof(struct input_event) != read(fd, &in_ev, sizeof(struct input_event))) {perror("");exit(-1);}printf("type(对事件的分类):%d code(具体事件):%d value(状态):%d\n", in_ev.type, in_ev.code, in_ev.value);}}
执行程序时需要传入参数,这个参数就是对应的输入设备的设备节点(设备文件),程序中会对传参进行校验。程序中首先调用open()函数打开设备文件,之后在while循环中调用read()函数读取文件,将读取到的数据存放在struct input_event结构体对象中,之后将结构体对象中的各个成员变量打印出来。注意,程序中使用了阻塞式I/O方式读取设备文件,所以当无数据可读时read调用会被阻塞,知道有数据可读时才会被唤醒!

交叉编译并拷贝到开饭板上 ,用cat指令获得设备节点路径 cat /proc/bus/input/devices

测试程序,获取输入设备信息

code = 1时(按键事件时),对应的value等于2,表示长按状态。
value等于1,表示按下状态。
value等于0,表示松开状态。
2.2 开发板USB接键盘按键测试
除了测试开发板上的KEY0按键之外,我们还可以测试键盘上的按键,首先找到一个USB键盘连接到开发板的USB HOST接口上,当键盘插入之后,终端将会打印出相应的驱动加载信息:

驱动加载成功之后,可以查看下该键盘设备对应的设备节点,使用命令"cat /proc/bus/input/devices",在打印信息中找到键盘设备的信息:
使用的是一个机械师的USB键盘"BY Tech Gaming Keyboard",对应的设备节点为/dev/input/event4,运行测试程序并按下、松开键盘上的按键:


相关文章:
Linux输入设备应用编程(键盘,按键,触摸屏,鼠标)
目录 一 输入设备编程介绍 1.1 什么是输入设备呢? 1.2 什么是输入设备的应用编程? 1.3 input子系统 1.4 数据读取流程 1.5 应用程序如何解析数据 1.5.1 按键类事件: 1.5.2 相对位移事件 1.5.3 绝对位移事件 二 读取 struct input_e…...
【Axure教程】滑动内容选择器
滑动内容选择器通常是一种用户界面组件,允许用户通过滑动手势在一组内容之间进行选择。这种组件可以在移动应用程序或网页中使用,以提供直观的图片选择体验。 那今天就教大家如何用中继器制作一个滑动内容选择器,我们会以滑动选择电影为案例…...
vite+vue3使用@路径,报错处理
报错原因:未配置 符号为指定路径别名,直接使用导致 处理方法: 安装path模块: npm install --save-dev types/node修改vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import path from…...
[开源]基于 AI 大语言模型 API 实现的 AI 助手全套开源解决方案
原文:[开源]基于 AI 大语言模型 API 实现的 AI 助手全套开源解决方案 一飞开源,介绍创意、新奇、有趣、实用的开源应用、系统、软件、硬件及技术,一个探索、发现、分享、使用与互动交流的开源技术社区平台。致力于打造活力开源社区࿰…...
2023年中国中端连锁酒店分类、市场规模及主要企业市占率[图]
中端连锁酒店行业是指定位于中档酒店市场、具有全国统一的品牌形象识别系统、全国统一的运营体系、会员体系和营销体系的酒店。中端酒店通常提供舒适、标准化的房间设施和服务,价格较为合理,符合广大消费者的需求。其价格略高于经济型酒店,但…...
mac下vue-cli从2.9.6升级到最新版本
由于mac之前安装了 vue 2.9.6 的版本,现在想升级到最新版本,用官方给的命令: npm uninstall vue-cli -g 发现不行。 1、究其原因:从vue-cli 3.0版本开始原来的npm install -g vue-cli 安装的都是旧版,最高到2.9.6。安…...
【cpolar】搭建我的世界Java版服务器,公网远程联机
🎥 个人主页:深鱼~🔥收录专栏:cpolar🌄欢迎 👍点赞✍评论⭐收藏 目录 前言: 1. 搭建我的世界服务器 1.1 服务器安装java环境 1.2 配置服务端 2. 测试局域网联机 3. 公网远程联机 3.1 安…...
Redis数据类型–Geospatial 地理空间
目录 前言 命令 1、geoadd 1)格式 2)实例 2、geopos 1)格式 2)实例 3、geodist 1)格式 2)实例 4、georadius 1)格式 2)实例 前言 Redis 3.2 中增加了对GEO类型的支持。GEO…...
LeetCode 面试题 16.26. 计算器
文章目录 一、题目二、C# 题解 一、题目 给定一个包含正整数、加()、减(-)、乘(*)、除(/)的算数表达式(括号除外),计算其结果。 表达式仅包含非负整数,, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。 示例 …...
15篇MyBatis-Plus系列集合篇「值得收藏学习」
历史文章(文章累计490) 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 M…...
C#入门(6): 结构体、ref struct
文章目录 定义结构体实例化结构体结构体的值类型特性结构体和类的区别限制ref structref return C# 中的结构体(Struct)是一种值类型数据结构,用于封装不同或相同类型的数据成一个单一的实体。结构体非常适合用来表示轻量级的对象,…...
Java shp 转 GeoJson
文章目录 1. 依赖安装1.1 配置软件源1.2 引入依赖 2. 功能实现3. 参考链接 1. 依赖安装 1.1 配置软件源 在项目 pom.xml 添加, maven 的 settings.xml 配置的源,mirrorOf 不能是 *,不然安装不上 <project>...<repositories><repository><id…...
shadow复习之planar shadow
planar shadow 通常来说 shadow都是画一个map 这个map有个很大的问题,那就是size有问题 你希望有很高的精度,就必定要用大size的图片,这显然是不太妙的 那么这里就出现一个取巧的法子,如果你只考虑投影到平面上,光源是…...
计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)
大家好,我是微学AI,今天给大家介绍一下计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)。本篇文章,我将向大家展示如何使用CrowdCountNet这个神奇的工具,以及它是如何利用深度学习技术来解决复杂…...
源启容器平台KubeGien 打造云原生转型的破浪之舰
云原生是应用上云的标准路径,也是未来发展大的趋势。如何将业务平滑过渡到云上?怎样应对上云期间的各项挑战呢?中电金信基于金融级数字底座“源启”打造了一款非常稳定可靠、多云异构、安全可控、开放灵活的容器平台产品——源启容器平台Kube…...
斯坦福机器学习 Lecture2 (假设函数、参数、样本等等术语,还有批量梯度下降法、随机梯度下降法 SGD 以及它们的相关推导,还有正态方程)
假设函数定义 假设函数,猜一个 x->y 的类型,比如 y ax b,随后监督学习的任务就是找到误差最低的 a 和 b 参数 有时候我们可以定义 x0 1,来让假设函数的整个表达式一致统一 如上图是机器学习中的一些术语 额外的符号…...
【腾讯云云上实验室-向量数据库】TAI时代的数据枢纽-向量数据库 VectorDB
一、向量数据库的发展历程和时代机遇 回顾向量数据库的发展历程: 2012年开始,深度神经网络的发展催生了向量数据库的发展;2015年至2016年,Google和微软发布了标志性的论文;2017年,Facebook开源了Faiss框架…...
掌握深度学习利器——TensorFlow 2.x实战应用与进阶
掌握深度学习利器——TensorFlow 2.x实战应用与进阶 摘要:随着人工智能技术的飞速发展,深度学习已成为当下最热门的领域之一。作为深度学习领域的重要工具,TensorFlow 2.x 备受关注。本文将通过介绍TensorFlow 2.x的基本概念和特性ÿ…...
MySQL 之多版本并发控制 MVCC
MySQL 之多版本并发控制 MVCC 1、MVCC 中的两种读取方式1.1、快照读1.2、当前读 2、MVCC实现原理之 ReadView2.1、隐藏字段2.2、ReadView2.3、读已提交和可重复读隔离级别下,产生 ReadView 时机的区别 3、MVCC 解决幻读4、总结 MVCC(多版本并发控制&…...
优步让一切人工智能化
优步(Uber)的商业模式建立在对数据的颠覆性使用上--通过将双方智能手机的位置数据关联起来,将出租车司机与乘客配对。这意味着,它可以比传统出租车公司更快地安排司机去接乘客,极大地冲击了传统出租车公司的业务。 优步自成立以来࿰…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...
