多点触控制协议简介
根据硬件的能力,该协议被分为两种类型。
对于只能处理匿名接触(type A)的设备,该协议描述了如何把所有的原始触摸数据发送给接收者。
对于那些有能力跟踪并识别每个触摸点的设备(type B),该协议描述了如何把每个触摸点的单独更新通过事件slots发送给接受者
协议的使用
对于type A设备的驱动,在每个数据包的结尾用input_mt_sync()对多个触控包进行分割,这将会产生一个SYN_MT_REPORT事件,它通知接收者接受当前的触控信息,并准备接收下一个信息。
对于type B设备的驱动,在每个数据包的开始,通过调用input_mt_slot()进行分割,同时带入一个参数:slot。这会产生一个ABS_MT_SLOT事件,它通知接收者准备更新给定slot的信息。
两种类型的驱动通常都通过调用input_sync()函数来标记一个多点触摸数据传送的结束,这通知接收者对从上一个EV_SYN/SYN_REPORT以来的所有累加事件作出响应,并准备接收新的一组事件/数据包。
type A协议和type B slot协议之间的主要区别是通过识别相同接触点来减低发送到用户空间的数据量。slot协议需要使用到ABS_MT_TRACKING_ID,它要么由硬件来提供,要么通过原始数据进行计算。
对于type A设备,内核驱动应该根据设备表面上全部有效触控进行列举并生成事件。每个触控点数据包在这次事件流中的顺序并不重要。事件过滤和手指跟踪的工作留给用户空间来实现。
对于type B设备,内核驱动应该把每一个识别出的触控点和一个slot相关联,并使用该slot来传播触摸状态的改变。通过修改关联slot的 ABS_MT_TRACKING_ID来达到对触摸点的创建,替换和销毁。一个非负数的跟踪id被解释为有效的触摸,-1则代表一个不再使用的slot。 一个之前没有出现过的跟踪id被认为是一个新的接触点,当一个跟踪id不再出现时则认为该接触点已经被移除。每当接收到一个MT事件,只需对当前slot的相关属性进行一次简单的更新即可。
Protocol Example A
A协议是当有任何一个事件发生变化,把当前存在的数据全部上报一次(就算是和原来值相同的数据也上报)。
对于一个两点触控的触摸信息,type A设备的最小的事件序列看起来就像下面这样:
code value
ABS_MT_POSITION_X x[0]
ABS_MT_POSITION_Y y[0]
SYN_MT_REPORT
ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1]
SYN_MT_REPORT
SYN_REPORT
实际上,在移动其中一个触控点后的上报序列看起来是一样的。所有存在触控点的原始数据被发送,然后在它们之间用SYN_REPORT进行同步。
当第一个接触点离开后,事件序列如下:
ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1]
SYN_MT_REPORT
SYN_REPORT
当第二个接触点离开后,事件序列如下:
SYN_MT_REPORT
SYN_REPORT
假如驱动在ABS_MT事件之外上报一个BTN_TOUCH 或ABS_PRESSURE事件,最后一个SYN_MT_REPORT可以省略掉,否则,最后的SYN_REPORT会被input核心层扔掉,结果就是一个0触控点事件被传到用户空间中。
Protocol Example B
每次事件发生,只报和上一时刻不同的数据。
对于一个两点触控的触摸信息,type B设备的最小的事件序列看起来就像下面这样:
code value
ABS_MT_SLOT 0 表示插槽是0
ABS_MT_TRACKING_ID 45 表示和插槽0关联的ID点是45
ABS_MT_POSITION_X x[0]
ABS_MT_POSITION_Y y[0]
ABS_MT_SLOT 1 表示插槽是1
ABS_MT_TRACKING_ID 46
ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1]
SYN_REPORT
ID 为 45的触控点在x方向移动后的事件序列如下:
ABS_MT_SLOT 0
ABS_MT_POSITION_X x[0] 说明:只报变化数据
SYN_REPORT
slot 0对应的接触点离开后,对应的事件序列如下:
ABS_MT_SLOT 0
ABS_MT_TRACKING_ID -1
SYN_REPORT
上一个被修改的slot也是0,所以ABS_MT_SLOT被省略掉。这一消息移除了接触点45相关联的slot 0,于是接触点45被销毁,slot 0被释放后可以被另一个接触点重用。
最后,第二个接触点离开后的时间序列如下:
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID -1
SYN_REPORT
事件的使用
一组ABS_MT事件集合按需要的特性被定义。这些事件被分成几个组,以便允许只实现其中的一部分。最小的集合由ABS_MT_POSITION_X和 ABS_MT_POSITION_Y组成,用于跟踪多点接触。
如果设备支持,ABS_MT_TOUCH_MAJOR和 ABS_MT_WIDTH_MAJOR用来提供接触面积和对应的接触工具。
TOUCH和WIDTH参数有一个几何解释。想象一下通过一个窗户观察:一个人把一个手指按压在对面的玻璃上,你会看到两个区域,内圈的区域包含了手指实际和玻璃接触的部分,而外圈则是手指的外轮廓。
接触区域(a)就是ABS_MT_POSITION_X/Y,而手指轮廓区域(b) 的中心就是ABS_MT_TOOL_X/Y。
接触区域的直径是ABS_MT_TOUCH_MAJOR,而手指轮廓的直径就是 ABS_MT_WIDTH_MAJOR。
通常,ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR的比值,总是小于1的,它和接触的压力相关。不过对于基于压力的设备,应该改为使用ABS_MT_PRESSURE 来提供接触的压力值。
可以检测悬浮的设备可以使用ABS_MT_DISTANCE来指出离表面的距离。
除了MAJOR参数之外,接触和手指区域的椭圆外形还可以增加一个MINOR参数,MAJOR和MINOR参数相当于椭圆的长轴和短轴。接触区域的椭圆的方向可以用ORIENTATION参数描述,而手指区域的椭圆方向可以通过向量运算(a-b)来获得。
对于type A设备,将来的格式可能会通过ABS_MT_BLOB_ID来描述接触的外形。
ABS_MT_TOOL_TYPE可以用来指出触控工具是手指还是笔或者其它物体。
ABS_MT_TRACKING_ID应该一直用来跟踪被识别的接触点。
在type B协议里,ABS_MT_TOOL_TYPE和ABS_MT_TRACKING_ID被隐藏在input核心层中进行处理,驱动程序应该改为调用input_mt_report_slot_state()。
ABS_MT_TOUCH_MAJOR事件的语义说明
接触区域的长轴的长度。该长度应该按接触表面的单位提供。如果表面的分辨率是X-Y,则ABS_MT_TOUCH_MAJOR可能的最大值是sqrt(X^2 + Y^2),它的对角线。
ABS_MT_TOUCH_MINOR
接触区域短轴的表面单位长度。如果区域是圆形,该事件可以忽略。
ABS_MT_WIDTH_MAJOR
工具轮廓区域长轴的表面单位长度。这应该就是工具本身的大小。接触面和轮廓面的方向被假设是一样的。
ABS_MT_WIDTH_MINOR
工具轮廓区域短轴的表面单位长度,圆形的话可以被忽略。
上述4个值可以被用来推导出接触面的额外信息。
ABS_MT_PRESSURE
接触区域的压力值,可以是任意单位。基于压力的设备应该使用该事件而不是TOUCH和 WIDTH事件。也用于可以报告空间信号强度的设备。
ABS_MT_DISTANCE
接触物到接触表面之间的表面单位距离。距离为0表明已经接触到表面。正值表示接触物悬浮在表面之上。
ABS_MT_ORIENTATION
接触椭圆区域的方向。该值描述了围绕触摸中心做顺时针转动的有符号数。没有限定该数值的范围,但是在椭圆和表面的Y方向对齐时应该返回0值,椭圆往左转时应该返回负值,往右转时应该返回正值。当和X轴完全对齐时,应该返回最大值。
接触的椭圆默认为是对称点。对于可以360度转动的设备,需要报告超出最大范围来指出转动多于1/4圈。对于倒置的手指,应该上报最大范围的两倍。
如果接触面是一个圆形,或者方向信息在内核驱动中不可用,此时方向参数可以被忽略。如果设备可以识别出两个轴方向,有可能只支持部分不连续的方向,在这种情况下,ABS_MT_ORIENTATION的范围应该是[0,1]。
ABS_MT_POSITION_X
接触中心的X坐标。
ABS_MT_POSITION_Y
接触中心的Y坐标 。
ABS_MT_TOOL_X
接触工具轮廓中心的X坐标。如果设备不能区分接触面和工具本身时,可以忽略该事件。
ABS_MT_TOOL_Y
接触工具轮廓中心的Y坐标。如果设备不能区分接触面和工具本身时,可以忽略该事件。
这4个位置值可以用于从触控工具位置中分离实际的接触位置。如果两种位置信息都存在,那么触控工具的长轴指向接触点,否则,工具和接触面的轴互相对齐。
ABS_MT_TOOL_TYPE
接近工具的类型。很多内核驱动程序不能区分不同的触控工具,比如手指和笔。这种情况下,该事件可以被忽略。目前的协议支持MT_TOOL_FINGER 和MT_TOOL_PEN两种类型。对于type B设备,该事件由input核心层处理,驱动应该改为使用input_mt_report_slot_state()来上报。
ABS_MT_BLOB_ID
BLOB_ID事件把几个数据包组合在一起来组成一个任意的接触形状。一些点组成的序列定义了一个多边形的外形。这是一个type A设备的底层匿名数据组合,不应该和上层的跟踪ID相混淆。多数type A设备没有blob功能,所以驱动可以放心地忽略该事件。 ABS_MT_TRACKING_ID
TRACKING_ID识别一个被启动的触控点的整个生命周期。对于type B设备,该事件由input核心层处理,驱动程序应该改为使用input_mt_report_slot_state()来上报该事件。