Linux输入设备应用编程(键盘,按键,触摸屏,鼠标)

news2024/10/7 16:25:45

目录

一 输入设备编程介绍

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/1221236.html

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

相关文章

使用Microsoft Dynamics AX 2012 - 2. 入门:导航和常规选项

Microsoft Dynamics AX的核心原则之一是为习惯于Microsoft软件的用户提供熟悉的外观和感觉。然而&#xff0c;业务软件必须适应业务流程&#xff0c;这可能相当复杂。 用户界面和常见任务 在我们开始进行业务流程和案例研究之前&#xff0c;我们想了解一下本章中的常见功能。…

linux 查看命令使用说明

查看命令的使用说明的命令有三种&#xff0c;但并不是每个命令都可以使用这三种命令去查看某个命令的使用说明&#xff0c;如果一种不行就使用另外一种试一试。 1.whatis 命令 概括命令的作用 2.命令 --help 命令的使用格式和选项的作用 3.man 命令 命令的作用和选项的详细…

小白必看,接口测试神器 Jmeter 如何实现测试关联

明年三四月份赶上跳槽高峰期&#xff0c;面试中&#xff0c;接口测试部分的关联是经常被提及的知识点之一&#xff0c;经常有同学因此错失良机&#xff0c;“关联”可谓是重中之重了&#xff0c;今天就写一篇关于Jmeter关联的文章&#xff0c;以作备忘。 所谓关联&#xff0c;…

交易者最看重什么?anzo Capital这点最重要!

交易者最看重什么&#xff1f;有人会说技术&#xff0c;有人会说交易策略&#xff0c;有人会说盈利&#xff0c;但anzo Capital认为Vishal 最看重的应该是眼睛吧&#xff01; 29岁的Vishal Agraval在9年前因某种原因失去了视力&#xff0c;然而&#xff0c;他的失明并未能阻…

回顾——自我监督的 Vision Transformer 学到了什么?

一、说明 在尝试自我监督学习时&#xff0c;主要有两种方法&#xff1a;对比学习&#xff08;CL&#xff09;和掩模图像建模&#xff08;MIM&#xff09;。然而&#xff0c;随着MIM最近受到关注&#xff0c;很多人使用MIM&#xff0c;但他们可能不知道为什么使用它以及何时应该…

每天一道算法题(四)——移动零(将数组中的零移到最后面)

文章目录 前言1、问题2、示例3、解决方法&#xff08;1&#xff09;方法1&#xff08;2&#xff09;方法2&#xff08;双指针&#xff09; 前言 提示&#xff1a; 1、问题 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的…

C#调用C++ dll教程

文章目录 一、创建C dll项目二、C#程序员调用C dll三、C与C#数据类型对应基本数据类型对应表C指针类型与C#类型 在使用C#开发客户端时&#xff0c;有时需要调用C dll&#xff0c;本篇博客来介绍C#程序如何调用C dll。 一、创建C dll项目 首先使用VS2022创建C dll项目&#xf…

c语言-数据结构-堆

目录 一、二叉树 1、二叉树的概念 2、完全二叉树和满二叉树 3、完全二叉树的顺序存储 二、堆 2、堆的概念与结构 3、堆的创建及初始化 4、堆的插入&#xff08;小堆&#xff09; 5、堆的删除 6、显示堆顶元素 7、显示堆里的元素个数 8、测试堆的各个功能 9、 实现堆…

TMS320F28335使用多个串口时,SCIRXST Register出现错误

TMS320F28335使用多个串口时&#xff0c;SCIRXST Register出现错误 void ClearErrorState(void) {if((SciaRegs.SCIRXST.bit.FE 1)||(SciaRegs.SCIRXST.bit.BRKDT 1)){SciaRegs.SCICTL1.bit.SWRESET 0;SciaRegs.SCICTL1.bit.SWRESET 1;}if((ScibRegs.SCIRXST.bit.FE 1)||(S…

