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
时间: 2024-10-23 12:28:30

Linux inpu子系统简介的相关文章

linux虚拟内存子系统简介

MMU(内存管理单元) 负责将虚拟地址转换为物理地址,数据存放在主存上,cpu访存时至少需要两次,第一次获取物理地址:第二次才获取数据. TLB:为了改善虚拟地址到物理地址的转换速度,提高cpu访存速度. 原理:TLB利用的是页表的访问局部性,即当一个转换的虚拟页号被使用时,它可能在不久 的将来再次被使用到.TLB是一种高速缓存,当cpu访问第一次某个线性地址时,通 过计算获得对应的物理地址,同时,该线性地址和物理地址的对应关系保存在一个 TLB表项中,以后对同一线性地址的访问,直接从TLB表项

【转】 linux iio子系统

原文网址:http://blog.csdn.net/tsy20100200/article/details/47101661 最近由于工作的需要,接触了Linux iio子系统,对于这个目录其实以前是很少接触,接下了对 Linux iio 子系统进行分析. 1.首先 iio子系统在内核树中位置:drivers/staging/iio 详细的iio子系统说明文档位置:drivers/staging/iio/Documentation(文档是个好东西,详细阅读文档,有利于更深层次的理解iio子系统)

Linux Framebuffer编程简介

linux下,framebuffer设备文件名通常是/ dev/fb0,1,2等.控制framebuffer设备的一般步骤如下:1) 打开设备,映射framebuffer2)依照硬件要求,准备好数据3)把数据复制到framebuffer例子程序如下:1)打开设备,映射framebufferstatic void *fbbuf;int openfb(char *devname){    int fd;    fd = open(devname, O_RDWR);    if (ioctl(fd,

linux中断子系统:中断号的映射与维护

写在前沿: 好久好久没有静下心来整理一些东西了,开始工作已有一个月,脑子里想整理的东西特别多.记录是一种很好的自我学习方式,静下来多思考多总结,三年的工作目标不能发生变化,作为职场菜鸟即将进入全世界半导体第一的Intel working,是机遇更是一种挑战,困难也是可想而知.脚踏实地.仰望星空,以结果为导向,以目标为准则,争取每天进步一点点. Linux内核版本:3.4.39 一. linux中断子系统的irq_desc初始化 linux内核最初的中断初始化过程入口为start_kernel.在

Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)

在前面章节的讨论中,我们一直基于一个假设:Linux中的时钟事件都是由一个周期时钟提供,不管系统中的clock_event_device是工作于周期触发模式,还是工作于单触发模式,也不管定时器系统是工作于低分辨率模式,还是高精度模式,内核都竭尽所能,用不同的方式提供周期时钟,以产生定期的tick事件,tick事件或者用于全局的时间管理(jiffies和时间的更新),或者用于本地cpu的进程统计.时间轮定时器框架等等.周期性时钟虽然简单有效,但是也带来了一些缺点,尤其在系统的功耗上,因为就算系统目

Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现

上一篇文章,我介绍了传统的低分辨率定时器的实现原理.而随着内核的不断演进,大牛们已经对这种低分辨率定时器的精度不再满足,而且,硬件也在不断地发展,系统中的定时器硬件的精度也越来越高,这也给高分辨率定时器的出现创造了条件.内核从2.6.16开始加入了高精度定时器架构.在实现方式上,内核的高分辨率定时器的实现代码几乎没有借用低分辨率定时器的数据结构和代码,内核文档给出的解释主要有以下几点: 低分辨率定时器的代码和jiffies的关系太过紧密,并且默认按32位进行设计,并且它的代码已经经过长时间的优化

Linux输入子系统框架分析(1)

在Linux下的输入设备键盘.触摸屏.鼠标等都可以用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层,事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备驱动层将输入事件上报给核心层input.c,核心层找到匹配的事件层,将事件交给事件层处理,事件层处理完后传递到用户空间. 我们最终要搞清楚的是在用户空间调用open和read最终在内核中是怎样处理的,向内核上报的事件又是谁处理的,处理完后是怎样传递到用户空间的? 上面两个图是输入子系统的框架. 下面

Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值

Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值 题外话:一个问题研究到最后,那边记录文档的前半部分基本上都是没用的,甚至是错误的. 重点在最后,前边不过一些假想猜測. http://blog.csdn.net/kangear/article/details/40072707 在调试一下红外遥控器input驱动时,直接採用的是一个半成品的驱动在上边实现的自己的设备的匹配,但同一时候遇到了一些关于input输入子系统的疑惑. 按键一般有「按下和抬起」两个状态一般使用0和1

Linux输入子系统(Input Subsystem)

Linux输入子系统(Input Subsystem) http://blog.csdn.net/lbmygf/article/details/7360084 input子系统分析  http://blog.chinaunix.net/uid-27717694-id-3758334.html