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

触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报

触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报

在这里插入图片描述
以下是架构图,对触摸屏(典型I2C + Input子系统设备)从设备树解析到触摸事件上报的全流程详细拆解,包含文字讲解和配套流程图:

注:代码程序可以参考driver\input\touchscreen\gt9xx.c,驱动程序非常复杂是因为要兼容很多厂家的设备甚至升级固件之类的操作,通用的大致流程如下:

一、核心角色与职责

组件作用
设备树描述硬件拓扑(I2C总线、触摸屏设备地址、中断号等)
i2c_client代表I2C总线上的触摸屏设备,保存设备地址、总线适配器等信息
i2c_driver触摸屏驱动核心,负责匹配i2c_client、初始化硬件、创建Input子系统设备
input_dev向上抽象为输入设备(如触摸屏),提供事件上报接口(按键、绝对坐标等)
input_handler输入事件处理器(如evdev),负责接收input_dev事件并暴露给用户空间

二、全流程分步讲解(配流程图)

1. 设备树解析与 i2c_client 创建

流程

设备树
设备树解析
i2c总线驱动
i2c_client创建
i2c_client注册到i2c总线

细节

  • 设备树中定义触摸屏节点(示例片段):
    i2c@12340000 { // I2C控制器节点touchscreen@38 { // 触摸屏子节点,地址0x38compatible = "vendor,touchscreen"; reg = <0x38>; // I2C设备地址interrupts = <IRQ_TYPE_EDGE_FALLING 25>; // 中断号};
    };
    
  • 内核启动时,I2C总线驱动解析设备树,为每个I2C设备创建 i2c_client,填充设备地址、兼容字符串、中断等信息,注册到 i2c_bus_type 总线。
2. i2c_driver 注册与匹配

流程

compatible匹配
i2c_driver编写
i2c_driver注册
i2c总线匹配
i2c_driver.probe调用

细节

  • 驱动代码中定义 i2c_driver
    static const struct of_device_id touchscreen_of_match[] = {{ .compatible = "vendor,touchscreen" }, // 匹配设备树compatible{ },
    };static struct i2c_driver touchscreen_i2c_driver = {.probe    = touchscreen_probe, // 匹配成功后执行的函数.driver = {.name = "touchscreen",.of_match_table = touchscreen_of_match,},
    };module_i2c_driver(touchscreen_i2c_driver); // 注册到I2C总线
    
  • 匹配逻辑i2c_bus_type 遍历总线上的 i2c_client 和已注册 i2c_driver,通过 compatible 字符串匹配。匹配成功后,调用 i2c_driver.probe 函数。
3. input_dev 创建与注册(在 probe 中完成)

流程

probe函数启动
硬件初始化
input_dev分配
input_dev设置
input_dev注册

细节

  • probe 函数核心逻辑:
    static int touchscreen_probe(struct i2c_client *client, const struct i2c_device_id *id) {struct input_dev *input;int ret;// 1. 硬件初始化(如配置I2C寄存器、申请中断)ret = i2c_smbus_write_byte_data(client, 0x00, 0x01); // 示例写寄存器if (ret < 0) return ret;// 2. 分配input_devinput = devm_input_allocate_device(&client->dev);if (!input) return -ENOMEM;// 3. 设置input_dev属性input->name = "touchscreen";input->phys = "i2c-touchscreen/input0";input->id.bustype = BUS_I2C;// 4. 声明支持的事件类型(如绝对坐标、按键)__set_bit(EV_ABS, input->evbit); __set_bit(ABS_X, input->absbit);__set_bit(ABS_Y, input->absbit);__set_bit(EV_KEY, input->evbit);__set_bit(BTN_TOUCH, input->keybit);// 5. 注册input_dev到Input子系统ret = input_register_device(input);if (ret < 0) return ret;// 6. 保存input_dev到私有数据(供中断处理用)i2c_set_clientdata(client, input);// 7. 申请中断(触摸事件触发时调用中断处理函数)return devm_request_irq(&client->dev, client->irq, touchscreen_irq_handler, IRQF_TRIGGER_FALLING, "touchscreen", input);
    }
    
4. input_handler 自动匹配与关联

流程

事件类型匹配
input_dev注册
Input子系统匹配
input_handler关联

细节

  • Input子系统中,input_handler(如通用的 evdev 处理器)会遍历所有 input_dev,根据 input_dev 声明的事件类型(evbit/keybit 等)自动匹配。
  • 典型场景:evdev 会匹配所有 input_dev,为每个设备创建 /dev/input/eventX 节点,用户空间通过读取这些节点获取事件。
5. 触摸事件上报(中断触发)

流程

触摸屏幕
硬件中断触发
中断处理函数
读取I2C数据
input_event上报
input_handler转发
用户空间读取

