嵌入式Linux应用_学习笔记(4:输入系统应用编程)

文章介绍了Linux下的输入系统,包括内核输入子系统、输入事件核心、事件处理和键盘鼠标事件处理程序。详细讲解了如何获取输入设备信息,如通过/dev/input和/proc/bus/input/devices,并提供了编写代码读取鼠标和键盘事件的例子,强调了事件的type、code和value在处理输入事件中的作用。
摘要由CSDN通过智能技术生成

这些内容均是留给自己用作学习笔记,如有错误,请批评指正!!!



前言

我们这一章主要学习如何编写代码来读取外部的输入设备


一、什么是输入系统

在Linux下,输入系统是指用于接收和处理用户输入设备(比如键盘、鼠标等)输入的软件系统。输入系统通常由以下几个组件构成:
1.内核输入子系统:负责驱动硬件设备,并将输入事件转换为内核中的事件结构体,发出一个内核事件。
2.输入事件核心:允许用户应用程序在用户空间读取内核事件。
3.输入事件处理:提供用户空间进程以一种统一的方式来管理输入事件的家族和多样化,同时也包括通过特殊的设备文件来定义输入设备类型和配置输入设备。
4.键盘和鼠标事件处理程序:在用户空间中运行,负责监听内核事件核心并处理用户输入设备的输入事件,例如响应键盘和鼠标事件并将它们转换为诸如移动光标和触发键盘快捷键等高级操作。
总之,在Linux系统下,输入系统是为用户提供与硬件输入设备进行交互的基础软件组件。
如图所示
在这里插入图片描述
举个非常简单的例子,比如用户按下键盘里的其中一个按键,它遵循流程是这样的:
​按键按下–>输入系统驱动层–>输入系统核心层–>输入系统事件层—>用户空间
​对于应用程序软件编程的角度,我们只需要关注用户空间是怎么得到按键按下以后获取的是什么事件就可以了,例如我想知道我当前按下的按是短按还是长按?或者我想知道当前我按下键盘的是空格键还是回车键等等。

二、获取输入设备信息

确定设备信息:输入设备的设备节点名为/dev/input/eventX(也可能是/dev/eventX, X表示 0、 1、 2 等数字)。查看设备节点,可以执行以下命令:

ls /dev/input

在这里插入图片描述
通过下面这条指令可以知道设备节点对应什么硬件?

cat /proc/bus/input/devices

在这里插入图片描述
I:id of the device(设备 ID)

N:name of the device设备名称

P:physical path to the device in the system hierarchy系统层次结构中设备的物理路径。

S:sysfs path位于 sys 文件系统的路径

U:unique identification code for the device(if device has it)设备的唯一标识码

H:list of input handles associated with the device.与设备关联的输入句柄列表。

B:bitmaps(位图)

值得注意的是 B 位图,比如上图中“ B: EV=b”用来表示该设备支持哪类输入事件。 b 的二进制是 1011, bit0、 1、 3 为 1,表示该设备支持 0、 1、 3 这三类事件,即 EV_SYN、 EV_KEY、 EV_ABS。

再举一个例子,“ B: ABS=2658000 3”如何理解?

它表示该设备支持 EV_ABS 这一类事件中的哪一些事件。这是 2 个 32 位的数 字: 0x2658000、 0x3, 高位在 前低 位在 后, 组成一 个 64 位 的数字 :“ 0x2658000,00000003”,数值为 1 的位有: 0、 1、 47、 48、 50、 53、 54,即:0、 1、 0x2f、 0x30、 0x32、 0x35、 0x36,对应以下这些宏:

在这里插入图片描述

系统框架

在这里插入图片描述

在input子系统中,每个事件的发生都使用事件(type)->子事件(code)->值(value) 所有的输入设备的主设备号都是13,输入系统核心层通过次设备来将输入设备进行分类,如0-31是游戏杆,32-63是鼠标(对应Mouse Handler)、64-95是事件设备(如触摸屏,对应Event Handler)。
在input.h中的源码:

