当前位置: 首页 > article >正文

Input子系统驱动---学习记录

目录

应用层如何使用Input子系统

驱动框架流程

驱动应该要实现的功能

evdev.c分析

小结:

gpio_keys.c分析


本文使用Linux4.9.88内核版本。

应用层如何使用Input子系统

Input子系统是一个典型的字符设备驱动程序,所以会创建/dev/input/eventX(也可能是/dev/eventX)设备节点,应用层通过open/read/write/ioctl去访问硬件设备。

驱动框架流程

硬件驱动建立在platform总线上,设备树通过platform_device与硬件驱动的platform_driver匹配,最后调用platform_driver下的.probe。

然后在.probe创建input_dev结构体,然后调用input_register_device去注册设备。

另一边/drivers/input/evdev.c通过module_init在初始化函数内创建input_handler结构体然后调用input_register_handler。(这块代码已经实现了,我们并不需要自己实现)

如何匹配是由/drivers/input/input.c里的两个全局变量input_handler_list、input_dev_list实现的,如下图:

input_register_handler会把input_handler通过list_add_tail添加进input_handler_list链表,然后通过list_for_each_entry在input_dev_list链表做匹配。

input_register_device会把input_dev通过list_add_tail添加进input_dev_list链表,然后通过list_for_each_entry在input_handler_list链表里做匹配。

如果匹配成功,就会调用evdev.c下input_handler结构体的.connect函数。如下图:

我们会发现input_register_handler使用的input_handler会和input_register_device使用的input_dev形成类似platform_device与platform_driver的映射关系。

所以input子系统驱动的整个流程用图表示如下:

驱动应该要实现的功能

由于/drivers/input/evdev.c已经帮我们实现了input_handler,所以我们只需要实现input_dev部分。

而这部分我们大概猜测:

1.创建input_dev结构体

2.设置设备树硬件信息

3.设置硬件中断(通过硬件中断去获取数据,所以在input的设备树节点中一定是有interrupts或者gpios用于设置中断)

4.调用input_register_device.

下面通过gpio_keys.c和evdev.c为例说下驱动流程.

evdev.c分析

input_register_handler设置evdev_handler,input_register_handler内部会首先把evdev_handler加入到全局链表input_handler_list里,如下图:

然后调用

    list_for_each_entry(dev, &input_dev_list, node)

        input_attach_handler(dev, handler);会去与input_dev_list这个全局链表查找匹配,而input_register_device设置的input_dev就是放进input_dev_list,如果匹配成功,就会调用input_attach_handler,从而调用evdev_handler里的.connect。

在evdev_connect中就会在/dev/input下创建eventX节点,应用层open/read/write/ioctl就会调用对应的file_operations函数,如下图:

当硬件驱动调用input_register_device里注册的中断函数触发中断就会调用input_event里的input_handle_event去传输数据,这样当应用层调用read时,就会进入等待,当硬件触发中断后,才会开始读取数据。

同样的应用层调用write时,调用input_handle_event写入数据。

小结:

evdev.c这个作用就是用来与所有的input设备进行匹配,并且实现了一套通用的file_operations函数,而我们只需要在建立的这套框架上实现input_dev这块的驱动即可。

gpio_keys.c分析

设置evdev.c里file_operations的open/close,这样当应用层调用open/close最终就会调用gpio_keys_open和gpio_keys_close,如下图:

通过gpio_keys_setup_key去设置中断,如果在设备树里用的是gpios表示中断,那么就用gpio_keys_gpio_isr设置,如果用的是interrupts表示中断,就用gpio_keys_irq_isr设置。如下图

 

在input_dev结构体中,evbit/keybit这两个参数是很重要的,如下图

所以,在gpio_keys_setup_key   >  input_set_capability里处理,而设备树中通过linux,code来设置,如下图

最后通过input_register_device注册input_dev。

当用户层调用read时,会进入等待,一直到按下按键,就会触发中断 gpio_keys_gpio_isr   >  gpio_keys_gpio_work_func   >  gpio_keys_gpio_report_event  >  input_event  > input_handle_event,最后就会唤醒read里的等待,最终读取数据。


http://www.kler.cn/a/448737.html

相关文章:

  • UWB无载波通信技术,UWB定位系统源码
  • 华为IPD流程6大阶段370个流程活动详解_第一阶段:概念阶段 — 81个活动
  • 微服务分布式(二、注册中心Consul)
  • 【Spring事务】深入浅出Spring事务从原理到源码
  • SAP HCM 考勤时间冲突到分 源码分析
  • 强基计划之编程:开启科研精英培养新路径
  • 整理一些/etc/X11/xorg.conf,/etc/X11/xorg.conf.d相关知识的学习笔记
  • 微服务openfeign配置重试机制
  • Unittest01|TestCase、断言、装饰器、夹具、清理函数、ddt
  • FastAPI vs Go 性能对比分析
  • 语言模型与向量模型:深入解析与实例剖析
  • PHP中实现拓扑算法
  • Bazel CI
  • 基于 SSM 和 Vue 的 WEB 开放性实验室集成管理系统
  • 【leetcode100】排序链表
  • springboot根据租户id动态指定数据源
  • react Moment.js 是一个流行的 JavaScript 库,用于处理日期和时间。它提供了丰富的功能,包括日期格式化、解析、操作和国际化
  • 前端 下载文件时如何处理后端返回的 文件流
  • Vulkan 学习(10)---- Vulkan SwapChain 创建
  • 实现 React 电子签名功能:从零开始构建一个完整的解决方案
  • Unity全局雾效
  • 深度学习革新音乐转录
  • MQTT实现集群分布式消费
  • 计算机前沿技术-人工智能算法-大语言模型-最新研究进 2024-12-22
  • XRP价格跌破2.20美元 1.94美元是否下一波牛市的关键支撑?
  • 【再谈设计模式】外观模式~复杂系统交互的简化大师