最近正在做安卓系统的驱动开发工作,学习了focaltech(敦泰)触摸屏驱动Ft5306.c,简单总结如下(未完,待续)。因为刚接触驱动开发,许多知识没有彻底理解,如有错误请指正。

1 概述

linux触摸屏驱动基于linux input 子系统,层次上位于input系统的第三层,主要是完成具体输入设备的驱动功能程序,Ft5306.c源文件位于kernel下drivers\input\touchscreen目录下,属于字符型驱动,ft5306使用的多点触控协议是A协议。

Ft5306驱动主要涉及的知识架构有:

linux驱动开始相关知识;

linux input 子系统机制;

linux I2C总线结构及I2C协议;

中断下半部处理机制-工作队列;

linux内核多点触控协议;

触摸屏实现原理;

其他:如platform机制、dts设备结构树,安卓下的唤醒机制、virtualkeys触摸按键发送方法等;

2 具体分析

2.1 驱动的注册及退出:ft5306.c

module_init(focaltech_ft5306_init);

module_exit(focaltech_ft5306_exit);

注意:驱动入口函数focaltech_ft5306_init有固定格式要求:函数入参必须为void,返回值类型必须为int。

2.2 I2C板级信息初始化

: 注意:0x70 >> 1为I2C通信中的从地址,通常从芯片手册中获取的地址需要右移1位;ps:board-granet.c(不同平台源文件可能不同)

staticstruct i2c_board_info __initdata ft5306_info[] = {

{                           /* New touch screeni2c slave address. */

I2C_BOARD_INFO("FocalTech-Ft5306",(0x70 >> 1)),

.platform_data= &ft5306_plat_data,

.irq= gpio_to_irq(TSC_GPIO_IRQ_PIN),

},};

i2c_board_info结构体用来保存I2C设备的相关信息,Linux根据这些信息创建I2C设备相关的设备模型树。对于mainboards,通过调  用i2c_register_board_info()静态完成。对于add-on boards,通过调用i2c_new_device()动态完成。i2c_board_info结构体有两个成员必须初始化,一个是type,用来初始化i2c_client.name;另一个是addr,用来初始化i2c_client.addr。其它i2c_board_info结构体成员根据需要赋值或保持为空。

2.3 I2c_client (I2C 适配器)注册(并没有创建)

:使用i2c_register_board_info(3, ft5306_info,ARRAY_SIZE(ft5306_info));board-granet.c

2.4 I2Cdriver的注册:ft5306.c

首先定义结构体:i2c_driver focaltech_ft5306_driver,注意.name 成员必须与ft5306_info中I2C_BOARD_INFO第一个参数相同,否则I2c_client 与I2C driver不会匹配成功

staticstruct i2c_driver focaltech_ft5306_driver = {

.probe                = focaltech_ft5306_probe,

.remove            = focaltech_ft5306_remove,

#ifndef CONFIG_HAS_EARLYSUSPEND

.suspend  = focaltech_ft5306_suspend,

.resume            = focaltech_ft5306_resume,

#endif

.id_table  = focaltech_ft5306_id,

.driver= {

.name       = "FocalTech-Ft5306",

},               }   ;

其次注册:在focaltech_ft5306_init   调用i2c_add_driver(&focaltech_ft5306_driver);

最后注销:i2c_driver注销 是在驱动文件中exit函数,例如 focaltech_ft5306_exit 调用i2c_del_driver;

2.5 I2Cclient 与driver的匹配:ft5306.c

foc   focaltech_ft5306_init -> i2c_add_driver-> i2c_register_driver-driver_register->调用i2c_for_each_dev遍历所有已存在的i2c_adapter->…-> i2c_do_add_adapter(该函数主要完成i2c_driver与i2c_adapter上的i2c设备的匹配工作,根据i2c_client.name与 driver.name 是否相同来匹配。如果匹配成功,初始化并创建对应的i2c_client。)                        在driver_register执行过程中,如果I2C总线上找到了与该驱动匹配的I2C设备,则i2c_driver.probe函数会被调用执行。

当进入i2c_driver.probe后,依次执行:

2.6 初始化input_dev 结构体

2.7.设置设备支持的事件类型

input_set_abs_params(ts->input_dev,ABS_MT_POSITION_X, 0, ts_x_max_value, 0, 0);

input_set_abs_params(ts->input_dev,ABS_MT_POSITION_Y, 0, ts_y_max_value, 0, 0);

input_set_abs_params(ts->input_dev,ABS_MT_TOUCH_MAJOR, 0, 8, 0, 0);

ABS_MT_POSITION_X等中表示多点触控协议的事件类型

2.8 注册input系统

