iTOP-i.MX6ULL开发板Linux下电容触摸屏驱动框架-多点触摸协议详解

电容触摸屏驱动其实就是一下几种 linux 驱动框架的组合:

① IIC 设备驱动,因为电容触摸 IC 基本都是 IIC 接口的,因此大框架就是 IIC 设备驱动。

② 通过中断引脚(INT)向 linux 内核上报触摸信息,因此需要用到 linux 中断驱动框架。坐标的上报在中断服务函数中完成。

③ 触摸屏的坐标信息、屏幕按下和抬起信息都属于 linux 的 input 子系统,因此向 linux 内核上报触摸屏坐标信息就得使用 input 子系统。只是,我们得按照 linux 内核规定的规则来上报坐标信息。

在上面的驱动框架组合中我们发现 I2C 驱动、中断驱动、input 子系统都已经学习了解过了,还没有

学习过 input 子系统下的多点电容触摸协议,这个就是本章学习的重点,linux 内核中有一份文档详细的讲

解了多点电容触摸屏协议,文档路径为:Documentation/input/multitouch-protocol.txt

MT 协议被分为两种类型,TypeA 和 TypeB,这两种类型的区别如下:

TypeA:适用于触摸点不能被区分或者追踪,此类型的设备上报原始数据(此类型在实际使用中非常少!)。

Type B:适用于有硬件追踪并能区分触摸点的触摸设备,此类型设备通过 slot 更新某一个触摸点的信息,FT5426 就属于此类型,一般的多点电容触摸屏 IC 都有此能力。

触摸点的信息通过一系列的 ABS_MT 事件(有的资料也叫消息)上报给 linux 内核,只有 ABS_MT 事件是用于多点触摸的,ABS_MT 事件定义在文件 linux/input.h 中,相关事件如下所示:

852 #define ABS_MT_SLOT 0x2f /* MT slot being modified */

853 #define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */

854 #define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */

855 #define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */

856 #define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */

857 #define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */

858 #define ABS_MT_POSITION_X 0x35 /* Center X touch position */

859 #define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */

860 #define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */

861 #define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */

862 #define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */

863 #define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */

864 #define ABS_MT_DISTANCE 0x3b /* Contact hover distance */

865 #define ABS_MT_TOOL_X 0x3c /* Center X tool position */

866 #define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */

在上面这些众多的 ABS_MT 事件中,我们最常用的就是 ABS_MT_SLOT 、 ABS_MT_POSITION_X 、ABS_MT_POSITION_Y 和 ABS_MT_TRACKING_ID 。其中 ABS_MT_POSITION_X 和 ABS_MT_POSITION_Y 用来上报触摸点的 (X,Y) 坐标信息,ABS_MT_SLOT 用来上报触摸点 ID ,对于 Type B 类型的设备,需要用到

ABS_MT_TRACKING_ID 事件来区分触摸点。

对于 TypeA 类型的设备,通过 input_mt_sync()函数来隔离不同的触摸点数据信息,此函数原型如下所示:

void input_mt_sync(struct input_dev *dev)

此函数只要一个参数,类型为 input_dev,用于指定具体的 input_dev 设备。input_mt_sync()函数会触发 SYN_MT_REPORT 事件,此事件会通知接收者获取当前触摸数据,并且准备接收下一个触摸点数据。

对于 Type B 类型的设备,上报触摸点信息的时候需要通过 input_mt_slot()函数区分是哪一个触摸点,

input_mt_slot()函数原型如下所示:

void input_mt_slot(struct input_dev *dev, int slot)

此函数有两个参数,第一个参数是 input_dev 设备,第二个参数 slot 用于指定当前上报的是哪个触摸点信息。input_mt_slot()函数会触发 ABS_MT_SLOT 事件,此事件会告诉接收者当前正在更新的是哪个触摸点(slot)的数据。

不管是哪个类型的设备,最终都要调用 input_sync()函数来标识多点触摸信息传输完成,告诉接收者处理之前累计的所有消息,并且准备好下一次接收。Type B 和 Type A 相比最大的区别就是 Type B 可以区分出触摸点, 因此可以减少发送到用户空间的数据。Type B 使用 slot 协议区分具体的触摸点,slot 需要用到 ABS_MT_TRACKING_ID 消息,这个 ID 需要硬件提供,或者通过原始数据计算出来。对于 TypeA 设备,内核驱动需要一次性将触摸屏上所有的触摸点信息全部上报,每个触摸点的信息在本次上报事件流中的顺序不重要,因为事件的过滤和手指(触摸点)跟踪是在内核空间处理的。

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。

你可能感兴趣的:(linux)