首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

input_system输入子系统解析(1)

input_system输入子系统解析(1)

Input子系统与TP驱动
对于众多的输入设备的驱动问题,linux提供了一套非常灵活的机制:input子系统。通过它我们只需要调用一些简单的函数,就可以将一个输入设备的功能呈现给应用程序。input输入子系统由输入子系统驱动层,核心层(Input Core),和事件处理层(Event Handler)三部分组成。

驱动层:负责和具体的硬件设备交互,采集输入设备的数据信息,通过核心层提供的API上报数据;
核心层:为事件处理层和设备驱动层提供接口API,起到一个中间层的作用;
事件处理层:通过核心层的API获取输入事件上报的数据,定义API与应用层交互。

主要是三大结构体所建立的联系,沟通了input子系统,他们在
kernel-4.4/include/linux/input.h中有定义:
struct input_dev:会在具体设备驱动层中被填充
struct input_handle:会在事件处理层和设备驱动层注册设备时通过input_dev或input_handler间接调用
struct input_handler:会在事件处理层如evdev.c中被实例化

浅析三大结构体关系

input_handle是连接input_dev和input_handler的桥梁,input_dev可以通过input_handle找到input_handler,同样的input_handler可以通过input_handle找到input_dev

一个device可能对应多个handler,而一个handler也不能只处理一个device,比如说一个鼠标,它可以对应evdev_handler,也可以对应mouse_handler,因此当其注册时与系统中的handler进行匹配,

就有可能产生两个实例,一个是evdev,另一个是mousedev,而任何一个实例中都只有一个handle,至于以何种方式来传递事件,就由用户程序打开哪个实例来决定

后面一个情况很容易理解,一个事件驱动不能只为一个甚至一种设备服务,系统中可能有多种设备都能使用这类handler,比如event handler就可以匹配所有的设备

在input子系统中,有8种事件驱动,每种事件驱动最多可以对应32个设备,因此dev实例总数最多可以达到256个。

以MTK的TP驱动为例贯穿讲解输入子系统:

MTK平台的TP驱动是分为两个部分组合在一起的,全平台的共享驱动mtk_tpd.c(抽象),以及各个型号TP的独立驱动(真实),mtk_tpd.c负责将TP注册到platform总线,以及利用input子系统核心层提供的API向事件处理层上报键值,各个型号的独立驱动负责I2C总线挂接,读取键值提交给mtk_tpd.c。mtk_tpd.c做的重要的一件事就是注册platform平台总线,对设备的申请tpd->dev = input_allocate_device();
==> input_register_device(tpd->dev)注册输入设备,一些事件的属性设置,以及对各型号TP的兼容遍历,都是在其probe函数(mtk_touch_driver函数的.of_match_table = touch_of_match的compatible = "mediatek,mt6739-touch"与在mt6739.dts注册的设备device touch: touch compatible = “mediatek,mt6739-touch”;相同,就执行tpd_probe函数)中完成的。

注册input device的过程就是为input device设置默认值,

==> list_add_tail(&dev->node, &input_dev_list)将新分配的input设备连接到input_dev_list链表上并与挂在input_handler_list链表中的handler相匹配

==> 调用input_attach_handler(dev, handler);去匹配

==> 调用input_match_device匹配(关于input_match_device函数,它是通过匹配id来确认匹配的,看handler的id是否支持),

所有的input_dev挂载到input_dev_list 链表上,所有的handler挂载到input_handler_list上),如果匹配成功就会调用handler的connnect函数,

==> connnect函数是在事件处理层定义并实现的,

以evdev.c为例,则connect函数就是 ==> evdev_connect。evdev_connect()函数主要用来连接input_dev和input_handler,这样事件的流通链才能建立,流通链建立后,事件才知道被谁处理,或者处理后将向谁返回结果。
返回列表