zoukankan      html  css  js  c++  java
  • 迅为i.MX6ULL终结者Linux INPUT子系统实验Input子系统

    文章目录
    1 input子系统简介
    2 input驱动程序编写流程
    3 input_event结构体
    1 input子系统简介
    input 子系统就是管理输入的子系统,和 pinctrl 和 gpio 子系统一样,都是 Linux 内核针对某一类设备而创建的框架。 input子系统处理输入事务,任何输入设备的驱动程序都可以通过input输入子系统提供的接口注册到内核,利用子系统提供的功能来与用户空间交互。输入设备一般包括键盘,鼠标,触摸屏等,在内核中都是以输入设备出现的。
    input子系统是分层结构的,总共分为三层: 硬件驱动层,子系统核心层,事件处理层。
    (1)硬件驱动层负责操作具体的硬件设备,这层的代码是针对具体的驱动程序的,需要驱动程序的作者来编写。
    (2)子系统核心层是链接其他两个层之间的纽带与桥梁,向下提供驱动层的接口,向上提供事件处理层的接口。
    (3)事件处理层负责与用户程序打交道,将硬件驱动层传来的事件报告给用户程序。

    各层之间通信的基本单位就是事件,任何一个输入设备的动作都可以抽象成一种事件,如键盘的按下,触摸屏的按下,鼠标的移动等。事件有三种属性:类型(type),编码(code),值(value),input子系统支持的所有事件都定义在input.h中,包括所有支持的类型,所属类型支持的编码等。事件传送的方向是 硬件驱动层–>子系统核心–>事件处理层–>用户空间。
    2 input驱动程序编写流程
    首先来看一下在input核心层实现了哪些功能,input核心层文件是input.c,路径:drivers/input/input.c,部分内容如下:

    第2418行,注册了一个input类,在系统启动后会在/sys/class目录下生成一个input类的子目录,如图 2.1所示:

    第2428、2489行,注册了一个字符设备,所以input子系统本质上也是字符设备驱动,主设备号为 INPUT_MAJOR,INPUT_MAJOR 定义在 include/uapi/linux/major.h 文件中,定义如下:
    #define INPUT_MAJOR 13
    所以input 子系统的所有设备主设备号都为 13,在使用 input 子系统处理输入设备的时候就不需要去注册字符设备了,我们只需要向系统注册一个 input_device 即可。
    1、input_dev 结构体
    input_dev结构体是input设备基本的设备结构,每个input驱动程序中都必须分配初始化这样一个结构,结构体定义在 include/linux/input.h 文件中,定义如下:

    第 129 行,evbit 表示输入事件类型,可选的事件类型定义在 include/uapi/linux/input.h 文件中,事件类型如下:

    根据使用的不同设备选择不同的事件类型,在本章的实验中我们会用到按键设备,那么我们就需要选择EV_KEY 事件类型。
    在看input_dev结构体中的第129~137行的evbit、keybit等成员变量,都是对应的不同事件类型的值。比如按键事件对应的keybit成员,keybit 就是按键事件使用的位图,Linux 内核定义了很多按键值,这些按键值定义在 include/uapi/linux/input.h 文件中,按键值如下:

    当我们编写input设备驱动时需要先创建一个input_dev 结构体变量,但是不用我们手动创建,input子系统提供了下面两个函数用于创建和注销input_dev 结构体变量。

    申请完input_dev结构体后,需要进行初始化,根据自己的设备来指定事件类型和事件值,比如按键设备的事件类型是evbit,事件值是keybit。
    input_dev结构体初始化完成后,使用input_register_device 函数向Linux内核注册input_dev设备。函数原型如下:
    int input_register_device(struct input_dev *dev)
    dev:要注册的 input_dev 。
    返回值:0,input_dev 注册成功;负值,input_dev 注册失败。
    同样的,注销 input 驱动的时候也需要使用 input_unregister_device 函数来注销掉前面注册的 input_dev,input_unregister_device 函数原型如下:
    void input_unregister_device(struct input_dev *dev)
    总结上面的内容,input_dev注册过程分为下面几步:
    ① 首先使用 input_allocate_device 函数申请一个 input_dev。
    ② 初始化 input_dev 的事件类型以及事件值。
    ③ input_register_device()函数是输入子系统核心(input core)提供的函数。该函数将input_dev结构体注册到输入子系统核心中
    ④ input_register_device()函数如果注册失败,必须调用input_free_device()函数释放分配的空间。如果该函数注册成功,在卸载函数中应该调用input_unregister_device()函数来注销输入设备结构体。
    input_dev注册过程实例代码如下:


    第 10~23 行都是初始化 input 设备事件和按键值,这里用了三种方法来设置事件和按键值。
    2、上报输入事件
    在input设备驱动中申请、注册完成input_dev结构体后,还不能正常使用input子系统,因为input设备是输入一些信息,但是Linux内核还不清楚输入的信息表示什么意思,有什么作用,所以我们需要驱动获取到具体的输入值,或者说输入事件,然后将输入事件上报给Linux内核。比如按键设备,我们需要在按键产生后将按键值上报给Linux内核,Linux内核获取到具体的按键值后,才会执行相应的功能。不同的事件上报的函数不同,我们分别来看一下有哪些常用的API函数。
    input_event函数:用于上报指定的事件以及对应的值。函数原型如下:

    函数参数和返回值含义如下:
    dev:需要上报的 input_dev。
    type: 上报的事件类型,比如 EV_KEY。
    code:事件码,也就是我们注册的按键值,比如 KEY_0、KEY_1 等等。
    value:事件值,比如 1 表示按键按下,0 表示按键松开。
    返回值:无。
    input_event函数可以用于所有事件类型和事件值的上报。
    input_report_key 函数:上报按键事件。具体函数内容如下:

    可以看出,input_report_key 函数的本质就是 input_event 函数,当然使用哪个函数都没有问题,不同的设备使用对应的函数更加合适一点。
    同样的还有一些其他事件对应的上报函数:

    input_sync 函数:用来告诉Linux内核input子系统上报结束。input_sync 函数本质上是上报一个同步事件,函数原型如下:
    void input_sync(struct input_dev *dev)
    列举了好几个函数,以按键设备为例,看一下如何使用:

    获取按键的值,然后判断按键是否按下,通过input_report_key函数上报按键的值,input_sync函数表示上报结束。
    3 input_event结构体
    Linux 内核使用 input_event 这个结构体来表示所有的输入事件,input_envent 结构体定义在include/uapi/linux/input.h 文件中,结构体内容如下:

    依次来看一下 input_event 结构体中的各个成员变量:
    time:时间,也就是此事件发生的时间,为 timeval 结构体类型,timeval 结构体定义如下:

    tv_sec 和 tv_usec 这两个成员变量都为 long 类型,也就是 32位,这个一定要记住,后面我们分析 event 事件上报数据的时候要用到。
    type:事件类型,比如 EV_KEY,表示此次事件为按键事件,此成员变量为 16 位。
    code:事件码,比如在 EV_KEY 事件中 code 就表示具体的按键码,如:KEY_0、KEY_1等等这些按键。此成员变量为 16 位。
    value:值,比如 EV_KEY 事件中 value 就是按键值,表示按键有没有被按下,如果为 1 的话说明按键按下,如果为 0 的话说明按键没有被按下或者按键松开了。
    input_envent 这个结构体非常重要,因为所有的输入设备最终都是按照 input_event 结构体呈现给用户的,用户应用程序可以通过 input_event 来获取到具体的输入事件或相关的值,比如按键值等。

    终结者资料全开源,不买也可以自由下载软硬件资源
    您只需要关注VX公众号:迅为电子 ,  回复 :终结者,免费获取产品资料
  • 相关阅读:
    算法竞赛入门经典习题2-3 韩信点兵
    ios入门之c语言篇——基本函数——5——素数判断
    ios入门之c语言篇——基本函数——4——数值交换函数
    144. Binary Tree Preorder Traversal
    143. Reorder List
    142. Linked List Cycle II
    139. Word Break
    138. Copy List with Random Pointer
    137. Single Number II
    135. Candy
  • 原文地址:https://www.cnblogs.com/liyue3/p/14261007.html
Copyright © 2011-2022 走看看