Linux输入设备应用编程(键盘,按键)

news2025/1/11 22:50:05

目录

一 输入设备编程介绍

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 :内核会记 录每个上报的事件其发生的时间

typetype 用于描述发生了哪一种类型的事件(对事件的分类),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) 

 以上这些宏定义也是在头文件中,所以在应用程序中需要包含该头文件;一种输入设备 通常可以产生多种不同类型的事件,譬如点击鼠标按键(左键、右键,或鼠标上的其它按键)时会上报按键 类事件,移动鼠标时则会上报相对位移类事件。

codecode 表示该类事件中的哪一个具体事件,以上列举的每一种事件类型中都包含了一系列具 体事件,譬如一个键盘上通常有很多按键,譬如字母 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,运行测试程序并按下、松开键盘上的按键:

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

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

相关文章

审视现状,持续优化,数字化转型不简单

北京市首都公路发展集团有限公司&#xff08;简称“首发集团”&#xff09;为北京市国有独资公司&#xff0c;1999年9月成立&#xff0c;负责北京市高速公路、城市道路及配套设施的投融资、建设及运营管理。集团下属4家分公司、10家全资或控股二级子公司&#xff0c;参股中铁京…

C++——map和set

作者&#xff1a;几冬雪来 时间&#xff1a;2023年11月17日 内容&#xff1a;C板块map和set知识讲解 目录 前言&#xff1a; map与set与关联式容器&#xff1a; set底层&#xff1a; set的书写&#xff1a; insert&#xff1a; erase&#xff1a; lower_bound与upper_b…

一文带你了解docker技术

什么是Docker Docker是一种虚拟技术&#xff0c;诞生于2013年&#xff0c;是dotCloud公司研发的开源项目&#xff0c;因为docker这个公司后来改名docker inc&#xff0c;docker的目标是实现轻量级的操作系统虚拟化解决方案。通俗点说&#xff0c;我们想在一台机器上运行多个系…

opencv(3):控制鼠标,创建 tackbar控件

文章目录 控制鼠标相关APIsetMouseCallbackcallback TrackBar 控件cv2.createTrackbarcv2.getTrackbarPos&#xff1a; 控制鼠标相关API setMouseCallback(winname, callback, userdata)callback(event, x, y, flags, userdata) setMouseCallback 在 OpenCV 中&#xff0c;s…

搞定这套Python爬虫面试题,大厂Offer拿到手软

文章目录 1、简述Python 的特点和优点2、Python 有哪些数据类型&#xff1f;3、列表和元组的区别4、Python 是如何运行的5、Python 运行速度慢的原因6、面对 Python 慢的问题&#xff0c;有什么解决办法7、描述一下全局解释器锁 GIL8、深拷贝 浅拷贝9、is 和 的区别10、文件读…

ZYNQ_project:uart(odd,even)

概念&#xff1a; UART&#xff08;Universal Asynchronous Receiver-Transmitter&#xff09;&#xff1a;即通用异步收发器&#xff0c;是一种通用串行数据总线&#xff0c;用于异步通信。一般UART接口常指串口。 UART在发送数据时将并行数据转换成串行数据来传输&#xff…

【数据结构(二)】稀疏 sparsearray 数组(1)

文章目录 1. 稀疏数组的应用场景1.1. 一个实际的需求1.2. 基本介绍 2. 稀疏数组转换的思路分析3. 稀疏数组的代码实现3.1. 二维数组转稀疏数组3.2. 稀疏数组转二维数组 4. 课后练习 1. 稀疏数组的应用场景 1.1. 一个实际的需求 问题&#xff1a;     编写的五子棋程序中&…

JavaEE初阶 01 计算机是如何工作的

前言 今天开始进行对JavaEE的一些基本总结,希望大家能在阅读中有所收获,如有错误还望多多指正. 1.冯诺依曼体系结构 这个体系结构相信学计算机的同学都不陌生,但是你真的知道这个体系结构说的是什么嘛?请听我娓娓道来.首先我先给出一张冯诺依曼体系结构的简图 你可以理解为当前…

资深品酒师荆芳老师倾情力作,带你品酒选酒,读懂葡萄酒的世界

