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日 

转载于:https://www.cnblogs.com/lihaiyan/p/4274456.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432020.shtml

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

相关文章

Logistic Regression:最基础的神经网络

一、什么是logictic regression 下面的图是Andrew Ng提供的一个用logistic regression来识别主子的图片的算法结构示意图&#xff1a; 「左边」的「x0到x12287「是输入&#xff08;input&#xff09;&#xff0c;我们称之为」特征&#xff08;feather&#xff09;」&#xff0…

Win7和Ubuntu14.10双系统

一、Wubi 本来是拿wubi安装的。步骤简单&#xff0c;装卸方便。就是失败了。。。 下载好镜像后解压一份&#xff0c;将wubi.exe复制出一份放在和镜像同目录下&#xff08;目录要全英&#xff09;。断网&#xff0c;运行wubi.exe按照提示安装。这里这篇教程挺好&#xff0c;之后…

LateX 笔记

y \frac{a}{b} y A_aA_{bb} y a\times{b} y \arctan{(x)} \pi y x^2

OpenDrive ARC绘制秘籍

加和减代表曲率的正负

mysql中char与varchar的区别分析

原文网址&#xff1a;http://www.jb51.net/article/23575.htm mysql中char与varchar的区别分析 作者&#xff1a; 字体&#xff1a;[增加 减小] 类型&#xff1a;转载在mysql教程中char与varchar的区别呢&#xff0c;都是用来存储字符串的&#xff0c;只是他们的保存方式不一样…

3W+字的设计模式手册

设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结&#xff0c;其中最出名的当属 Gang of Four (GoF) 的分类了&#xff0c;他们将设计模式分类为 23 种经典的模式&#xff0c;根据用途我们又可以分为三大类&#xff0c;分别为创建型模式、结构型模式和行为型模式。…

datagridview 当前上下文中不存在bind_全面解析JavaScript中this指向问题

this指向参考文章&#xff1a;* thisJavaScript中this指向分为以下几种情况&#xff1a;普通函数或作为对象属性事件绑定构造函数箭头函数call/apply/bind指定下面我们来进行一一介绍普通函数或作为对象属性this取决于方法执行前面是否有“点”&#xff0c;有“点”的话&#x…

Unity Scene为每一个游戏物体进行扩展编辑

2个月前还在忙碌的找实习工作,看见招聘信息上面有一条熟悉扩展Unity编辑器,配合美工编程. 自己动手写完这个代码时候,发现写代码就像弹钢琴多么神奇. TestEdit类: using UnityEngine; using System.Collections; using UnityEditor;[CustomEditor(typeof(Test))] public class …

esmini LongSpeedAction修改

esmini的LongSpeedAction&#xff0c;如果shape设置为step的话&#xff0c;DynamicsDimension实际就无效了&#xff0c; 因为step的意思就是直接设置&#xff0c;在LongSpeedAction的Start过程中设置完就结束了&#xff0c;Step就不在 执行。 如果我们在step的情况下&#x…

cc2530i2c可同时接受两个传感器的数据吗_汽车方向及维修_玉树沃尔沃S40方向机,宝马531电子方向机进水可以维修吗...

产品品牌&#xff1a;徐州永诚汽车方向及维修公司产品单价&#xff1a;最小起订&#xff1a;23供货总量&#xff1a;2交货期限&#xff1a;13发货城市&#xff1a;徐州玉树沃尔沃S40方向机,宝马531电子方向机进水可以维修吗 [qadxfh3k]凭以往的经验&#xff0c;像这种多个控制模…

Android项目实战视频教程_快递轨迹查询应用开发

基于Android平台的快递轨迹查询应用开发全程实录&#xff08;MenuDrawer、DbUtils、HttpUtils、讯飞语音识别&#xff09;课程分类&#xff1a;Android适合人群&#xff1a;中级课时数量&#xff1a;10(17节)课时用到技术&#xff1a;MenuDrawer、DbUtils、HttpUtils、讯飞语音…

OpenXLSX 字段读取问题

在读取excel的时候发现有些字段无法读取&#xff0c;通过把excel文件解压后对比发现&#xff0c;正常读取和不 能正常读取的字段在sharedString.xml中存储的格式有差异&#xff0c;取其中一个字段&#xff0c;如下图&#xff1a; 正常读取的 不能读取的 对比可以看到其区别&a…

六西格玛dfss_六西格玛系列知识之二:六西格玛管理的基本原理

六西格玛管理是一系统&#xff0c;其系统性体现在它既提出了面向产品和服务设计开发的六西格玛设计&#xff0c;又提出了面向流程、产品制造、服务提供的六西格玛改进方法。从当前的情况来看&#xff0c;六西格玛设计&#xff08;DFSS&#xff09;项目推进尚未形成统一的或得到…

XCode5.1.1怎样实现代码块自己主动排版

1.问题描写叙述 在开发中常常遇到代码块须要排版的情况&#xff0c;假设一行一行缩进就太out了&#xff0c;但在xcode中怎样实现还真不知道2.解决方法 2.1选中须要排版的代码块 2.2单击"Editor | Structure | Re-Indent"菜单项 2.3看看是不是已经得到想要的结果了&am…

数据库监控[Z]

--查看表锁 select * from sys.v_$sqlarea where disk_reads>100--监控事例的等待 select event,sum(decode(wait_Time,0,0,1)) "Prev", sum(decode(wait_Time,0,1,0)) "Curr",count(*) "Tot"from v$session_Wait group by event order by 4 …

Could NOT find XXX (missing: XXX_LIBRARY XXX_DIR)

有时候从github上下载一些新的包编译时经常会缺少一些插件或库文件&#xff0c;比如 Could NOT find Bullet (missing: BULLET_DYNAMICS_LIBRARY BULLET_COLLISION_LIBRARY BULLET_MATH_LIBRARY BULLET_SOFTBODY_LIBRARY BULLET_INCLUDE_DIR) 或者 Could NOT find SDL (miss…

minheight能继承吗_民法典亮点盘点 | 侄子能继承叔叔的遗产吗?

2020年5月28日&#xff0c;十三届全国人大三次会议表决通过了《中华人民共和国民法典》&#xff0c;《民法典》将于2021年1月1日起施行。《民法典》共7编&#xff0c;依次为&#xff1a;总则编、物权编、合同编、人格权编、婚姻家庭编、继承编、侵权责任编&#xff0c;以及附则…

多C++标准版本指定

本文主要介绍 CMake 中 include 指令的相关知识。 1 概述 引用 CMake 官网对于 include 指令的介绍&#xff0c;如下&#xff1a; Load and run CMake code from a file or module. include 指令的用法如下&#xff1a; include(<file|module> [OPTIONAL] [RESULT_VA…

STL容器存储的内容动态分配情况下的内存管理

主要分两种情况&#xff1a;存储的内容是指针&#xff1b;存储的内容是实际对象。 看以下两段代码&#xff0c; typedef pair<VirObjTYPE, std::list<CheckID>*> VirObj_CheckID_pair;class LangChecker{public: LangChecker(); ~LangChecker(); voi…

一分二功率分配器_一文学会微波功率分配器

功率分配器是微波电路设计中常用的一个无源元器件&#xff0c;简称功分器&#xff0c;顾名思义&#xff0c;就是把一路输出功率按照一定的比例分配成N路功率输出的一种微波元器件&#xff0c;如下图所示&#xff0c;A端口进入的信号分成两路信号从C1和C2端口输出。当然&#xf…