• Linux学习第43天:Linux 多点电容触摸屏实验:难忘记第一次牵你手的温存


    Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 


           人都是性情中人,如果把学习当做自己的女朋友,对她细致入微、掏心掏肺、有耐心有恒心,终会修成正果。

            而我们本节需要学习的电容触摸屏的驱动开发,就相当于你第一次牵手未来另一半的温存。真正学会学懂,等真正用到的时候才知道会有多香多甜多心满意足。

             本章主要学习触摸屏的驱动开发,需要学习的主要内容包括电容触摸屏的驱动框架简介、硬件原理分析以及驱动的开发与测试。本节内容重点学习本章的第一节电容触摸屏的驱动框架,其余内容将在下一节进行学习。

            本章的思维导图内容如下:

    一、Linux下电容触摸屏驱动框架简介

    1、多点触摸(MT)协议详解

    ①、电容屏 IIC接口  IIC设备驱动
    ②、中断获取触摸信息 中断驱动框架

    ③、是否触摸  绝对位置 input子系统
    ④、电容触摸屏不需要校准

            多点电容触摸协议

            MT协议两种类型:typeA 、typeB(常用 硬件追踪)

            ABS_MT事件多点触控:

    ABS_MT_SLOT :触摸点ID
    ABS_MT_POSITION_X 、 ABS_MT_POSITION_Y :触摸点坐标

    ABS_MT_TRACKING_ID:Type B 设备区分触摸点

            input_mt_slot()函数:Type B 设备  区分哪一个触摸点

    void input_mt_slot(struct input_dev *dev, int slot)//slot 当前上报的哪个触摸点

    触发ABS_MT_SLOT事件。

            input_sync()函数来标识多点触摸信息传输完成,告诉接收者处理之前累计的所有消息,并且准备好下一次接收。

            Type B 设备驱动需要给每个识别出来的触摸点分配一个 slot,后面使用这个 slot 来上报触
    摸点信息。

            可以通过 slot 的 ABS_MT_TRACKING_ID 来新增、替换或删除触摸点。一个非负数的 ID 表示一个有效的触摸点, -1 这个 ID 表示未使用 slot。一个以前不存在的 ID 表示这是一个新加的触摸点,一个 ID 如果再也不存在了就表示删除了。

            有些设备识别或追踪的触摸点信息要比他上报的多,这些设备驱动应该给硬件上报的每个触摸点分配一个 Type B 的 slot。一旦检测到某一个 slot 关联的触摸点 ID 发生了变化,驱动就应该改变这个 slot 的 ABS_MT_TRACKING_ID,使这个 slot 失效。如果硬件设备追踪到了比他正在上报的还要多的触摸点,那么驱动程序应该发送 BTN_TOOL_*TAP 消息,并且调用
    input_mt_report_pointer_emulation()函数,将此函数的第二个参数 use_count 设置为 false。
     

    2、TypeA触摸点信息上报时序

    1. 1 ABS_MT_POSITION_X x[0]
    2. 2 ABS_MT_POSITION_Y y[0]
    3. 3 SYN_MT_REPORT//上报 SYN_MT_REPORT 事件,通过调用 input_mt_sync 函数来实现。
    4. 4 ABS_MT_POSITION_X x[1]
    5. 5 ABS_MT_POSITION_Y y[1]
    6. 6 SYN_MT_REPORT
    7. 7 SYN_REPORT//上报 SYN_REPORT 事件,通过调用 input_sync 函数实现。

    3、TypeB触摸点信息上报时序

    1. 1 ABS_MT_SLOT 0/*每次上报一个触摸点坐
    2. 标之前要先使用input_mt_slot函数上报当前触摸点SLOT*/
    3. 2 ABS_MT_TRACKING_ID 45/*每个 SLOT 必须关联一个 ABS_MT_TRACKING_ID,通过
    4. 修改 SLOT 关联的 ABS_MT_TRACKING_ID 来完成对触摸点的添加、替换或删除。具体用到的函数input_mt_report_slot_state*/
    5. 3 ABS_MT_POSITION_X x[0]
    6. 4 ABS_MT_POSITION_Y y[0]
    7. 5 ABS_MT_SLOT 1
    8. 6 ABS_MT_TRACKING_ID 46
    9. 7 ABS_MT_POSITION_X x[1]
    10. 8 ABS_MT_POSITION_Y y[1]
    11. 9 SYN_REPORT

            触摸点移除:

    1. 1 ABS_MT_TRACKING_ID -1/*input_mt_report_slot_state 设置active为false*/
    2. 2 SYN_REPORT

    4、MT其他事件的使用

    ABS_MT_POSITION_X 和ABS_MT_POSITION_Y:上报触摸点

    ABS_MT_TOUCH_MAJOR 和 ABS_MT_WIDTH_MAJOR :上报触摸面积

    ABS_MT_TOOL_TYPE 事件用于上报触摸工具类型:

    MT_TOOL_FINGER(手指)、 MT_TOOL_PEN(笔)和 MT_TOOL_PALM(手掌)
    于Type B类型,事件由input子系统内核处理。上报此类事件,由函数

    input_mt_report_slot_state完成。

    5、多点触摸所使用到的API函数

    1)、input_mt_init_slots函数

    用于初始化 MT 的输入 slots:

    1. int input_mt_init_slots( struct input_dev *dev,
    2. unsigned int num_slots,
    3. unsigned int flags)

    2)、input_mt_slot函数

            用于产生 ABS_MT_SLOT 事件,告诉内核当前上报的是哪个触摸点的坐标数据:

    1. void input_mt_slot(struct input_dev *dev,
    2. int slot)

    3)、input_mt_report_slot_state函数

            用于 Type B 类型,用于产生 ABS_MT_TRACKING_ID 和 ABS_MT_TOOL_TYPE
    事 件 , ABS_MT_TRACKING_ID 事 件 给 slot 关 联 一 个 ABS_MT_TRACKING_ID ,
    ABS_MT_TOOL_TYPE 事 件 指 定 触 摸 类 型 ( 是 笔 还 是 手 指 等 )。

    1. void input_mt_report_slot_state( struct input_dev *dev,
    2. unsigned int tool_type,
    3. bool active)/*true,连续触摸,input 子系统内核会自动分配一个 ABS_MT_TRACKING_ID 给 slot。
    4. false,触摸点抬起,表示某个触摸点无效了, input 子系统内核会分配一个-1 给 slot,表示触摸
    5. 点溢出。*/

    4)、input_report_abs函数

            上报触摸点坐标信息:

    1. void input_report_abs( struct input_dev *dev,
    2. unsigned int code,/*要上报的是什么数据,可以设置为 ABS_MT_POSITION_X 或 ABS_MT_POSITION_Y,
    3. 也就是 X 轴或者 Y 轴坐标数据。*/
    4. int value)/*具体的 X 轴或 Y 轴坐标数据值。*/

    5)、input_mt_report_pointer_emulation函数

            如果追踪到的触摸点数量多于当前上报的数量,驱动程序使用 BTN_TOOL_TAP 事件来通知用户空间当前追踪到的触摸点总数量,然后调用 input_mt_report_pointer_emulation 函数将
    use_count 参数设置为 false。否则的话将 use_count 参数设置为 true,表示当前的触摸点数量(此
    函数会获取到具体的触摸点数量,不需要用户给出):

    1. void input_mt_report_pointer_emulation(struct input_dev *dev,
    2. bool use_count)

    6、多点电容触摸驱动框架

    1)、I2C驱动框架

    1. 1 /* 设备树匹配表 */
    2. 2 static const struct i2c_device_id xxx_ts_id[] = {
    3. 3 { "xxx", 0, },
    4. 4 { /* sentinel */ }
    5. 5 };
    6. 6
    7. 7 /* 设备树匹配表 */
    8. 8 static const struct of_device_id xxx_of_match[] = {
    9. 9 { .compatible = "xxx", },
    10. 10 { /* sentinel */ }
    11. 11 };
    12. 12
    13. 13 /* i2c 驱动结构体 */
    14. 14 static struct i2c_driver ft5x06_ts_driver = {
    15. 15 .driver = {
    16. 16 .owner = THIS_MODULE,
    17. 17 .name = "edt_ft5x06",
    18. 18 .of_match_table = of_match_ptr(xxx_of_match),
    19. 19 },
    20. 20 .id_table = xxx_ts_id,
    21. 21 .probe = xxx_ts_probe,
    22. 原子哥在线教学:www.yuanzige.com 论坛:www.openedv.com
    23. 1511
    24. I.MX6U 嵌入式 Linux 驱动开发指南
    25. 22 .remove = xxx_ts_remove,
    26. 23 };
    27. 24
    28. 25 /*
    29. 26 * @description : 驱动入口函数
    30. 27 * @param : 无
    31. 28 * @return : 无
    32. 29 */
    33. 30 static int __init xxx_init(void)
    34. 31 {
    35. 32 int ret = 0;
    36. 33
    37. 34 ret = i2c_add_driver(&xxx_ts_driver);
    38. 35
    39. 36 return ret;
    40. 37 }
    41. 38
    42. 39 /*
    43. 40 * @description : 驱动出口函数
    44. 41 * @param : 无
    45. 42 * @return : 无
    46. 43 */
    47. 44 static void __exit xxx_exit(void)
    48. 45 {
    49. 46 i2c_del_driver(&ft5x06_ts_driver);
    50. 47 }
    51. 48
    52. 49 module_init(xxx_init);
    53. 50 module_exit(xxx_exit);
    54. 51 MODULE_LICENSE("GPL");
    55. 52 MODULE_AUTHOR("zuozhongkai");

            当设备树中触摸IC的设备节点和驱动匹配以后,xxx_ts_probe函数就会执行。可以在此函数中初始化触摸IC,中断和input子系统。

    2)、初始化触摸IC、中断和input子系统

    1. 1 static int xxx_ts_probe(struct i2c_client *client, const struct
    2. i2c_device_id *id)
    3. 2 {
    4. 3 struct input_dev *input;
    5. 4
    6. 5 /* 1、初始化 I2C */
    7. 6 ......
    8. 7
    9. 8 /* 2,申请中断, */
    10. 9 devm_request_threaded_irq(&client->dev, client->irq, NULL,
    11. 10 xxx_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
    12. 11 client->name, &xxx);
    13. 12 ......
    14. 13
    15. 14 /* 3, input 设备申请与初始化 */
    16. 15 input = devm_input_allocate_device(&client->dev);
    17. 16
    18. 17 input->name = client->name;
    19. 18 input->id.bustype = BUS_I2C;
    20. 19 input->dev.parent = &client->dev;
    21. 20 ......
    22. 21
    23. 22 /* 4,初始化 input 和 MT */
    24. 23 __set_bit(EV_ABS, input->evbit);
    25. 24 __set_bit(BTN_TOUCH, input->keybit);
    26. 25
    27. 26 input_set_abs_params(input, ABS_X, 0, width, 0, 0);
    28. 27 input_set_abs_params(input, ABS_Y, 0, height, 0, 0);
    29. 28 input_set_abs_params(input, ABS_MT_POSITION_X,0, width, 0, 0);
    30. 29 input_set_abs_params(input, ABS_MT_POSITION_Y,0, height, 0, 0);
    31. 30 input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0);
    32. 31 ......
    33. 32
    34. 33 /* 5,注册 input_dev */
    35. 34 input_register_device(input);
    36. 35 ......
    37. 36 }

            devm_request_threaded_irq 函数特点:

    ①、用于申请中断。

    ②、此函数的作用是中断线程化。

    ③、使用“ devm_”前缀的函数申请到的资源可以由系统自动释放,不需要我们手动处理。
            多点电容屏的触摸坐标为绝对值,因此需要上报 EV_ABS 事件。触摸屏有按下和抬起之分,因此需要上报 BTN_TOUCH 按键。

    3)、上报坐标信息

    1. 1 static irqreturn_t xxx_handler(int irq, void *dev_id)
    2. 2 {
    3. 3
    4. 4 int num; /* 触摸点数量 */
    5. 5 int x[n], y[n]; /* 保存坐标值 */
    6. 6
    7. 7 /* 1、从触摸芯片获取各个触摸点坐标值 */
    8. 8 ......
    9. 9
    10. 10 /* 2、上报每一个触摸点坐标 */
    11. 11 for (i = 0; i < num; i++) {
    12. 12 input_mt_slot(input, id);
    13. 13 input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
    14. 14 input_report_abs(input, ABS_MT_POSITION_X, x[i]);
    15. 15 input_report_abs(input, ABS_MT_POSITION_Y, y[i]);
    16. 16 }
    17. 17 ......
    18. 18
    19. 19 input_sync(input);
    20. 20 ......
    21. 21
    22. 22 return IRQ_HANDLED;
    23. 23 }

            每一轮触摸点坐标上报完毕以后就调用一次 input_sync 函数发送一个SYN_REPORT 事件。

            以下内容将在下一节笔记中更新。

    二、硬件原理图分析

    三、实验程序编写

    1、修改设备树

    1)、添加FT5426所使用的IO

    2)、添加FT5426节点

    2、编写多点电容触摸驱动

    四、运行测试

    1、编译驱动程序

    2、运行测试

    3、将驱动添加到内核中

    1)、将驱动文件放到合适的位置

    2)、修改对应的Makefile

    五、tslib移植与使用

    1、tslib移植

    1)、获取tslib源码

    2)、修改tslib源码所属用户

    3)、ubuntu工具安装

    4)、编译tslib

    5)、配置tslib

    6)、tslib测试

    六、使用内核自带的驱动

    1、修改edt-ft5x06.c

    2、使能内核自带的FT5X06驱动

    3、修改设备树

    七、4.3.寸屏触摸驱动实验

    1、修改设备树pinctrl_tsc节点内容

    2、在设备树的i2c2节点下添加tgt9147子节点

    3、修改设备树的lcdif节点

    4、编译GT9147驱动文件

    八、总结


    本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。

  • 相关阅读:
    关于我加了一行日志搞崩了服务这件小事
    底层全部重构,小米澎湃OS完整系统架构公布
    LeetCode | 850. 矩形面积 II
    [附源码]计算机毕业设计springboot校园生活服务平台
    基于Pytest+Requests+Allure实现接口自动化测试!
    winform 使用MiniExcel 动态读取EXCEL文件 动态加载列跟数据
    权威认可 | Smartbi为何屡获市场认可,多个权威报告给出答案
    JAVA毕业设计共享顺风车管理系统计算机源码+lw文档+系统+调试部署+数据库
    安防监控系统/视频云存储EasyCVR平台视频无法播放是什么原因?
    已知CSIDL常量值,求其对应路径。
  • 原文地址:https://blog.csdn.net/jiage987450/article/details/134482470