一、 多点触摸协议(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)注册输入设备