全网络对Linux input子系统最清晰、详尽的分析

Linux input分析之二:解构input_handler、input_core、input_device

输入输出是用户和产品交互的手段,因此输入驱动开发在Linux驱动开发中很常见。同时,input子系统的分层架构思想在Linux驱动设计中极具代表性和先进性,因此对Linux input子系统进行深入分析很有意义。

本文继续在《Linuxinput子系统分析之一:软件分层》的基础上继续深入研究Linux输入子系统的分层架构思想以及其实现。软件分层探讨的是输入消息从底层硬件到内核、应用层的消息传递和使用过程,而本文则是专注剖析Linux内核驱动层对输入设备的抽象分层管理和实现。

一、input子系统知识点回顾

详细请看《Linux input子系统分析之一:软件分层》一文。输入子系统对linux的输入设备驱动进行了高度抽象,最终分成了三层,包括input核心层、input事件处理层和input设备驱动层。input核心层(input-core)对input设备(input-device)和input事件处理(input-handler)进行管理并进行消息转发。如下图:

所有的输入设备的主设备号都是13,input-core通过次设备来将输入设备进行分类,如0-31是游戏杆,32-63是鼠标(对应Mouse Handler)、64-95是事件设备(如触摸屏,对应Event Handler)。

二、input核心层的任务

核心层input-core完成的工作包括:

1) 直接跟字符设备驱动框架交互,字符设备驱动框架根据主设备号来进行管理,而input-core则是依赖于次设备号来进行分类管理。Input子系统的所有输入设备的主设备号都是13,其对应input-core定义的structfile_operations input_fops.驱动架构层通过主设备号13获取到input_fops,之后的处理便交给input_fops进行。

2) 提供接口供事件处理层(input-handler)和输入设备(input-device)注册,并为输入设备找到匹配的事件处理者。

3) 将input-device产生的消息(如触屏坐标和压力值)转发给input-handler,或者将input-handler的消息传递给input-device(如鼠标的闪灯命令)。

三、input子系统初始化

1.    input-core初始化

--driver/input/input.c

在设备模型/sys/class目录注册设备类,在/proc/bus/input目录产生设备信息,向字符设备驱动框架注册input子系统的接口操作集合(主设备号13和input_fops)。

2.input-handler初始化

以支持触摸屏TS的event-handler为例说明。

--driver/input/evdev.c

继续展开input_register_handler接口:

--driver/input/input.c

3.input-device初始化

以触摸屏TSC2007为例,该触摸屏是I2C总线接口访问。

--driver/input/touchscreen/tsc2007.c

I2C总线的管理类似于平台总线,在注册I2C设备驱动接口i2c_add_driver中也会匹配其管理的I2C设备链表元素,匹配成功后即会调用i2c_driver的probe接口。有关总线、设备和驱动的关系请参看《从需求的角度去理解Linux:总线、设备和驱动》。

继续跟踪tsc2007_probe之前先看看input-device的数据结构:

继续跟踪tsc2007_probe:

继续展开input_register_device接口:

--driver/input/input.c

4.input-core关联匹配input-device和input-handler

在input_register_handler和input_register_device最后都会使用input_attach_handler接口来匹配输入设备和对应的事件处理者。

继续跟踪evdev_connect:

--driver/input/evdev.c

Struct evdev evdev_table代表evdev_handler所管理的底层input-device(通过input-handle管理)和应用层已打开该设备的进程、同步的相关结构和消息队列(evdev_client记录)。

input-handle关联input-device和input-handler一目了然。

所以input_register_handle的接口很容易想到是通过input-handle通过自身的d-node和h-node关联到input-device和input-handler实例中。这样通过input-handler可以快速找到input-device,通过input-device也可以快速找到input-handler。

至于evdev_install_chrdev即是将一个evdev实例记录到evdev_table数组,宣告其存在。

至此,我们可以得到以下evdev-handler管理下的示意图:

四、应用open过程

假设触摸屏驱动在注册输入设备过程中生成/dev/input/event0设备文件。我们来跟踪打开这个设备的过程。

Open(“/dev/input/event0”)

1.vfs_open打开该设备文件,读出文件的inode内容,得到主设备号13和次设备号64.

2.chardev_open 字符设备驱动框架的open根据主设备号13得到输入子系统的input_fops操作集。

3.input_fops->open, 即input_open_file

4.继续跟踪input-handler层的evdev-open,至此evdev不仅关联了底层具体的input-device,而且记录了应用层进程打开该设备的信息。之后input-device产生的消息可以传递到evdev的client中的消息队列。便于上层读取。

5. input-device层的open。

实际上,tsc2007驱动并没有定义input_dev的open接口。

五、触屏消息传递过程

1. open获得的fd句柄对应的file_operations是evdev_handler的evdev_fops。因此read接口最终会调用到evdev_fops的read接口,即evdev_read。接下来我们来跟踪这个接口的实现过程。我们先看看struct evdev的成员evdev_client的定义,其即是代表打开该输入设备的进程相关的数据结构。

2. evdev_read

3. 假设消息队列为空时,则上层进程将会睡眠,直到被唤醒再进行消息读取。谁来唤醒它呢?由底层input-device的硬件中断发起,最终将触屏消息送达该消息队列后即会发出唤醒信号。tsc2007_probe中注册的外部硬件中断服务函数即是发起者。