在 Probe方式下(input系统外添加字符驱动的位置在probe使用input_register_device函数中,注销字符驱动的位置的remove中).   Linux input 字符设备的注册是在evdev_connect 函数中实现的,使用的是cdev_add 函数,字符设备的删除是在evdev_cleanup函数中实现的。xxx_fops在cdev_init(&xxx_dev.cdev, &xxx_fops)的语句中被建立与cdev的连接。

2.9 申请中断request_irq

if(request_irq(GPIO_TO_IRQ(ts_gpio_irq_pin), focaltech_ft5306_irq_handler,

IRQF_TRIGGER_FALLING,client->name, ts) >= 0) {

printk("RequestedIRQ\n");

ts->use_irq= 1;

printk(KERN_INFO"GPIO_%d INT: %d", ts_gpio_irq_pin,

GPIO_TO_IRQ(ts_gpio_irq_pin));

/*if((ret = set_irq_wake(client->irq, 1)) < 0) {

printk(KERN_ERR"failed to set IRQ wake: %d\n", ret);

}*/

}

2.10 实现睡眠唤醒机制

#ifdefCONFIG_HAS_EARLYSUSPEND

ts->early_suspend.level= EARLY_SUSPEND_LEVEL_BLANK_SCREEN;

ts->early_suspend.suspend= focaltech_ft5306_early_suspend;

ts->early_suspend.resume= focaltech_ft5306_late_resume;

register_early_suspend(&ts->early_suspend);

3 重点分析

3.1中断下半部工作队列软件实现:

focaltech_ft5306_irq_handler中断处理函数

focaltech_ft5306_work_func  中断处理后半部函数

l 声明工作队列结构体:static struct workqueue_struct *synaptics_wq;

l 初始化创建工作队列:

synaptics_wq =create_singlethread_workqueue("synaptics_wq");

