0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用Linux系统下的输入设备进行应用编程

嵌入式开发爱好者 来源:嵌入式开发爱好者 作者:嵌入式开发爱好者 2022-11-10 10:10 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

今天主要来聊一聊,如何使用Linux系统下的输入设备进行应用编程

第一:什么是输入设备

先来了解一下什么是输入设备(称为input设备),常见的输入设备有鼠标、键盘、触摸屏、遥控器、画图板等,用户通过输入设备与系统进行交互。

由上面可知,输入设备种类非常多,那么Linux系统如何管理呢?Linux系统为了统一管理这些输入设备,实现了一套能够兼容所有输入设备的框架,那么这个框架就是input子系统。驱动开发人员基于input子系统开发输入设备的驱动程序,input子系统可以屏蔽硬件的差异,向应用层提供一套统一的接口

基于input子系统注册成功的输入设备,都会在/dev/input目录下生产对应的设备节点(设备文件),设备文件节点名称通常为eventX()(X表示一个数字编号0,1,2,3,等),譬如/dev/input/event0、/dev/input/event1、/dev/input/event2 等,通过读取这些设备节点可以获取输入设备上报的数据。

第二:读取数据的流程

如果我们要读取触摸屏的数据,假设触摸屏设备对应的设备节点为/dev/input/event0,那么数据读取流程如下:

1、应用程序打开/dev/input/event0设备文件。

2、应用程序发去读操作(譬如调用read),如果没有数据可读则会进入休眠(阻塞I/O情况下)。

3、当有数据可读时,应用程序会被唤醒,读操作获取到数据返回。

4、应用程序对读取到的数据进行解析。

当无数据可读时,程序会进入休眠状态(也就是阻塞),譬如应用程序读触摸屏数据,如果当前并没有去触碰触摸屏,自然是无数据可读。当我们用手指触摸触摸屏或者在屏上滑动时,此时就会产生触摸数据、应用程序就有数据可读了,应用程序会被唤醒,成功读取到数据。那么对于其它输入设备亦是如此,无数据可读时应用程序会进入休眠状态(阻塞式 I/O 方式下),当有数据可读时才会被唤醒。

第三:应用程序该如何解析

应用程序打开输入设备对应的设备文件,向其发起读操作,那么这个读操作获取到的是什么样的数据呢?其实每一次read操作获取的都是一个struct input_event结构体数据,该结构体定义在头文件中,它的定义如下:

structinput_event{
structtimeval time;
__u16 type;
__u16 code;
__s32value;
};

结构体中的time成员变量是一个struct timeval类型的变量,该结构体在前面给大家介绍过,内核会记录每个上报的事件及发生的时间,并通过变量 time 返回给应用程序。时间参数通常不是那么重要,而其它3 个成员变量 type、code、value 更为重要。

type:用于描述发生了哪一种类型的事件,Linux系统所支持的输入事件类型如下所示:

#define EV_SYN 0x00 //同步类事件,用于同步事件
#define EV_KEY 0x01 //按键类事件
#define EV_REL 0x02 //相对位移类事件(譬如鼠标)
#define EV_ABS 0x03 //绝对位移类事件(譬如触摸屏)
#define EV_MSC 0x04 //其它杂类事件

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

code:code表示该类事件中的哪一个具体事件,以上列举的每一种事件类型中都包含一系列具体事件,譬如一个键盘通常有很多按键,譬如字母A、B、C、D或者数字1、2、3、4等,而code变量则告知应用程序是哪一个按键发生了输入事件。每一种事件类型包含多种不同的事件,譬如按键类事件;

#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 键

相对位移事件

#define REL_X 0x00 //X 轴
#define REL_Y 0x01 //Y 轴
#define REL_Z 0x02 //Z 轴
#define REL_RX 0x03
#define REL_RY 0x04

绝对位移事件

触摸屏设备是一种绝对位移设备,它能产生绝对位移事件;譬如对于触摸屏来说,一个触摸点所包含的信息可能有多种,譬如触摸点的X轴坐标、Y轴坐标、Z轴坐标,按压大小以及接触面积等,所以code变量告知应用程序当前上报的是触摸点的哪一种信息。