来看看该中断服务函数tsc2007_irq:

ts-work即是tsc2007_work:

跟踪input_report_abs接口:

继续跟进evdev_event:

即会唤醒执行在evdev_read中等待读取消息的进程,继续下面的执行过程,从client的buffer中取出消息,并通过copy_to_user返回给应用程序。

有一点需要注意,每次触屏消息产生后,在tsc2007_work中要input-report-abs报告x坐标,y坐标和压力值,最后再通过input-sync接口发出同步事件,向上层应用发出异步通知进行读取。

怎样,应该是全网络讲述Linux input子系统最详尽和最深入的分析了吧!

敬请关注微信公众号:嵌入式企鹅圈,百分百原创,嵌入式Linux和物联网开发技术经验,资深嵌入式软件架构师撰文。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 01:35:33

全网络对Linux input子系统最清晰、详尽的分析的相关文章

Android驱动之 Linux Input子系统之TP——A/B(Slot)协议

utm_source=tuicool&utm_medium=referral">点击打开链接 将A/B协议这部分单独拿出来说一方面是由于这部分内容是比較easy忽视的.周围大多数用到input子系统的开发者也不甚理解.还有一方面是由于这部分知识一旦扩展到TP(触摸屏Touch Panel)的多点触摸就要与Middleware/Framework一起结合起来看才干全然掌握,复杂性所在. 这里的Middleware/Framework是针对android来说的,本人从事android这

Linux input 子系统应用之按键驱动

硬件平台:s5pv210 软件平台:Linux2.6.35.7 应用程序:inputk2_app.c #include <stdio.h> #include <fcntl.h> #include <linux/input.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char** argv) { int fd; int count; int i = 0; int

Android驱动之 Linux Input子系统之TP——A/B(Slot)协议【转】

转自:http://www.thinksaas.cn/topics/0/646/646797.html 将A/B协议这部分单独拿出来说一方面是因为这部分内容是比较容易忽视的,周围大多数用到input子系统的开发人员也不甚理解:另一方面是由于这部分知识一旦扩展到TP(触摸屏Touch Panel)的多点触摸就要与Middleware/Framework一起结合起来看才能完全掌握,复杂性所在.这里的Middleware/Framework是针对android来说的,本人从事android这几个层次的

Linux input子系统编程、分析与模板

输入设备都有共性:中断驱动+字符IO,基于分层的思想,Linux内核将这些设备的公有的部分提取出来,基于cdev提供接口,设计了输入子系统,所有使用输入子系统构建的设备都使用主设备号13,同时输入子系统也支持自动创建设备文件,这些文件采用阻塞的IO读写方式,被创建在"/dev/input/"下.如下图所示.内核中的输入子系统自底向上分为设备驱动层,输入核心层,事件处理层.由于每种输入的设备上报的事件都各有不同,所以为了应用层能够很好识别上报的事件,内核中也为应用层封装了标准的接口来描述

linux input子系统 — TP A/B(Slot)协议【转】

本文转载自:http://blog.csdn.net/u012719256/article/details/53609906 将A/B协议这部分单独拿出来说一方面是因为这部分内容是比较容易忽视的,周围大多数用到input子系统的开发人员也不甚理解:另一方面是由于这部分知识一旦扩展到TP(触摸屏Touch Panel)的多点触摸就要与Middleware/Framework一起结合起来看才能完全掌握,复杂性所在.这里的Middleware/Framework是针对android来说的,本人从事an

Linux Input子系统

先贴代码: //input.c int input_register_handler(struct input_handler *handler) { //此处省略很多代码 list_for_each_entry(dev, &input_dev_list, node) input_attach_handler(dev, handler); //此处省略很多代码 return 0; } EXPORT_SYMBOL(input_register_handler); int input_registe

Linux input子系统学习总结(二)----Input事件驱动

Input 事件驱动:  (主要文件 :drivers/input/evdev.c  .  drivers/input/input.h)基于kernel 4.0  一. 关键函数调用顺序: 1.input_register_handler(&evdev_handler); ///注册 evdev_handler 这个input事件驱evdev.c      2.input_attach_handler(dev, handler);////input 设备和 input 事件进行匹配   inpu

linux input输入子系统应用分析

输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理是底层在按键.触摸等动作发送时产生一个中断(或驱动通过timer定时查询),然后CPU通过SPI.I2 C或外部存储器总线读取键值.坐标等数据,放入1个缓冲区,字符设备驱动管理该缓冲区,而驱动的read()接口让用户可以读取键值.坐标等数据. 显然,在这些工作中,只是中断.读值是设备相关的,而输入事件的缓冲区管理以及字符设备驱动的file_operations接口则对输入设备是通用的.基于此,内核设计了输入子系统,由核心层

linux input输入子系统分析《四》:input子系统整体流程全面分析

1      input输入子系统整体流程 本节分析input子系统在内核中的实现,包括输入子系统(Input Core),事件处理层(Event Handler)和设备驱动层.由于上节代码讲解了设备驱动层的写法,因此在开头部分会从设备驱动层做为线索,分析输入子系统和事件处理层是如何配合的,最后从用户角度出发,从"/dev/input/*"接口如何使用输入子系统提供的服务. 既然需要详细分析,有一个这样的流程图能够帮助我们在被绕进代码的过程中,找到出口,你能够知道你现在位于代码框架的什