struct input_event {
	struct timeval time;
	__u16 type;
	__u16 code;
	__s32 value;
};

timeval 表示的是“自系统启动以来过了多少时间”,它是一个结构体,含有“ tv_sec、 tv_usec”两项(即秒、微秒)。

支持的事件类型

举几个例子,如同步事件,按键事件,按压屏幕时的坐标变化

事件类型编码含义
EV_SYN0x00同步事件
EV_KEY0x01按键事件
EV_REL0x02相对坐标
EV_ABS0x03绝对坐标
驱动程序上报完一系列的数据后,会上报一个“同步事件”,表示数据上报完毕。 APP 读到“同步事件”时,就知道已经读完了当前的数据。同步事件也是一个 input_event 结构体,它的 type、code、 value 三项都是 0。

三、编写代码来测试鼠标、键盘

先要确定对应关系,上图中我已经知道了我的电脑处理鼠标事件的是event2,处理键盘事件的是event1,可以使用hexdump命令显示数据。

hexdump /dev/input/event2 //event3、event4

分步骤来实现编程:
第一步:定义一个事件的结构体变量,我们要用到事件,需要得到事件,在程序中肯定需要一个变量来描述这个事件。

第二步:打开设备节点,Linux中一切皆文件,所以用open函数,打开输入设备节点

第三步:读取事件,读取打开的输入设备节点中的数据,到我们第一步的定义的事件变量中

第四步:利用获取的事件信息来完成我们自己编写的处理逻辑,这里就简单输出一下鼠标位置,键盘按下时的code和value值。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>
#include <string.h>
//sudo ./event_mice_test /dev/input/event2  鼠标事件

//sudo ./event_mice_test /dev/input/event1  键盘事件

int main(int argc,char **argv)
{
    //1、定义一个结构体变量用来描述input事件
    struct input_event event_mouse ;
	struct input_event event_keybored;
	if (argc != 2)
	{
		printf("Must need two argv!\n");
		return -1 ;
	}
    //2、打开input设备的事件节点  
	//我的通用USB鼠标事件的节点是event2,通用键盘事件的节点是event1
	int fd    = -1 ;
	fd = open(argv[1], O_RDWR,0664);
    if(-1 == fd)
    {
        printf("open %s event fair!\n",argv[1]);
        return -1 ;
    }

	if(strcmp(argv[1],"/dev/input/event2")==0)
	{
		while(1)
		{
			//3、读鼠标事件
			read(fd, &event_mouse, sizeof(event_mouse));
		  	if(EV_ABS == event_mouse.type)
		   {
			//code表示位移X或者Y,当判断是X时,打印X的位移value
			   //当判断是Y时,打印Y的位移value
				if(event_mouse.code == ABS_X)
				{
					printf("event_mouse.code_X:%d\n", event_mouse.code);
					printf("event_mouse.value_X:%d\n", event_mouse.value);
				}
				else if(event_mouse.code == ABS_Y)
				{
					printf("event_mouse.code_Y:%d\n", event_mouse.code);
					printf("event_mouse.value_Y:%d\n", event_mouse.value);
				}
			}
		}
	}
	else
	{
		while(1)
		{
			//3、读键盘事件
			read(fd, &event_keybored, sizeof(event_keybored));
		  	if(EV_KEY == event_keybored.type)
		   {
		   		printf("event_keybored.type:%d\n", event_keybored.type);
				printf("event_keybored.code:%d\n", event_keybored.code);
				printf("event_keybored.value:%d\n", event_keybored.value);
			}
		}
	}
    
    close(fd);
    return 0 ;
}


在这里插入图片描述
在这里插入图片描述

运行的时候需要添加sudo命令,因为打开设备文件时需要root权限。

总结

这章对输入系统有了一定的了解,明确了驱动程序会上报什么事件,事件内有什么数值如type,code,value等,并能够对输入系统应用编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值