Linux 输入子系统原理理解(原创)

linux    输入子系统原理理解(原创)

以前学了单独的按键设备驱动以及鼠标驱动,实际上,在linux中实现这些设备驱动,有一种更为推荐的方法,就是input输入子系统。平常我们的按键,触摸屏,鼠标等输入型设备都可以利用input接口来简化驱动程序并实现设备驱动。

输入子系统原理

linux输入子系统的体系结构可以分为三个层面,分别为:驱动层、输入核心层、事件处理层,三个有点类似PHP的MVC模式,意思就是每个层次只是负责单独的一个功能,无需参与其他的功能,有点类似函数的封装,好了,废话不多说,三个层面具体的功能如下:

(1)驱动层:将底层的硬件输入转化为统一的事件类型,向输入核心(input core)汇报0,简单来说,驱动层就是负责汇报事情。

(2)输入核心层:为驱动层提供输入设备的注册和操作接口。

比如: 1. 用input_register_device函数对设备进行注册;

2. 通知事件处理层对事件进行处理;

3. 在/proc下产生相应的设备信息。

(3)事件处理层:主要作用就是与用户空间进行交互。包含提供驱动程序的fops接口,在/dev下生成相应的设备文件节点nod等功能。

总的来说,归纳一下上面的一大段内容:

一个事件,如鼠标移动,键盘按下事件,首先通过 
 驱动层Driver --> 输入核心层 InputCore-->事件处理层Event handler-->用户空间userspace的顺序来完成事件的响应。

设备描述

Input设备用input_dev结构体来描述。

在input子系统实现设备驱动程序中,驱动的核心工作是向系统报告按键,触摸屏,鼠标等事件,无须关心文件操作接口,因为这些接口是有事件处理层Event handler来实现的。

好了,原理讲的差不多了,接下来讲一下驱动的实现

驱动实现

1.事件支持

首先一个设备驱动,我们应该通过set_bit()函数来告诉输入子系统它支持哪些事件,哪些按键,例如:

Set_bit(EV_KEY,button_dev.evbit);            告诉输入子系统支持按键的时间

Struct input_dev中有两个成员:

Evbit: 事件类型

Keybit: 按键类型

事件类型:

EV_RST            reset                   EV_KEY            按键

EV_REL            相对坐标     EV_ABS      绝对坐标

EV_MSC            其他                  EV_LEC            LED

EV_SND            声音                   EV_REP            repeat

EV_FF            力反馈

但事件类型为EV_KEY时,还需指明按键类型:

BTN_LEFT:      鼠标左键            BTN_0:数字0键

BTN_RIGHT:      鼠标右键            BTN_1:数字1键

BTN_MIDDLE:      鼠标中键

2.报告事件

当事件真的发生的时间,我们的驱动层应该向输入核心层Input Core来报告EV_KEY,EV_REL,EV_ABS等事件,报告函数分别为:

Void input_report_key(struct input_dev *dev,unsigned int code, int value)

Void input_report_rel(struct input_dev *dev,unsigned int code, int value)

Void input_report_abs(struct input_dev *dev,unsigned int code, int value)

Code: 事件的代码:如果事件类型是EV_KEY, 则该代码则为设备的键盘代码,例如键盘上按键代码值为0~127 ,鼠标键代码值为0x110 ~ 0x116 具体请参考include/linux/input.h文件

Value:事件的值。如果事件类型是EV_KEY, 按键按下时值为1,松开即为0

3.报告结束

Input_sync()用于告诉输入核心层input core:此次报告已经结束

例如,在触摸屏设备驱动中,一次点击的整个报告事件过程如下:

Input_report_abs(input_dev, ABS_X, x);      //报告X坐标

Input_report_abs(input_dev, ABS_Y, y);      //报告Y坐标

Input_report_abs(input_dev, ABS_PRESSURE, 1);      //报告事件类型为按下,且value值为1

Input_sync(input_dev);      //报告完毕,同步事件

一个按键驱动程序的局部函数:

//在按键中断中报告事件

Static void buton_interrupt(int irq, void *dummy, struct pt_regs *fp)

{

//注意,此处所有的按键都要报告,无论是0号按键还是1号按键

Input_report_key(&button_dev, BTN_0, inb(BUTTON_PORT0));

Input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT1));

Input_sync(&button_dev);      //报告完毕,同步事件

//此时,输入核心层和事件处理层就会将收集的事件类型形成相应的数据,放到file operation 中和 buffer中,以用用户空间读取

}

//驱动初始化函数

Static int __init  button_init(void){

//申请中断,因为按键事件报告是在中断中执行

If( request_irq(BUTTON_IRQ,button_interrupt, 0, “button”, NULL) )

Return –EBUSY;

Set_bit(EV_KEY, button_dev.evbit);  //告诉输入子系统支持EV_key事件
             Set_bit(BTN_0, button_dev.keybit);  //告诉输入子系统支持0号键
             Set_bit(BTN_1, button_dev.keybit);  //告诉输入子系统支持1号键

Input_register_device(&button_dev);      //注册input设备

}

应用程序实现

当相应的时间响应,用户空间读取事件是,所读取到的是 input_event 结构的信息,不再是一个单纯的数字,

在input_event 结构中,已经包含 按键类型type, 按键键值code等信息。

