一、移植并测试触摸屏驱动
1.1 下载正确的触摸屏驱动文件并替换掉原来不对的
1.1.1 电容触摸屏的驱动在下面这个位置:
这个驱动到底是内核自带的,还是之前的板卡商,在移植的时候放进去的,对我们来说,不用去关心
总之,我们拿到的源码,是有的,代码就在这里面呢
这个文件,有相应的.o文件,是被编译了
这个文件,没有.o文件,所以,没有被编译
这个,本来是用make menuconfig来进行配置的,但是这里却被直接注释了
并且,这里只能被编译成为一个module了
如果想编译到zImage里面去,那么这里就要修改成:obj-y
其实只有这两个文件是有用到的
这个pad.c是没有用到的
但问题是这个pad.h是有被用到的
其实,大部分东西,都是在这个pad.h里面的
现在输出的情况不对,就是因为pad.h里面,有些变量的定义是不对的
1.1.2 分析不对的源码
首先,是定义了width与height,也就是定义了分辨率,7inch里面,一般最高分辨率就是1280 X 800
这个是不对的,因为咱们的屏幕是1024 X 600的
这是一个数组,用const修饰,是一个不可更改的常量,这里面写了很多寄存器的配置值
这个寄存器非常大,并且有非常多的数值
这里面还有很多固件(的标志),并且,这里面也全是key和value的,并且是成对的
前面的key应该是寄存器的地址,后面的value,应该是寄存器的值
这些是电容触摸屏里面的那些寄存器
每一款电容触摸屏,其实它里面是有自己的处理器的,它那个处理器,就负责处理电容触摸屏内部的寄存器
每一个电容触摸屏都有多达几百个寄存器,这里面的寄存器,都是用来配置一些特性的,比如配置屏幕的分辨率,配置电容感应的灵敏度这些的。
因为按到的点,中心和边缘的力度,还是有区别的,所以做电容触摸屏这一行,也还是有一点技术含量在里面的。
我们现在,就是这些寄存器里面,配的寄存器的值不对
我们现在要修复这个驱动的话,要找到一个正确的.h文件,把这个错误的.h文件给替换了
先把错误的文件,改个名字
找到正确的文件
这个是根据我们的屏幕给配出来的
这个差异,是来自于触摸屏的差异,因为:
一个触摸屏芯片,是不止配置于,一款触摸屏的;这个芯片能够适配于很多屏幕,有些屏幕大,有些屏幕小,有些分辨率大,有些分辨率小。
触摸屏芯片本身的配置,要和我们的屏幕适配,就要去修改寄存器;这个适配的过程,要懂触摸屏芯片的寄存器怎么写;而且,有时候,还要去调一些效果。
并且,这个过程,有用到专门的人,用专门的软件去调,这个一般是触摸屏芯片厂商去调的
这个要找FAE,以及代理商,帮忙调的,自己没必要去学怎么调试,这种技能只能用于调试这个厂商的
如果公司很小,人家的FAE不理你的话,没有实力调这个,那就不要调这个,直接买过来就行了,如果非要自己调试,那么就是自讨苦吃。
1.1.3 把正确的源码复制到Ubuntu
- 先把正确的给复制过来
这个就是我们的正确的
- 然后,编译生成模块
在这里编译生成驱动模块
可以看到,已经被编译了
这里会把所有的配置为-m的那些模块,全部重新编译一遍
Linux里面,如果我们把它集成到内核里面,还不知道能不能编译单个模块,这个是不行的
但是在Android里面,如果想编译单个模块,可以只编译这个模块
如果我们把驱动放在了外面,那我们可以直接在驱动那里去make module
但是,现在我们把驱动是集成到内核里面了,所以,就要编译所有的
- 编译生成了.ko文件
这个文件,也就是我们所需要的
- 然后,把这个ko文件拷贝到板子上面去
其中,这个rootfs文件夹,已经被nfs共享出去了
- 在板子上面找到这个.ko文件
如上图所示
- 先进到.ko文件夹
如上图所示
- 先把老版本的.ko文件mv掉
如上图所示
- 把板子上的.ko文件复制到当前的文件夹
这个ko文件就是我们刚才编译成功的,正确的ko文件了
到这一步,部署就完成了
- 卸载老驱动
remod gslx680.ko
- 装载新的驱动
insmod gslx680.ko
如上命令所示
- 或者简单粗暴地直接重启,重启的话,也会insmod这个驱动的
重启,也就会重新加载驱动了
- 先看看/dev/input/里面有没有设备
- 重新挂载nfs文件系统
- 进入到应用程序文件夹下,并执行应用程序
- 查看效果
可以看到,效果是对的了
但是,调试触摸屏芯片寄存器的过程,应当是触摸屏芯片厂商自己专门做的,而不是我们自己去做
二、触摸屏驱动源码简单分析
2.1 找到并确认实际工作的源码
- 先找到源码在哪
pad_touch_back.c
pad.c:这个没有被调用
touch_id:只包含少量内容
- 分析源码
源码中,最核心的两个源码,就是在这里的
- 来分析:gsl_ts_init
- 有两个分支
一个是Linux里面的驱动
一个是Android里面的驱动
这两个驱动是不太一样的
区别就是:Linux里面只支持单点,Android里面呢支持多点,但是这个芯片本身是支持多点的
Android里面,大部分时候,都是支持多点触控的
Linux里面,大部分时候,都会 使用Qtcreator这样一些GUI,这个时候就不需要多点触控
大部分驱动,也都是一样的
- gsl_ts_init函数分析
在这个函数里面,做的事情主要是这个
- 分析
I2C Device呢,一个触摸屏驱动对我们主机来说,其实就是I2C的从设备
所以:这里就是一个I2C Device,一个I2C Driver
那么I2C Device在什么地方添加了呢?就是在设备树解析的那个地方添加了,给你做了I2C add device了
然后,在这个地方执行了i2c_add_driver了
再然后,driver和device在I2C总线上一match
match之后呢,就probe了
probe之后,就执行我们的驱动了
所以,下一步,其实就到了驱动这里了
- 找到驱动
进入到驱动这里
这里主要是一个probe函数
I2C总线driver和device那边一match,就会调用这个probe
所以,所有的驱动入口函数,就在probe函数这里
这都是非常经典的驱动函数框架
进入到probe函数里面
可以看到,probe函数,其实是先在定义变量
然后,这里先做相关的check
然后将ts进行相关的实例化,分配内存
然后进行填充
然后,在这里面,把各种数据,把Device和Driver里面的那个硬件数据进行挂接
irq_pin:就是我们中断对应的引脚
也就是说,我们的I2C设备,有一个引脚是专门来处理中断的,这是一个硬件信息,是硬件要告诉软件的
也就是Device要告诉Driver的,Driver这边操作irq的时候,只会直接基于irq的pin来直接进行处理,这个是纯软件的,这个只负责直接具体的操作,而不知道是哪个Pin,这个是要device告诉它的,怎么告诉它呢?三种方法:
第一种方法:简单粗暴,这就是直接硬编程,直接编译进去了;缺点就是,如果你要移植,那就必须要修改源码,如果不修改源码,如果不修改源码,这个是完不成的;所以一般正式的代码都不可能这样写的。
第二种方法:老式的做法是:通过I2C Device那里来,进行配置,也就是直接使用数据结构,在代码里面定义数据结构,但是,在数据结构那个地方就需要改;也就是说,还需要改源码。
第三种方法:新式的做法:改设备树,设备树的代码,就在下面:
这里,就是通过设备树来获取具体的Pin
获取touch-gpio的节点,那个节点里面有这样一个属性,属性就是:touch-gpio
获取reset-gpio的节点,那个节点里面有这样一个属性,属性就是:reset-gpio
那么,这个函数在哪里呢?
这就是goodix这家的触摸屏的
这就是gsl680这家的触摸屏的对应的
这里是对应的i2c从地址,对应的0x40
compatible,这个属性是为了让它能够匹配上的
所以可以看到,其实人家在这里,都配好了
但是,在源码里面,是没有用设备树传参的
但是,SDK在做这个的时候,已经基本把这个做好了
看设备树里面的相关属性
这里应该不是800 x 1280,应该是600 x 1024
这里没有修改,没有修改是很正常的,因为都是写死的,因为没有用到设备树,在这里改了,其实也不影响
这两个节点的数值,本来就被配置为4和3
如果在代码里面用这两行,读出来也是4和3
再往下走,这个驱动,其实是和原来的驱动,没啥区别了
但是,这个驱动和以前的相比,差别就在这里
在核心课程一期里面,是没有看到这些寄存器配置值的,因为当时用的是.bin文件,当年,触摸屏厂商为了保持竞争力,是不愿意把这个寄存器的设置值开源的,核心课程一期是15年讲的。
寄存器配置值是不是以文本的方式给客户,这个对我们是没有影响的
用没用到设备树,也是一个比较大的不同
别的驱动,也与这个触摸屏的驱动类似