当前位置: 首页 > 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设备(如按键、传感器),还是优化事件响应,都能更清晰地定位问题~

相关文章:

  • 1免费网站建站百度极速版推广员怎么申请
  • 如何进入网站后台 被黑怎么给自己的公司建立网站
  • 网站建设阝金手指实惠保定百度seo排名
  • 龙川网站建设搜索热词排名
  • 珠海企业网站设计苏州seo优化
  • 2016大型注册域名网站有哪些/宁波seo关键词培训
  • 011 Linux进程
  • OpenLayers 图文标注大全
  • springcloud/springmvc协调作用传递验证信息
  • 什么是Sentinel?以及优缺点
  • 手撕 Decoder
  • Day 2:Shell变量解密——从“Hello World“到会“记忆“的脚本
  • C语言数组介绍 -- 一维数组和二维数组的创建、初始化、下标、遍历、存储,C99 变长数组
  • Zynq + FreeRTOS + YAFFS2 + SQLite3 集成指南
  • python计算长方形的周长 2025年3月青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析
  • Vibe Coding - 使用cursor从PRD到TASK精准分解执行
  • 《内心强大不怯场》读书笔记3
  • 智能营销系统对企业的应用价值
  • 【Java面试】你是怎么控制缓存的更新?
  • Linux内核网络栈的智慧:skb->cb控制缓冲区的设计哲学
  • sudo安装pip包的影响
  • 有哪些词编码模型
  • 相机标定与3D重建技术通俗讲解
  • Python基础(​​FAISS​和​​Chroma​)
  • 每日算法刷题Day36 6.23:leetcode枚举技巧枚举中间4道题,用时1h30min
  • VLN论文复现——VLFM(ICRA最佳论文)