一、 多点触摸协议(MT)
input子系统下的多点触摸协议称为MT协议,其文档为:Documentation/input/multitouch-protocol.txt。
MT协议被分为两种类型,取决于硬件的兼容性:
- Type A:适用于触摸点不能被区分或者追踪,此类型的设备上报原始数据
- Type B:适用于有硬件追踪并能区分触摸点的触摸设备,此类型设备都通过slot更新某一个触摸点的信息
触摸点的信息通过一系列的ABS_MT事件上报给Linux内核,定义在文件include/uapi/linux/input.h
中:
#define ABS_MT_SLOT0x2f/* MT slot being modified */#define ABS_MT_TOUCH_MAJOR0x30/* Major axis of touching ellipse */#define ABS_MT_TOUCH_MINOR0x31/* Minor axis (omit if circular) */#define ABS_MT_WIDTH_MAJOR0x32/* Major axis of approaching ellipse */#define ABS_MT_WIDTH_MINOR0x33/* Minor axis (omit if circular) */#define ABS_MT_ORIENTATION0x34/* Ellipse orientation */#define ABS_MT_POSITION_X0x35/* Center X touch position */#define ABS_MT_POSITION_Y0x36/* Center Y touch position */#define ABS_MT_TOOL_TYPE0x37/* Type of touching device */#define ABS_MT_BLOB_ID0x38/* Group a set of packets as a blob */#define ABS_MT_TRACKING_ID0x39/* Unique ID of initiated contact */#define ABS_MT_PRESSURE0x3a/* Pressure on contact area */#define ABS_MT_DISTANCE0x3b/* Contact hover distance */#define ABS_MT_TOOL_X0x3c/* Center X tool position */#define ABS_MT_TOOL_Y0x3d/* Center Y tool position */
其中最常用的是:
- ABS_MT_SLOT:用来上报触摸点ID
- ABS_MT_POSITION_X和ABS_MT_POSITION_Y:用来上报触摸点的 (X, Y) 坐标信息
- ABS_MT_TRACKING_ID:对于Type B类型的设备,需要用该事件来区分触摸点
二、FT5426触摸芯片
FT5x06系列是单芯片电容触摸板控制器IC,内部带有一个8bit的MCU,支持2.8’‘到8.9’‘的触摸屏,区别如下:
其内部框图如下:
与主控制器的连接示意图如下:
串行接口支持I2C(最大400KHz)和SPI,I2C的通信格式如下:
本文使用的是正点原子7’’RGB屏幕,分辨率1024*600,触摸屏及其驱动IC集成在屏幕上,通过FPC排线与imx6ull开发板相连:
imx6ull底板的排线连接情况如下:
可以看出:触摸屏IC接在I2C2接口上,RST复位引脚接在SNVS_TAMPER9这个引脚上,中断引脚接在GPIO1_IO09上。
三、使用内核自带的驱动
1. 驱动源码
Linux内核已经集成了很多电容触摸IC的驱动文件,针对FT5426触摸IC,驱动文件为:drivers/input/touchscreen/edt-ft5x06.c。
此驱动源码在正点原子的开发板上不能直接使用,正点原子官方对其进行了修改,修改的地方如下。
(1)edt_ft5x06_i2c_ts_probe_dt 设备树解析函数
增加触摸IC中断引脚使用的gpio:
(2)edt_ft5x06_ts_probe 挂载函数
看上去像是600不是64的倍数,所以选择在驱动里写死:
驱动ic的中断引脚需要设置gpio:
(3)edt_ft5x06_ts_isr 触摸中断处理函数
此函数修改的地方有点多,截取部分:
(4)EDT_RAW_DATA_RETRIES
2. 使能驱动
查看该文件下的makefile:
需要开启该宏来使能驱动,进入menuconfig界面,按/
,搜索该宏定义位置:
按照帮助文档给出,使能该驱动:
配置修改后保存退出,生成新的.config文件,重新编译内核后,将修改同步到开发板配置文件 。
3. 添加设备树节点
需要先屏幕冲突的已有节点,见后面第5节记录的问题。
驱动添加完成后,还需要添加与之匹配的设备树节点,根据兼容性查找对应的绑定文档:
找到绑定文档为:Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt,其中给出的i2c示例节点为:
polytouch: edt-ft5x06@38 {compatible = "edt,edt-ft5406", "edt,edt-ft5x06";reg = <0x38>;pinctrl-names = "default";pinctrl-0 = <&edt_ft5x06_pins>;interrupt-parent = <&gpio2>;interrupts = <5 0>;reset-gpios = <&gpio2 6 1>;wake-gpios = <&gpio4 9 0>;};
根据绑定文档,在开发板的设备树中 i2c2 节点下,添加自己的节点:
polytouch: edt-ft5x06@38 {compatible = "edt,edt-ft5406", "edt,edt-ft5x06";reg = <0x38>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_ft5x06>;interrupt-parent = <&gpio1>;interrupts = <9 0>;reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;};
在pinctrl节点下,添加edt_ft5x06_pins描述:
pinctrl_ft5x06: ft5x06grp {fsl,pins = <MX6UL_PAD_GPIO1_IO09__GPIO1_IO090xF080MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO090x10B0>;};
修改完成,重新编译设备树。
4. 测试
使用新的内核和设备树启动,查看启动日志input子系统相关:
查看input输入设备的节点:
这里我另外还注册了按键为回车键,所以会有三个输入设备,根据启动顺序,触摸屏应该是event1。
查看触摸屏数据:
hexdump /dev/input/event1
执行此命令后,开始点击触摸屏,就会输出数据。如果无数据,则表示驱动有问题。
5. 过程中遇到的问题记录
(1)问题1
分析:GPIO1_IO09引脚已被使用。
解决:
(2)问题2
问题分析:gpio1-09已被申请,肯定是没有屏蔽干净。
问题解决:
四、FT5x06驱动浅析
1. i2c驱动框架
FT5x06的核心是一个i2c设备,所以整个驱动都是基于i2c驱动框架所写:
兼容性如下:
2. 挂载函数的流程
static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){}
(1)复位引脚、中断引脚相关操作
获取设备树节点中的gpio引脚信息:
该函数中会调用gpio子系统,操作上一步拿到的复位引脚,复位ic,实现如下:
接下来申请中断引脚对应的gpio:
(2)I2C设备操作
检测ft5x06版本号:
该函数实现如下:
i2c读写函数封装为edt_ft5x06_ts_readwrite,实现如下:
(3)input子系统操作
(4)注册gpio引脚中断
中断函数为edt_ft5x06_ts_isr,在该函数中完成触摸事件的上报。
(5)注册输入设备