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

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,运行测试程序并按下、松开键盘上的按键:

  • 38
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
嵌入式Linux系统开发技术是一个较为广泛的领域,其中以基于ARM的嵌入式系统应用较为常见。嵌入式Linux系统的开发技术可以涵盖从硬件平台的选择到Linux内核的移植,再到应用程序的开发等方面。以下是关于嵌入式Linux系统开发技术的详细解释。 硬件平台选择:首先需要进行硬件平台的选择,确定嵌入式设备所需的处理器、内存、存储等组件规格。由于ARM架构的设计优势,小型化、低功耗、价格实惠等特点,ARM处理器得到了广泛应用,并成为最受欢迎的嵌入式处理器之一。因此,选择基于ARM架构的嵌入式平台也成为了最常见的选择。 移植Linux内核:对于选择的硬件平台,需要进行Linux内和的移植,这样才能在嵌入式设备上运行Linux系统。有关ARM平台的内核移植,需要一个交叉编译工具链,以允许在主机上编译ARM平台的内核。内核移植大量依赖高级的交叉编译技术,需要深入了解编译规则、配置文件修改和编译选项等技术。 设备驱动开发设备驱动是嵌入式Linux系统最重要的核心内容之一,负责管理外部设备设备驱动的编写第一要件是了解设备硬件特性,需要具备一定的硬件电路知识。对于具体的外设需要进行详细的驱动开发,如磁盘驱动、键盘驱动等。 应用程序开发:完成内核移植和设备驱动的编码后,紧接着就是应用程序的开发。嵌入式Linux系统的应用程序需要根据具体需求进行开发,在编写过程中需要对硬件资源的使用和管理进行严格考虑,避免出现内存泄漏、死锁、内核过载等问题。因此,对C/C++开发技术的掌握是优秀的嵌入式Linux系统应用程序开发必不可少的能力。 综上所述,嵌入式Linux系统开发涉及硬件平台的选择、内核移植、设备驱动开发应用程序开发等多个方面。在基于ARM的嵌入式系统应用中,Linux内核的移植是关键步骤,需要学习交叉编译技术,硬件驱动开发应用程序开发也同样重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@ChenPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值