首页 > 代码库 > Linux inpu子系统简介

Linux inpu子系统简介

1.前言

本文主要对Linux下的input子系统进行介绍

2. 软件架构

 

技术分享

图 input子系统结构图

input子系统主要包括三个部分:设备驱动层、核心层和事件层。我们可以分别理解为:具体的输入设备、过度设备和逻辑设备。对于用户空间来说与之直接交互的只有逻辑设备也就是事件层。

Input子系统主要包含两条路径(主要讲述第一条路径):

  • 第一条路径

设备驱动层捕获事件并向核心层报告->核心层将事件交由事件层处理->用户空间读取事件层处理的数据

  • 第二条路径

用户空间写入事件数据->事件层生成事件->调用核心层传递事件信息给驱动层->设备驱动层驱动硬件设备

 3.系统组件之间的关联

技术分享

图 input_dev  input_handle  input_handler之间的关联

通常input_dev、 input_handle、input_handler三者的关系如上图所示。

  • input_dev

input_dev通过node链接进全局链表input_dev_list中;通过h_list将与其关联的所有input_handle链接起来,这说明每个input_dev可能会有多个handle与其连接

  • input_handler

input_handler通过node节点链接进全局链表input_handler_list中;通过h_list将与其关联的所有input_handle链接起来,这说明每个input_handler可能会有多个handle与其连接

 4. 系统组件

4.1 input_handle

 

Elemete Name input_handle
Path include/linux/input.h
Responsiblities

用于连接input_dev和input_handler,由input_handler创建

Attributions
  • private:void *类型,存放input handle的特有数据
  • open:open用来计数,指示这个handle是否被打开了
  • name:const char *类型,handler的名字,由handler在创建handle的时候指定
  • dev:struct input_dev *类型,与此handle关联的input_dev
  • handler:struct input_handler *类型,handler通过handle与上面的input_dev一起work
  • d_node:struct list_head类型,可以把此节点链到input_dev的h_list链表上,这说明一个input_dev可以与多个handle链接
  • h_node:struct list_head类型,可以将此节点链接到input_handler的h_list链表上,这说明一个input_handler可以与多个handle链接
Operations

 

 

 

4.2 input_dev

 

Elemete Name input_dev
Path include/linux/input.h
Responsiblities

代表一个input设备,如按键设备、触摸屏设备等

Attributions

name:const char *类型,input设备的名字

phys:const char *类型,/sys/目录下的文件节点名,如/sys/class/input/event0

uniq:const char *类型,设备的唯一标识码,需要设备支持

         struct input_id id;

设备的ID,包括生产商,产品好,版本号

         unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];

 

         unsigned long evbit[BITS_TO_LONGS(EV_CNT)];

设备支持哪些事件

         unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];

这个设备支持哪些按键和button

         unsigned long relbit[BITS_TO_LONGS(REL_CNT)];

设备的相对坐标,针对鼠标设备?

         unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];

针对触摸屏设备?

         unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];

设备支持的杂项事件

         unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];

设备上的LED

         unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];

设备的声音支持相关,如蜂鸣器等

         unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];

设备所支持的强反馈事件,如马达等

         unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

设备是否支持开关,如iphone上的静音开关

         unsigned int hint_events_per_packet;

设备打包事件暗含的数目,一般发生在EV_SYN和SYN_REPORT之间的事件数目,input_handler需要据此预估buffer大小来存放事件

         unsigned int keycodemax;

按键码表的大小,用来存放按键码,实际的按键码个数可能小于此

         unsigned int keycodesize;

实际上存放在按键码表中的按键码数目

         void *keycode;

扫描码到按键码的映射,对ADC按键扫描码可以理解为某个按键的ADC值,按键码有音量加,音量减等

         int (*setkeycode)(struct input_dev *dev,

                              const struct input_keymap_entry *ke,

                              unsigned int *old_keycode);

 

         int (*getkeycode)(struct input_dev *dev,

                              struct input_keymap_entry *ke);

 

         struct ff_device *ff;

 

         unsigned int repeat_key;

repeat_key保存了上次按下的按键,用于软件自动重发

         struct timer_list timer;

软件重发的定时器,包括按键按下多长时间启动自动重发功能,每隔多长时间重发一次

         int rep[REP_CNT];

用于自动重发的参数值保存

         struct input_mt *mt;

 

         struct input_absinfo *absinfo;

 

         unsigned long key[BITS_TO_LONGS(KEY_CNT)];

反应当前key/button设备的状态,如按下还是抬起

         unsigned long led[BITS_TO_LONGS(LED_CNT)];

         unsigned long snd[BITS_TO_LONGS(SND_CNT)];

         unsigned long sw[BITS_TO_LONGS(SW_CNT)];

 

         int (*open)(struct input_dev *dev);

这个方法由第一个用户在调用input_open_device时被调用,驱动中此时需要已经开启 poll线程,并可以上报事件,其它用户调用时将只把user计数加1

         void (*close)(struct input_dev *dev);

最后一个用户调用input_close_device时将调用此函数,驱动需要实现做一个善后工作

         int (*flush)(struct input_dev *dev, struct file *file);

         int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);

主要用于input_handler接收用户层的操作事件,对input_dev进行操作,如对led和ff设备的操作

         struct input_handle __rcu *grab;

一旦grab不为空,则说明此input_handle将成为此input_dev的唯一事件处理者

         spinlock_t event_lock;

用于input core接收或处理此input_dev的事件

         struct mutex mutex;

用于保证open、close、flush方法的串行执行

         unsigned int users;

input_handler执行input_open_device的次数

         bool going_away;

标示input_dev在执行unregister的过程中,此时执行input_open_device将失败

         struct device dev;

设备驱动模型device

         struct list_head         h_list;

用于链接此input_dev的所有input_handle

         struct list_head         node;

用于将此input_dev加入到全局input_dev_list中

         unsigned int num_vals;

当前队列中有多少个frame在排队,每个frame可以理解成EV_SYN和SYN_REPORT之间的事件

         unsigned int max_vals;

一个frame中可以包含的最大事件个数???

         struct input_value *vals;

入队到当前队列的数组????

         bool devres_managed;

指示设备资源是否由设备资源框架进行管理

 

Operations

 

 

 

 

Linux inpu子系统简介