找回密码
 注册
关于网站域名变更的通知
查看: 336|回复: 1
打印 上一主题 下一主题

迅为i.MX6ULL终结者Linux INPUT子系统实验Input子系统

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-1-11 10:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
文章目录
* u  D+ K$ R* U" A8 e1 input子系统简介
+ }1 Q, i, X  I2 input驱动程序编写流程
$ ~- x! A0 s% X0 i, z3 input_event结构体& l( d! U8 l% x  R7 ]
1 input子系统简介1 q9 ?' \6 w; w
input 子系统就是管理输入的子系统,和 pinctrl 和 gpio 子系统一样,都是 Linux 内核针对某一类设备而创建的框架。 input子系统处理输入事务,任何输入设备的驱动程序都可以通过input输入子系统提供的接口注册到内核,利用子系统提供的功能来与用户空间交互。输入设备一般包括键盘,鼠标,触摸屏等,在内核中都是以输入设备出现的。
5 H* G& K0 B/ x; R( J" x$ v: ginput子系统是分层结构的,总共分为三层: 硬件驱动层,子系统核心层,事件处理层。/ x( q" j7 J/ O' B8 V- {6 h0 \5 L8 c
(1)硬件驱动层负责操作具体的硬件设备,这层的代码是针对具体的驱动程序的,需要驱动程序的作者来编写。) W$ H2 J* Q2 s& R2 V
(2)子系统核心层是链接其他两个层之间的纽带与桥梁,向下提供驱动层的接口,向上提供事件处理层的接口。
+ v8 Y* T$ z5 ~( A# c( V(3)事件处理层负责与用户程序打交道,将硬件驱动层传来的事件报告给用户程序。
( V, y3 t$ V9 B! R+ ]% P  d4 \1 F+ L; j  ]; j
各层之间通信的基本单位就是事件,任何一个输入设备的动作都可以抽象成一种事件,如键盘的按下,触摸屏的按下,鼠标的移动等。事件有三种属性:类型(type),编码(code),值(value),input子系统支持的所有事件都定义在input.h中,包括所有支持的类型,所属类型支持的编码等。事件传送的方向是 硬件驱动层–>子系统核心–>事件处理层–>用户空间。
# R1 Z- A+ ?/ _+ b7 t2 input驱动程序编写流程
6 u" W) Y2 R3 n2 [首先来看一下在input核心层实现了哪些功能,input核心层文件是input.c,路径:drivers/input/input.c,部分内容如下:
( I" j4 N- k) q, b% }; ?9 u# c
1 A7 a5 M" n' e8 f2 a. z" D第2418行,注册了一个input类,在系统启动后会在/sys/class目录下生成一个input类的子目录,如图 2.1所示:1 J$ l) e; S% S0 T" i: e
6 d; L& e1 A2 P5 X" y$ L
第2428、2489行,注册了一个字符设备,所以input子系统本质上也是字符设备驱动,主设备号为 INPUT_MAJOR,INPUT_MAJOR 定义在 include/uapi/linux/major.h 文件中,定义如下:
, R. k9 D' i/ \7 V#define INPUT_MAJOR 13
. K4 u2 c$ @( J" x5 E, D所以input 子系统的所有设备主设备号都为 13,在使用 input 子系统处理输入设备的时候就不需要去注册字符设备了,我们只需要向系统注册一个 input_device 即可。
" [: p; W7 a: q# w6 c- ?1、input_dev 结构体4 C0 }5 V( o3 ]# h
input_dev结构体是input设备基本的设备结构,每个input驱动程序中都必须分配初始化这样一个结构,结构体定义在 include/linux/input.h 文件中,定义如下:
7 C' B  L8 d7 I3 M9 M  }, K( E& ^& Z
* M8 a" z: u$ ~; T! R第 129 行,evbit 表示输入事件类型,可选的事件类型定义在 include/uapi/linux/input.h 文件中,事件类型如下:" n! n0 b4 Y3 e7 S  R

8 `$ w  o4 t8 D6 }+ S根据使用的不同设备选择不同的事件类型,在本章的实验中我们会用到按键设备,那么我们就需要选择EV_KEY 事件类型。
+ V0 W: b4 O/ W5 e. H; E7 `在看input_dev结构体中的第129~137行的evbit、keybit等成员变量,都是对应的不同事件类型的值。比如按键事件对应的keybit成员,keybit 就是按键事件使用的位图,Linux 内核定义了很多按键值,这些按键值定义在 include/uapi/linux/input.h 文件中,按键值如下:* ^% B- b5 k, y0 o+ g% R  W. m- ^
. ^. `/ ~1 m% `6 [9 n/ \, ~: c
当我们编写input设备驱动时需要先创建一个input_dev 结构体变量,但是不用我们手动创建,input子系统提供了下面两个函数用于创建和注销input_dev 结构体变量。
9 l/ [+ c4 r# \$ w% a4 k1 u
# v% d6 d1 {3 T: C/ f) N申请完input_dev结构体后,需要进行初始化,根据自己的设备来指定事件类型和事件值,比如按键设备的事件类型是evbit,事件值是keybit。
5 {' [7 ~' I: `input_dev结构体初始化完成后,使用input_register_device 函数向Linux内核注册input_dev设备。函数原型如下:
( ~* Y* h: h# X; p; w. Hint input_register_device(struct input_dev *dev)( J! P0 G- e8 O. Q
dev:要注册的 input_dev 。- Z; x1 S8 M4 C4 w3 T% Y
返回值:0,input_dev 注册成功;负值,input_dev 注册失败。" N) q; A8 B/ T4 j; K) |
同样的,注销 input 驱动的时候也需要使用 input_unregister_device 函数来注销掉前面注册的 input_dev,input_unregister_device 函数原型如下:' K( X  l! o& G  L' h& C4 i' ?
void input_unregister_device(struct input_dev *dev); K$ O5 k9 @: C; I# k3 ?$ N
总结上面的内容,input_dev注册过程分为下面几步:' m# \9 W/ c2 U  S
① 首先使用 input_allocate_device 函数申请一个 input_dev。
+ C3 {/ e; d0 c3 W② 初始化 input_dev 的事件类型以及事件值。
3 p4 X/ F" p. Q& V③ input_register_device()函数是输入子系统核心(input core)提供的函数。该函数将input_dev结构体注册到输入子系统核心中
& l' q( K0 g' N9 H④ input_register_device()函数如果注册失败,必须调用input_free_device()函数释放分配的空间。如果该函数注册成功,在卸载函数中应该调用input_unregister_device()函数来注销输入设备结构体。
4 t0 s# f( h! |; Qinput_dev注册过程实例代码如下:
  d% b+ f  `8 A' [9 u% n: R$ h6 m3 j' {  G/ R
( a3 G7 T1 q) w3 ~7 M; T; @
第 10~23 行都是初始化 input 设备事件和按键值,这里用了三种方法来设置事件和按键值。
: |3 n' N. x! ]2、上报输入事件, I5 o+ z5 t' D9 V) _
在input设备驱动中申请、注册完成input_dev结构体后,还不能正常使用input子系统,因为input设备是输入一些信息,但是Linux内核还不清楚输入的信息表示什么意思,有什么作用,所以我们需要驱动获取到具体的输入值,或者说输入事件,然后将输入事件上报给Linux内核。比如按键设备,我们需要在按键产生后将按键值上报给Linux内核,Linux内核获取到具体的按键值后,才会执行相应的功能。不同的事件上报的函数不同,我们分别来看一下有哪些常用的API函数。6 ?* \3 A( R) i( t0 z' B
input_event函数:用于上报指定的事件以及对应的值。函数原型如下:$ k8 [- W( m) B9 H, `6 p$ R1 n! l

- k: S4 Z- r$ b. D; S函数参数和返回值含义如下:
+ v1 P8 t4 G$ k: E" v5 e, z# Ydev:需要上报的 input_dev。5 F& k" @: S2 T$ O- X$ g! L
type: 上报的事件类型,比如 EV_KEY。$ z: t9 W$ r: v+ e7 D# M* r' k
code:事件码,也就是我们注册的按键值,比如 KEY_0、KEY_1 等等。
4 q7 u8 a; ~% T1 G$ D! Q% Q* kvalue:事件值,比如 1 表示按键按下,0 表示按键松开。$ F  D2 k) }: x6 @5 E+ G9 Z( l8 }
返回值:无。
8 E( }$ D9 `3 e& @, _input_event函数可以用于所有事件类型和事件值的上报。
% w. q* w) A+ Uinput_report_key 函数:上报按键事件。具体函数内容如下:* d% i6 M( m3 s5 V

. x2 j( |( ~* p( o% |可以看出,input_report_key 函数的本质就是 input_event 函数,当然使用哪个函数都没有问题,不同的设备使用对应的函数更加合适一点。  K6 u0 {6 s: u
同样的还有一些其他事件对应的上报函数:
0 r" t$ K' V7 F( x% O% H' V, Z$ d' I3 V# U, Q
input_sync 函数:用来告诉Linux内核input子系统上报结束。input_sync 函数本质上是上报一个同步事件,函数原型如下:
2 c$ A% V& }- q, s, `* ?, q* vvoid input_sync(struct input_dev *dev)
4 k1 ]6 x, p0 A& f% q! g4 Y列举了好几个函数,以按键设备为例,看一下如何使用:& |$ F0 o' b" A  H  U( r& }
1 W. Z( B% q) m( y$ Z7 b- R5 u
获取按键的值,然后判断按键是否按下,通过input_report_key函数上报按键的值,input_sync函数表示上报结束。5 o% L% Y4 W7 O4 r( n6 C
3 input_event结构体  d" {/ z- k  Y- V9 k
Linux 内核使用 input_event 这个结构体来表示所有的输入事件,input_envent 结构体定义在include/uapi/linux/input.h 文件中,结构体内容如下:5 ]. k! e' J4 ?9 q
1 X; S2 G7 h0 ^+ V9 `: B5 K. }; w. B
依次来看一下 input_event 结构体中的各个成员变量:
' w/ S  _9 c. ^# t1 Ytime:时间,也就是此事件发生的时间,为 timeval 结构体类型,timeval 结构体定义如下:2 P+ i, t  I2 F! ^

3 ?) i4 k( t0 r( C' |! |tv_sec 和 tv_usec 这两个成员变量都为 long 类型,也就是 32位,这个一定要记住,后面我们分析 event 事件上报数据的时候要用到。
& X' L: L: m  H# e) N& Ytype:事件类型,比如 EV_KEY,表示此次事件为按键事件,此成员变量为 16 位。7 Q1 h3 M4 L7 f! o' ?3 y
code:事件码,比如在 EV_KEY 事件中 code 就表示具体的按键码,如:KEY_0、KEY_1等等这些按键。此成员变量为 16 位。. R" E' Y$ ?, _. F4 ], M
value:值,比如 EV_KEY 事件中 value 就是按键值,表示按键有没有被按下,如果为 1 的话说明按键按下,如果为 0 的话说明按键没有被按下或者按键松开了。5 S: d% c& t, n, u) e2 R
input_envent 这个结构体非常重要,因为所有的输入设备最终都是按照 input_event 结构体呈现给用户的,用户应用程序可以通过 input_event 来获取到具体的输入事件或相关的值,比如按键值等。4 q- r/ S, P* Y4 q  e6 x! G
/ O0 T+ @$ D' ~5 q' `( `9 C) R( }  e
$ X# Y/ K& T+ R; r% l8 x. L
终结者资料全开源,不买也可以自由下载软硬件资源
您只需要关注VX公众号:迅为电子 ,  回复 :终结者,免费获取产品资料
  ?: H' I' X/ y3 s5 E  s5 H

: |+ D3 W, q( M  m/ f' O! q- X, Z! N/ j
  • TA的每日心情
    开心
    2022-12-26 15:46
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2021-1-12 19:25 | 只看该作者
    很详细,谢谢
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-24 17:59 , Processed in 0.171875 second(s), 24 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表