细节

  • 中断触发:触摸屏幕时,硬件产生中断,触发 touchscreen_irq_handler
  • 中断处理函数
    static irqreturn_t touchscreen_irq_handler(int irq, void *dev_id) {struct input_dev *input = dev_id;struct i2c_client *client = input_get_drvdata(input);u16 x, y;bool pressed;// 1. 从I2C设备读取触摸坐标、压力等数据i2c_smbus_read_i2c_block_data(client, 0x10, 4, buffer); // 示例读数据x = (buffer[0] << 8) | buffer[1];y = (buffer[2] << 8) | buffer[3];pressed = (buffer[0] & 0x80) ? 1 : 0; // 假设最高位表示按压// 2. 上报按键事件(按下/松开)input_report_key(input, BTN_TOUCH, pressed);// 3. 上报绝对坐标事件input_report_abs(input, ABS_X, x);input_report_abs(input, ABS_Y, y);// 4. 同步事件(通知用户空间数据已就绪)input_sync(input);return IRQ_HANDLED;
    }
    
  • 用户空间读取:通过 libinput 或直接读 /dev/input/eventX,解析事件结构体(struct input_event)获取坐标、按键状态。

三、完整流程图(合并版)

在这里插入图片描述

flowchart TBsubgraph 设备树解析A[设备树定义触摸屏节点] --> B[i2c总线驱动解析]B --> C[i2c_client创建并注册到i2c_bus_type]endsubgraph 驱动注册与匹配D[i2c_driver定义(含compatible)] --> E[i2c_driver注册到i2c_bus_type]E --> F{i2c_bus_type匹配}F -->|compatible一致| G[调用i2c_driver.probe]endsubgraph Input子系统初始化G --> H[硬件初始化(I2C、中断)]H --> I[input_dev分配+配置(事件类型)]I --> J[input_dev注册到Input子系统]J --> K{Input子系统匹配}K -->|事件类型匹配| L[input_handler(如evdev)关联]endsubgraph 触摸事件上报M[触摸屏幕触发硬件中断] --> N[中断处理函数调用]N --> O[读取I2C触摸数据(坐标、压力)]O --> P[input_event上报(按键、坐标)]P --> Q[input_sync同步事件]Q --> R[input_handler转发到/dev/input/eventX]R --> S[用户空间读取事件]end

四、关键总结

  1. 分层解耦:I2C总线负责硬件通信,Input子系统负责输入事件抽象,驱动只需关注“硬件数据读取”和“事件上报”。
  2. 自动匹配:通过 compatible(I2C层)和 事件类型(Input层)实现驱动与设备、处理器的自动关联。
  3. 事件流:触摸动作→硬件中断→驱动读数据→input_event 上报→input_handler 转发→用户空间消费。

理解这套流程后,无论是调试触摸屏驱动、扩展Input设备(如按键、传感器),还是优化事件响应,都能更清晰地定位问题~

http://www.lryc.cn/news/574422.html

相关文章:

  • Redis哨兵模式深度解析与实战部署
  • 用 GitHub Issues 做任务管理和任务 List,简单好用!
  • 【图像】ubuntu中图像处理
  • Redis精简总结|一主二从哨兵模式(工作机制)|集群模式|缓存的穿透雪崩击穿
  • NFS服务配置超详细版
  • 第一节 布局与盒模型-Flex与Grid布局对比
  • 考研408《计算机组成原理》复习笔记,第三章(2)——存储器的ROM、RAM(DRAM和SRAM)、磁盘硬盘
  • 鸿蒙容器组件 Row 全解析:水平布局技术与多端适配指南
  • 实现 “WebView2 获取word选中内容
  • Python-1-环境
  • SQLite3 在嵌入式系统中的应用指南
  • 华为云 Flexus+DeepSeek 征文|CCE 集群部署 Dify 平台:【工作流协同高质量知识库】搭建企业级教培行业 Agent 顾问
  • C3新增特性
  • springcloud/springmvc协调作用传递验证信息
  • 如何实现财务自由
  • qt常用控件--02
  • AI-Sphere-Butler之如何将豆包桌面版对接到AI全能管家~新玩法(一)
  • 功率器件的基本公式概念
  • React Native【实用教程】(含图标方案,常用第三库,动画,内置组件,内置Hooks,内置API,自定义组件,创建项目等)
  • 【机器学习1】线性回归与逻辑回归
  • iperf3使用方法
  • 实验九:RIPv2协议配置与分析
  • 【C语言】解决VScode中文乱码问题
  • 目标检测之YOLOv5到YOLOv11——从架构设计和损失函数的变化分析
  • Windows电脑数据恢复终极指南:从原理到实战
  • 【AI论文】扩展大型语言模型(LLM)智能体在测试时的计算量
  • K8S下http请求在ingress和nginx间无限循环的问题
  • 【第二章:机器学习与神经网络概述】03.类算法理论与实践-(1)逻辑回归(Logistic Regression)
  • Threejs实现 3D 看房效果
  • 基于java SSM的房屋租赁系统设计和实现