面试题 Android 如何实现自定义View 固定帧率绘制

曾经遇到的面试题, 如何实现自定义View 1s内固定帧率的绘制. 当时对Android理解不深, 考虑的不全面, 直接回答了在onDraw结束时通过postDelay发送一个(1000 / 帧数)ms的延时消息触发invalidate进行下一次绘制. 但实际上这样做存在明显的问题 实际上1s绘制的帧数是不符合期望帧…

FindMy技术用于保温杯

在即将到来的冬季&#xff0c;每个人都开始给自己准备一个保温杯&#xff0c;保温杯是一种盛水的容器&#xff0c;主要由陶瓷或不锈钢制成&#xff0c;并加入真空层&#xff0c;以实现保温效果。这种杯子顶部有盖&#xff0c;密封严实&#xff0c;能够延缓内部液体散热&#xf…

基于黏菌算法优化概率神经网络PNN的分类预测 - 附代码

基于黏菌算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于黏菌算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于黏菌优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

echarts 横向柱状图示例

该示例有如下几个特点&#xff1a; ①实现tooltip自定义样式&#xff08;echarts 实现tooltip提示框样式自定义-CSDN博客&#xff09; ②实现数据过多时滚动展示&#xff08;echarts 数据过多时展示滚动条-CSDN博客&#xff09; ③柱状图首尾展示文字&#xff0c;文字内容嵌入图…

【MMC/SD/SDIO】读写操作

SD 总线是基于命令和数据流&#xff0c;它们由一个开始 Bit 发起&#xff0c;由一个停止 Bit 结束。 Command&#xff1a;命令开始一个操作。命令由 Host 驱动&#xff0c;或者给单卡&#xff08;寻址命令&#xff09;&#xff0c;或者给所有连接的卡&#xff08;广播命令&…

【EI会议征稿】第七届大数据与应用统计国际学术研讨会(ISBDAS 2024)

第七届大数据与应用统计国际学术研讨会&#xff08;ISBDAS 2024&#xff09; 2024 7th International Symposium on Big Data and Applied Statistics 第七届大数据与应用统计国际学术研讨会&#xff08;ISBDAS 2024&#xff09;定于2024年3月8-10日在中国上海举行。会议旨在…

红黑树的插入与验证

红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路 径会比其他路径长出俩倍&#xff0c;因而是接近平衡的…

微信小程序获取手机号报错getPhoneNumber:fail no permission

目录 一、问题描述二、解决方法 一、问题描述 微信小程序调用 API 获取手机号报错&#xff1a; getPhoneNumber:fail no permission二、解决方法 小程序没有认证&#xff0c;需要对小程序进行微信认证。如果是复用公众号资质认证&#xff0c;在公众号关联小程序后&#xff0…

EtherCAT 伺服控制功能块实现

EtherCAT 是运动控制领域主要的通信协议&#xff0c;开源EtherCAT 主站协议栈 IgH 和SOEM 两个项目&#xff0c;IgH 相对更普及一些&#xff0c;但是它是基于Linux 内核的方式&#xff0c;比SOEM更复杂一些。使用IgH 协议栈编写一个应用程序&#xff0c;控制EtherCAT 伺服电机驱…

MIKE水动力笔记19_统计平均潮差

本文目录 前言Step 1 ArcGIS中创建渔网点Step 2 将dfsu数据提取到渔网点Step 3 Python统计平均潮差 前言 日平均潮差&#xff08;average daily tidal range&#xff09;&#xff1a;日高潮潮高合计之和除以实有高潮个数为日平均高潮潮高&#xff0c;日低潮潮高合计之和除以实…

【漏洞复现】NUUO摄像头存在远程命令执行漏洞

漏洞描述 NUUO摄像头是中国台湾NUUO公司旗下的一款网络视频记录器&#xff0c;该设备存在远程命令执行漏洞&#xff0c;攻击者可利用该漏洞执行任意命令&#xff0c;进而获取服务器的权限。 免责声明 技术文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&…