if (!synaptics_wq) {

printk(KERN_ERR"Could not create work queue synaptics_wq: no memory");

return -ENOMEM;

l 在工作队列中添加一个工作:

INIT_WORK(&ts->work, focaltech_ft5306_work_func);

// focaltech_ft5306_work_func为处理函数,ts->work(ts为触摸屏结构体synaptics_rmi4)

focaltech_ft5306_work_func为使用container_of实现data指针的传递。

l probe函数中使用request_irq申请中断,绑定中断处理函数focaltech_ft5306_irq_handler

l 安排任务进工作队列:中断处理函数focaltech_ft5306_irq_handler中,queue_work(synaptics_wq,&ts->work);

l focaltech_ft5306_work_func函数中实现数据的上报等

l 工作队列的销毁focaltech_ft5306_exit中,

if (synaptics_wq)

destroy_workqueue(synaptics_wq);

3.2通过I2C数据读取

协议要求

l 从I2C从设备读取数据时,应先调用i2c_master_recv()发送I2C从设备的寄存器地址(I2C从设备的寄存器地址独立于 CPU 内存地址空间,因此不需要做 ioremap()映射),再调用i2c_master_send()读取数据。

l I2C 总线控制器从 I2C 从设备读取数据,只需要调用i2c_master_send(),buf[0]是 I2C 从设备的寄存器地址。

Ft306中I2C接口使用:ft520x_i2c_rxdataft520x_i2c_txdata

l  调用关系:focaltech_ft5306_work_func->fts_ctpm_get_touch_info –>ft520x_i2c_rxdata-> i2c_transfer (相当于调用i2c_master_send,因为ft520x_i2c_rxdata做了部分初始化)

l  数据封装:

i2c发送或者接收一次数据都以数据包 structi2c_msg封装
struct i2c_msg { 
    __u16 addr;     // 从机地址 
    __u16 flags;    // 标志 
#define I2C_M_TEN   0x0010  // 十位地址标志 
#define I2C_M_RD    0x0001  // 接收数据标志 
    __u16 len;      // 数据长度 
    __u8 *buf;      // 数据指针 
}; 
其中addr为从机地址;flags则是这次通信的标志,发送数据为0,接收数据则为 I2C_M_RD;len为此次通信的数据字节数;buf 为发送或接收数据的指针。在设备驱动中我们通常调用 i2c-core 定义的接口 i2c_master_send 和 i2c_master_recv 来发送或接收一次数据。

i2c_transfer(client->adapter,msgs, 2);  // 这里 num = 2,通信成功 ret = 2

使用i2c_transfer接口读取数据时,返回的data中,data[0]为寄存器的地址,data[1]以后才是读取的有效数据。

3.3 linux内核多点触控协议

3.4 触摸数据解析上报分析

3.5 dts设备树

focaltech(敦泰)触摸屏驱动Ft5306.c学习记录相关推荐

  1. RK3399 focaltech敦泰触摸屏移植调试

    CPU:RK3399 系统:Android 7.1 IC:FT5406 focaltech(敦泰)触摸屏也是比较常用的,但是相对汇顶,就比较少用 RK的源码中虽然有 focaltech 的代码,但没有 ...

  2. [RK3399][Android7.1]触摸屏TP,敦泰FT5436驱动移植

    最近在RK3399上移植了敦泰的FT5436触摸屏驱动,分享出来供大家参考. 找敦泰厂家索取FT5436的驱动包,驱动包名称:focaltech_touch 没有什么需要特别注意的地方,按照驱动包里面 ...

  3. linux 触摸屏驱动中断下半部实现-工作队列

    工作队列(work queue)是Linux kernel中将工作推后执行的一种机制.这种机制和BH或Tasklets不同之处在于工作队列是把推后的工作交由一个内核线程去执行,因此工作队列的优势就在于 ...

  4. 移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植

    移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植的过程记录下来: (1)首先打一个补丁:s3c2410_touchscreen.patch, 在内核解压的根目录下 patch -N ...

  5. Linux驱动开发学习笔记-电容触摸屏驱动

    <电容触摸屏驱动框架> 电容触摸屏驱动其实是以下几种 linux 驱动框架的组合: ① IIC 设备驱动,因为电容触摸 IC 基本都是 IIC 接口的,因此大框架就是 IIC 设备驱动. ...

  6. cypress离线安装_新思、敦泰、汇顶/赛普拉斯触控ICD万能脱机烧录测试工具TP-TEST...

    触摸屏脱机烧测工具TP-TESTER产品介绍TP-TESTER是深圳康协利http://www.comshare-sz.com(Comshare)针对触摸屏行业而研发的一款通用型触摸屏生产测试设备.相 ...

  7. STM32MP157驱动开发——多点电容触摸屏驱动

    STM32MP157驱动开发--多点电容触摸屏驱动 一.简介 二.电容触摸屏驱动框架简介 多点触摸(MT)协议详解 三.驱动开发 1.添加 FT5426 设备节点 2.FT5426 节点配置 3.驱动 ...

  8. WINCE6.0+S3C6410的触摸屏驱动

    ********************************LoongEmbedded******************************** 作者:LoongEmbedded(kandi ...

  9. linux rs232触摸屏驱动程序,Linux下的触摸屏驱动

    一.触摸屏理论概述 对于触摸屏驱动,我们主要需要掌握触摸屏驱动代码和应用层测试代码.下面讲的是基于Mini2440的触摸屏驱动,现在的驱动我们都将设备和驱动分离,挂在平台设备总线上,让设备和驱动去匹配 ...

最新文章

  1. AAAI 2021 最「严」一届发榜,1692 篇论文中选,录取率仅为 21%
  2. 用java程序编写ip仿真器_用java 编写一个可以实现IP地址查询功能的课程设计
  3. 【Linux 内核】调度器 ⑤ ( put_prev_task、set_next_task 函数 | select_task_rq 函数 | migrate_task_rq 函数 )
  4. 批处理启动和关闭VMware
  5. Vue入门:Vue项目创建及启动
  6. 客户细分_客户细分:K-Means聚类和A / B测试
  7. onresize的应用--自适应弹窗
  8. 深度学习Dubbo系列(入门开篇)
  9. Wine DLL库安装工具winetricks
  10. 华三 h3c 基于IP子网的vlan
  11. 什么情况下使用weak关键字,相比assign有什么不同
  12. 端口(port)详解
  13. 如何使用计算机管理员账户密码是什么意思,电脑管理员密码是什么
  14. CF 1467 C. Three Bags
  15. error: expected unqualified-id before 'xxx'
  16. java中sof是什么意思_SOF是什么意思
  17. java 泰勒级数_使用rSymPy计算泰勒级数
  18. 加班多?交友范围窄?单身互联网人点进来!
  19. 国产机们的高端梦:OV保守、米耀激进
  20. 计算机原理与应用 第二章——ARM处理器

热门文章

  1. 坑爹!攻城狮老爸被苹果解雇 只因女儿晒iPhone X
  2. 【转】珍藏多年的素材,灵感搜寻网站
  3. Adobe Dreamweaver 默认快捷键 集锦
  4. Ubuntu清理系统垃圾 命令
  5. 利用Javascript制作宾果(BINGO)游戏
  6. mdx格式mysql_Saiku_学习_02_Schema Workbench 开发mdx和模式文件
  7. android代码图片编辑,怎样修改android系统apk软件里面的代码和图片?
  8. 数据分析六个步骤,一款BI工具即可全部完成
  9. 传递函数的幅值计算公式_设积分环节的传递函数为G(s)=1/s ,则其频率特性幅值M(ω)=( )...
  10. python下标越界怎么解决_Python异常处理