在美酒琳琅满目的今天&#xff0c;如何才能挑选到适合自己的葡萄酒&#xff1f;如何品鉴葡萄酒的独特魅力&#xff1f;资深品酒师荆芳老师的最新力作《葡萄酒爱好者》正式上线&#xff0c;带你走进葡萄酒的世界&#xff0c;领略品酒选酒的奥秘。作为一位资深的品酒师和教育工作…

leetcode - 串联所有单词的子串 - 最小覆盖子串 - x 的平方根

I30. 串联所有单词的子串 - 力扣&#xff08;LeetCode&#xff09; 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab&qu…

卡方检验-python代码

故事背景 问题 卡方检验的结果怎么计算&#xff1f; 方法 python代码 import numpy as np from scipy.stats import chi2_contingency# 观察频数矩阵 observed np.array([[47, 21, 17],[63, 29, 15],[11, 2, 4]])# 进行卡方检验 chi2, p, dof, expected chi2_contingency(o…

电子器件系列44:环形线圈电感

干货&#xff01;电感最重要、最常见的几个作用_线圈 环形线圈电感的原理&#xff1a; 电感中包含了哪三个物理学定律&#xff0c;为什么它能以磁场形式储能_哔哩哔哩_bilibili 电感的基本原理_哔哩哔哩_bilibili 环形线圈电感的作用: 1.储能器&#xff1a; 环形线圈电感能够…

Neo4j安装(Docker中安装Neo4j)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

【漏洞复现】用友U8-Cloud 存在任意文件上传漏洞

漏洞描述 U8 cloud 聚焦成长型、创新型企业的云 ERP,基于全新的企业互联网应用设计理念,为企业提供集人财物客、产供销于一体的云 ERP 整体解决方案,全面支持多组织业务协同、智能财务,人力服务、构建产业链智造平台,融合用友云服务实现企业互联网资源连接、共享、协同。…

Windows 安装 汉化版 burp suite

注&#xff1a;个人笔记&#xff0c;仅供参考。 burpsuite 软件下载链接&#xff1a; https://www.alipan.com/s/cWxMF5S9sq4 提取码: 31ut 注&#xff1a;安装路径不要有中文 安装 配置 Java 环境 因为burpsuite是在JAVA环境下运行的&#xff0c;所以首先应该配置好JAVA环…

浙大恩特客户资源管理系统 SQL注入漏洞复现

0x01 产品简介 浙大恩特客户资源管理系统是一款针对企业客户资源管理的软件产品。该系统旨在帮助企业高效地管理和利用客户资源&#xff0c;提升销售和市场营销的效果。 0x02 漏洞概述 浙大恩特客户资源管理系统中T0140_editAction.entweb接口处存在SQL注入漏洞&#xff0c;未…

解决Error:java: System Java Compiler was not found in classpath

解决Error:java: System Java Compiler was not found in classpath 一、配置maven 注意:我的C盘比较大直接配置在了C盘&#xff0c;建议配置到其他盘&#xff0c;记得做maven环境变量配置 二、卸载本地JDK&#xff0c;换个版本安装配置环境变量 重启电脑或idea&#xff0c;…

React经典初级错误

文章 前言错误场景问题分析解决方案后言 前言 ✨✨ 他们是天生勇敢的开发者&#xff0c;我们创造bug&#xff0c;传播bug&#xff0c;毫不留情地消灭bug&#xff0c;在这个过程中我们创造了很多bug以供娱乐。 前端bug这里是博主总结的一些前端的bug以及解决方案&#xff0c;感兴…

Linux环境下C++ 接入OpenSSL

接上一篇&#xff1a;Windows环境下C 安装OpenSSL库 源码编译及使用&#xff08;VS2019&#xff09;_vs2019安装openssl_肥宝Fable的博客-CSDN博客 解决完本地windows环境&#xff0c;想赶紧在外网环境看看是否也正常。毕竟现在只是HelloWorld级别的&#xff0c;等东西多了&am…

如何在latex中高亮文本

导入soul 包可以使用高亮功能 在文本中插入 \hl{} 即可 导入color 包可以使用颜色功能 color 也可以替换成 xcolor \documentclass{report} \usepackage{xcolor,soul} \begin{document}\textcolor{red}{Text}\hl{Text} \hl{\textbf{Text}} \textbf{\textcolor{red}{\hl{Text}…