#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

以上除了列举出来的之外,还有很多,大家可以预览头文件。

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 值而定!

第四:数据同步方法

应用程序读取输入设备上报的数据时,一次 read 操作只能读取一个 struct input_event 类型数据,譬如对于触摸屏来说,一个触摸点的信息包含了 X 坐标、Y 坐标以及其它信息,对于这样情况,应用程序需要执行多次 read 操作才能把一个触摸点的信息全部读取出来,这样才能得到触摸点的完整信息。那么应用程序如何得知本轮已经读取到完整的数据了呢?其实这就是通过同步事件来实现的,内核将本轮需要上报、发送给接收者的数据全部上报完毕后,接着会上报一个同步事件,以告知应用程序本轮数据已经完整、可以进行同步了。

所有的输入设备都需要上报同步事件通常是SYN_REPORT,而value值通常为0。

第五:读取struct input_event数据代码实现

对输入设备调用read()会读取到一个struct input_event类型数据。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc, char *argv[])
{
 struct input_event in_ev = {0};
 int fd = -1;
  /* 校验传参 */
 if (2 != argc) {
 fprintf(stderr, "usage: %s 
", argv[0]);
 exit(-1);
 }
 /* 打开文件 */
 if (0 > (fd = open(argv[1], O_RDONLY))) {
 perror("open error");
 exit(-1);
 }
 for ( ; ; ) {
 /* 循环读取数据 */
 if (sizeof(struct input_event) !=
 read(fd, &in_ev, sizeof(struct input_event))) {
 perror("read error");
 exit(-1);
 }
 printf("type:%d code:%d value:%d
",
 in_ev.type, in_ev.code, in_ev.value);
 }
}

分析:该案件是,在出厂系统中,该案件驱动基于input子系统而实现,所以在/dev/input目录下存在KEY0的设备节点,具体是哪个设备节点,可以查看/proc/bus/input/devices文件得知。

3121c894-6042-11ed-8abf-dac502259ad0.png

执行结果如下:

3163918e-6042-11ed-8abf-dac502259ad0.png

程序运行后,执行按下 KEY0、松开 KEY0 等操作,终端将会打印出相应的信息,如上图所示。

第一行中 type 等于 1,表示上报的是按键事件 EV_KEY,code=114,打开 input-event-codes.h 头文件进行查找,可以发现 cpde=114 对应的是键盘上的 KEY_VOLUMEDOWN 按键,这个开发板出厂系统已经配置好的。而 value=1 表示按键按下,所以整个第一行的意思就是按键 KEY_VOLUMEDOWN被按下。

第二行,表示上报了 EV_SYN 同步类事件(type=0)中的 SYN_REPORT 事件(code=0),表示本轮数据已经完整、报告同步。

第三行,type 等于 1,表示按键类事件,code 等于 114、value 等于 0,所以表示按键 KEY_VOLUMEDOWN被松开。

第四行,又上报了同步事件。

所以整个上面 4 行的打印信息就是开发板上的 KEY0 按键被按下以及松开这个过程,内核所上报的事件以及发送给应用层的数据 value。我们试试长按按键 KEY0,按住不放,如下所示:

31915678-6042-11ed-8abf-dac502259ad0.png

可以看到上报按键事件时,对应的 value 等于 2,表示长按状态。

总结:使用好标准的输入设备系统,对实现输入功能具有重要意义。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 触摸屏
    +关注

    关注

    42

    文章

    2439

    浏览量

    120935
  • Linux
    +关注

    关注

    88

    文章

    11628

    浏览量

    217956

原文标题:Linux系统中输入设备的控制方法

文章出处:【微信号:嵌入式开发爱好者,微信公众号:嵌入式开发爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    【书籍评测活动NO.67】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    景化应用的完整体系。从Linux内核开发的环境搭建、模块编程,到设备树、总线驱动,再到内存优化、DMA 技术,最后到IIO、GPIO、输入系统
    发表于 11-17 17:52

    基于Hbird-e-sdk Linux环境使用Uart0 对串口进行输入的软件代码参考

    本次代码是基于hbird-e-sdksoftware参考示例demo_gpio的中断代码实现相应更改,然后通过蜂鸟调试器连接的UART0实现对串口的输入(PC/LINUX) 一.软件头文件修改
    发表于 10-31 06:32

    飞凌嵌入式ElfBoard-系统应用编程之文件I/O

    1.1 文件I/O的简单概念本章节仅作为初识简单概念,在后续章节会对相关概念进行深入介绍。在linux系统中有一个概念,一切皆文件,所有的设备都以文件形式存在。几乎所有的
    发表于 10-24 08:57

    是否可以通过 CLI 在 Linux 上通过 Nu-Link 对 M2354 MCU 进行编程

    是否可以通过 CLI 在 Linux 上通过 Nu-Link 对 M2354 MCU 进行编程? 我正在尝试从运行 armbian 最小版本的基于 arm 的 PC 对 M2354 MCU
    发表于 08-18 08:10

    开源系统适配:聚徽分享国产工控平板在 Linux / 鸿蒙系统的技术优化

    工控平板进行技术优化,实现与 Linux、鸿蒙系统的高效适配,成为行业关注的焦点。 一、Linux 系统
    的头像 发表于 06-13 16:29 711次阅读

    能否提供LinuxUSB转SPI模式的测试程序?

    我已在 Linux 上成功配置了 CY7C65211 器件,使其在 USB 转 SPI 模式运行。 使用 lsusb 命令,设备显示如下:总线 003 设备 002:ID 04b4:
    发表于 05-22 06:16

    不借助Linux系统,在Windows如何搭建ZMC900E交叉编译环境

    嵌入式Linux系统,由于系统资源的匮乏,通常无法安装本地编译器进行本地开发,而需要在借助一台主机进行交叉开发。一般情况
    的头像 发表于 05-21 11:34 648次阅读
    不借助<b class='flag-5'>Linux</b><b class='flag-5'>系统</b>,在Windows<b class='flag-5'>下</b>如何搭建ZMC900E交叉编译环境

    嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-input子系统之input子系统简介

    Linux系统中,Input子系统是一个用于处理输入设备的软件框架。它提供了一种统一的接口和机制,使得各种
    发表于 04-15 10:42

    飞凌嵌入式ElfBoard ELF 1板卡-input子系统之input子系统简介

    Linux系统中,Input子系统是一个用于处理输入设备的软件框架。它提供了一种统一的接口和机制,使得各种
    发表于 04-15 10:27

    Linux的作用

    。 2、嵌入式系统Linux可以被嵌入到各种嵌入式设备中,如智能路由器、智能电视等。它提供了一个灵活的平台,可以根据设备的需求进行定制和优
    发表于 04-04 01:57

    LinuxVim编辑器的使用技巧

    【Vim】常用总结⟳ 简介⟳ image 什么是vim?⟳ Linux两大编辑神器之一 vim • Linux/Unix使用最多的编辑器 • vi的改进版 • 可能是最难上手的编辑
    的头像 发表于 04-01 17:36 1029次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>下</b>Vim编辑器的使用技巧

    嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-Linux设备驱动的分类

    设备和块设备都映射到了虚拟文件系统目录下。应用程序可以通过系统调用接口open、close、write、read等相关API进行访问字符
    发表于 03-12 10:20

    飞凌嵌入式ElfBoard ELF 1板卡-Linux设备驱动的分类

    设备和块设备都映射到了虚拟文件系统目录下。应用程序可以通过系统调用接口open、close、write、read等相关API进行访问字符
    发表于 03-10 17:00

    Linux系统安装中文环境和中文输入法(),触觉智能嵌入式开发板

    触觉智能经验分享,Linux系统安装中文环境和中文输入法(
    的头像 发表于 02-26 16:26 817次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>系统</b>安装中文环境和中文<b class='flag-5'>输入</b>法(<b class='flag-5'>下</b>),触觉智能嵌入式开发板

    Linux系统安装中文环境和中文输入法(上),触觉智能嵌入式开发板

    触觉智能经验分享,Linux系统安装中文环境和中文输入法(上)
    的头像 发表于 02-26 16:23 1074次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>系统</b>安装中文环境和中文<b class='flag-5'>输入</b>法(上),触觉智能嵌入式开发板