zoukankan      html  css  js  c++  java
  • 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 ”,ev_key.type,ev_key.code,ev_key.value);

                If( EV_SYN == ev_key.type )  

                           Printf(“syn event ”);

    }

    }

    Close(button_fd);

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

  • 相关阅读:
    【iOS
    【iOS】Swift ESTabBarController的使用
    【iOS
    【iOS】图表实现-Charts(二)
    【iOS】图表实现-Charts(一)
    【iOS】图表实现-AAChartKit
    【iOS】图表实现-总述
    【iOS
    【iOS
    整理下开发中常用的第三方库
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4274456.html
Copyright © 2011-2022 走看看