首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Linux设备模型之input子系统详解

Linux设备模型之input子系统详解

本节从整体上讲解了输入子系统的框架结构。有助于读者从整体上认识linux的输入子系统。在陷入代码分析的过程中,通过本节的知识能够找准方向,明白原理。
本节重点:
       
  •          输入子系统的框架结构   
  •          各层对应内核中的文件位置   
  •          输入子系统的事件处理机制   
  •          输入子系统的驱动层基本操作流程   
  •          输入子系统的驱动层常用函数
本节难点:
输入子系统的事件处理机制
输入子系统的驱动工作流程
1 初识linux输入子系统
linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler)、输入子系统核心层(InputCore)和输入子系统设备驱动层。
对于输入子系统设备驱动层而言,主要实现对硬件设备的读写访问,中断设置,并把硬件产生的事件转换为核心层定义的规范提交给事件处理层。
对于核心层而言,为设备驱动层提供了规范和接口。设备驱动层只要关心如何驱动硬件并获得硬件数据(例如按下的按键数据),然后调用核心层提供的接口,核心层会自动把数据提交给事件处理层。
对于事件处理层而言,则是用户编程的接口(设备节点),并处理驱动层提交的数据处理。
对于linux输入子系统的框架结构如下图1所示:

图1 linux输入子系统框架结构

由上图所展现的内容就是linux输入子系统的分层结构。

/dev/input目录下显示的是已经注册在内核中的设备编程接口,用户通过open这些设备文件来打开不同的输入设备进行硬件操作。
事件处理层为不同硬件类型提供了用户访问及处理接口。例如当我们打开设备/dev/input/mice时,会调用到事件处理层的Mouse Handler来处理输入事件,这也使得设备驱动层无需关心设备文件的操作,因为Mouse Handler已经有了对应事件处理的方法。
输入子系统由内核代码drivers/input/input.c构成,它的存在屏蔽了用户到设备驱动的交互细节,为设备驱动层和事件处理层提供了相互通信的统一界面。
下图2简单描述了linux输入子系统的事件处理机制:

图2 linux输入子系统事件处理机制

由上图可知输入子系统核心层提供的支持以及如何上报事件到input event drivers。
作为输入设备的驱动开发者,需要做以下几步:
1、在驱动加载模块中,设置你的input设备支持的事件类型,类型参见表1设置
2、 注册中断处理函数,例如键盘设备需要编写按键的抬起、放下,触摸屏设备需要编写按下、抬起、绝对移动,鼠标设备需要编写单击、抬起、相对移动,并且需要在必要的时候提交硬件数据(键值/坐标/状态等等)
3、 将输入设备注册到输入子系统中
表1 Linux输入子系统支持的数据类型
EV_SYN     0x00    同步事件EV_KEY     0x01    按键事件EV_REL     0x02    相对坐标(如:鼠标移动,报告相对最后一次位置的偏移)EV_ABS     0x03    绝对坐标(如:触摸屏或操作杆,报告绝对的坐标位置)EV_MSC     0x04    其它EV_SW      0x05    开关EV_LED     0x11    按键/设备灯EV_SND     0x12    声音/警报EV_REP     0x14    重复EV_FF      0x15    力反馈EV_PWR    0x16    电源EV_FF_STATUS    0x17   力反馈状态EV_MAX    0x1f    事件类型最大个数和提供位掩码支持
由表1可知,设备所能表示的事件种类,一个设备可以选择一个或多个事件类型上报给输入子系统。
Linux输入子系统提供了设备驱动层上报输入事件的函数,在include/linux/input.h中:
voidinput_report_key(struct input_dev *dev, unsigned int code, int value);      //上报按键事件voidinput_report_rel(struct input_dev *dev, unsigned int code, int value);       //上报相对坐标事件voidinput_report_abs(struct input_dev *dev, unsigned int code, int value);              //上报绝对坐标事件
当提交输入设备产生的输入事件之后,需要调用下面的函数来通知输入子系统,以处理设备产生的完整事件:
void input_sync(struct input_dev *dev);
继承事业,薪火相传
返回列表