用户需要对input_event 进行相应的解析,获得相应的信息。

Struct   input_event  ev_key;  //声明结构体

Button_fd = open(“/dev/event0”,O_RDWR);

While(1){

Count = read(button_fd, &ev_key, sizeof( struct input_event ));

for( i=0; i<(int)count/sizeof( struct input_event ); i++ ){

if(EV_KEY  ==  ev_key.type)            //确定类型是否相同

printf(“type:%d, code:%d, value:%d \n”,ev_key.type,ev_key.code,ev_key.value);

If( EV_SYN == ev_key.type )

Printf(“syn event \n”);

}

}

Close(button_fd);

我们都在路上,有时苦有时甜,为此我送给自己以及相同爱好者们两个字:坚持 。
       一起加油!!!
       2015年1月16日

时间: 2024-10-01 07:51:24

Linux 输入子系统原理理解(原创)的相关文章

Linux输入子系统(转)

Linux输入子系统(Input Subsystem) 1.1.input子系统概述 输入设备(如按键,键盘,触摸屏,鼠标等)是典型的字符设备,其一般的工作机制是低层在按键,触摸等动作发生时产生一个中断(或驱动通过timer定时查询),然后cpu通过SPI,I2C或者外部存储器总线读取键值,坐标等数据,放一个缓冲区,字符设备驱动管理该缓冲区,而驱动的read()接口让用户可以读取键值,坐标等数据. 在Linux中,输入子系统是由输入子系统设备驱动层.输入子系统核心层(Input Core)和输入

Linux输入子系统框架分析(1)

在Linux下的输入设备键盘.触摸屏.鼠标等都可以用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层,事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备驱动层将输入事件上报给核心层input.c,核心层找到匹配的事件层,将事件交给事件层处理,事件层处理完后传递到用户空间. 我们最终要搞清楚的是在用户空间调用open和read最终在内核中是怎样处理的,向内核上报的事件又是谁处理的,处理完后是怎样传递到用户空间的? 上面两个图是输入子系统的框架. 下面

Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值

Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值 题外话:一个问题研究到最后,那边记录文档的前半部分基本上都是没用的,甚至是错误的. 重点在最后,前边不过一些假想猜測. http://blog.csdn.net/kangear/article/details/40072707 在调试一下红外遥控器input驱动时,直接採用的是一个半成品的驱动在上边实现的自己的设备的匹配,但同一时候遇到了一些关于input输入子系统的疑惑. 按键一般有「按下和抬起」两个状态一般使用0和1

Linux输入子系统(Input Subsystem)

Linux输入子系统(Input Subsystem) http://blog.csdn.net/lbmygf/article/details/7360084 input子系统分析  http://blog.chinaunix.net/uid-27717694-id-3758334.html

Android底层开发之Linux输入子系统要不要判断系统休眠状态上报键值

Android底层开发之Linux输入子系统要不要判断系统休眠状态上报键值 题外话:一个问题研究到最后,那边记录文档的前半部分基本上都是无用的,甚至是错误的.重点在最后,前边仅仅是一些假想推测. http://blog.csdn.net/kangear/article/details/40072707 在调试一下红外遥控器input驱动时,直接采用的是一个半成品的驱动在上边实现的自己的设备的匹配,但同时遇到了一些关于input输入子系统的疑惑. 按键一般有「按下和抬起」两个状态一般使用0和1来分

linux输入子系统(input subsystem)之evdev.c事件处理过程

1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input_subsys.drv.c 1 #include <linux/module.h> 2 #include <linux/version.h> 3 4 #include <linux/init.h> 5 #include <linux/fs.h> 6 #inclu

Linux 输入子系统

Technorati 标签: Kernel 输入子系统 Input      在Linux中,输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理,是底层在按键.触摸时,触发一个中断,或者驱动通过定时器定时查询,通过这两种方式通知CPU,CPU然后通过SPI.I2C或I/O接口读取键值.坐标等数据,放入缓冲区,字符设备驱动管理该缓冲区,向上提供read接口供应用程序使用.      在上述的工作流程中,只有终端.读取数值是根具体硬件设备相关,而输入事件的缓冲区管理以及字符设

linux输入子系统(5) - 学习框架

注:本系列转自: http://www.ourunix.org/post/290.html input子系统学习系列文章,是我在实际开发过程中遇到也是必须啃下去的第一个Linux驱动,所以有必要记载下来的.由于刚开始未接触过Input子系统,部分资料还是借鉴网络,本系列文章是本人的学习心得以及集百家所长的产物. input子系统学习系列文章,主要包含下述内容:         Input subsystem理论部分         input subsystem介绍         input子

Linux输入子系统

在Linux中,按键.触摸屏.鼠标等等输入设备都可以依靠输入子系统提供的接口函数来实现他们的设备驱动,在输入子系统中,系统已经完成了这些输入设备的共性,所以根据子系统提供的接口,只需要完成各自的独特性即可完成一个输入设备的设备驱动. Linux中,输入子系统由设备驱动层.核心层.事件处理层这三层组成.设备驱动层讲底层输入设备的响应转化为标准的输入事件,事件处理层就为应用程序提供统一的设备访问接口来跟底层交互数据,核心层则是连接驱动层和事件处理层的桥梁. 在输入子系统中重要的结构体就是input_