Copyright: |copy| 2009-2010 Henrik Rydberg rydberg@euromail.se
此文章为个人翻译英文文档的产物,仅当做个人笔记使用,不喜勿喷!!
对于翻译内容有强迫症的读者请勿阅读此文档!!
阅读过程中如有不恰当之处欢迎交流指正~~
如需转载,请注明出处!
介绍
为了能够使用多点触控和多用户设备的全部功能,需要一种从各类触控设备报告详细数据的方法,例如:设备表面直接接触设备。本文描述的多点触控(MT)协议用于内核驱动报告任意数量触点的详细信息。
本协议依据硬件的功能分为两种类型。对于处理匿名触点(类型A)的设备,本协议描述如何发送所有触点的原始数据给接收者。对于能够跟踪区分触点(类型B)的设备,本协议描述了如何通过事件slot发送各个触点的更新。
注意:MT协议类型A已经被淘汰了,所有内核驱动都被转换到使用类型B。
协议使用
触点的详细信息作为ABS_MT事件的单独数据包顺序发送。只有ABS_MT事件被认为是触点包的一部分。因为这些事件会被当前的单点触控(ST)应用忽略,MT协议可以在存在于现有驱动中的ST协议上实现。
类型A设备的驱动通过在每个数据包的结尾调用input_mt_sync()实现分离触点数据包。这将会产生一个SYN_MT_REPORT事件,从而通知接收者接收当前触点信息,同时准备接收另一个触点信息。
类型B设备的驱动通过在每个数据包的开头以slot为参数调用input_mt_slot()来分离触点数据包。这会产生一个ABS_MT_SLOT事件,从而通知接收者准备所给的slot的更新。
所有驱动都调用通用input_sync()函数来标记多点触控转换结束。这会通知接收者执行自上次EV_SYNC/SYN_REPORT后累计的大量事件,同时准备接收新的事件和数据包。
无状态的类型A协议和有状态的类型B插槽协议之间的主要区别在于使用可识别的触点来减少发送到用户空间的数据量。使用slot协议需要有ABS_MT_TRACKING_ID,这个由硬件提供或从原始数据中计算得到[#f5]_。
对于类型A设备,内核驱动需要产生当前面板上的所有触点,数据包出现在事件流中的顺序是不重要的。事件过滤和手指追踪都流给用户空间去做[#f3_]。
对于类型B设备,内核驱动需要将每个识别的触点与一个slot关联,利用这个slot来传递对应触点的变化。触点的创建、替换和销毁是通过修改相关联slot的ABS_MT_TRACTKING_ID完成的。一个无符号的追踪id代表一个触点,值-1表示一个未使用的slot。一个未出现的过的追踪id被认为是新的,而一个不在出现的追踪id考虑被移除。因为只传递了变化的信息,每个触点的全部信息需要保存在接收端。当接收到MT事件时,简单地更新当前slot的对应属性。
一些设备识别并/或追踪的触点多于他们能够报告给驱动的数量。这种设备的驱动需要将硬件上报的每一个触点与一个类型B的slot相关联。一旦与一个slot关联的触点的识别发生改变,驱动需要改变它的ABS_MT_TRACKING_ID使这个slot作废。如果硬件表明当前追踪的点比上报的点多,驱动需要使用BTN_TOOL_*TAP事件来告诉用户空间当前硬件追踪的总触点数量。驱动在调用input_mt_report_pointer_emulation()时需要明确地发送相应的BTN_TOOL_*TAP事件,同时设置use_count为false。驱动程序应该只上报硬件和硬件能够报告一样多的slot。用户空间可以检测出驱动可以报告比slot更多的总触点,通过指出最大支持的BTN_TOOL_ * TAP事件大于ABS_MT_SLOT轴的absinfo中报告的类型B的slot数量。
ABS_MT_SLOT轴的最小值必须为0。
协议例子A
以下是类型A设备中两点触控最小事件顺序:
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会被输入内核放弃,从而导致没有空触事件到达用户层。
协议例子B
以下是类型B设备的两指触控最小事件顺序:
ABS_MT_SLOT 0
ABS_MT_TRACKING_ID 45
ABS_MT_POSITION_X x[0]
ABS_MT_POSITION_Y y[0]
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID 46
ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1]
SYN_REPORT
以下是在X方向上移动触点45后的顺序:
ABS_MT_SLOT 0
ABS_MT_POSITION_X x[0]
SYN_REPORT
以下是slot 0中触点离开后的顺序:
ABS_MT_TRACKING_ID -1
SYN_REPORT
由于slot被修改为0,因此这个ABS_MT_SLOT被忽略。这条信息移除了slot 0和触点45的联系,因此销毁触点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)给出。
对于A型设备,可以通过ABS_MT_BLOB_ID进一步指定触摸形状。
ABS_MT_TOOL_TYPE可以用于区分接触工具是手指、笔或者其他工具。最后,ABS_MT_TRACKING_ID事件可以用于跟踪一段时间内已识别的触点[#f5]_。
事件含义
ABS_MT_TOUCH_MAJOR
触点主轴长度。该长度需要以表面单位给出。如果表面的分辨率是X的Y倍,则ABS_MT_TOUCH_MAJOR的最大可能值为sqrt(X ^ 2 + Y ^ 2),即对角线[#f4]_。
ABS_MT_TOUCH_MINOR
触点的短轴长度,单位为表面单位。如果触点是元,该事件可以被忽略。
ABS_MT_WIDTH_MAJOR
接触工具的长轴长度,单位为表面单位。这要被理解为工具自身的尺寸。触点和接触工具的方向假定是一样的[#f4]_。
ABS_MT_WIDTH_MINOR
接触工具的长轴短度,单位为表面单位。如果为圆形忽略[#f4]_。
以上四个值可用于导出触点的其他信息。 比率ABS_MT_TOUCH_MAJOR / BS_MT_WIDTH_MAJOR近似于压力的概念。 手的手指和手掌都有不同的特征宽度。
ABS_MT_PRESSURE
接触区域上的压力(以任意单位表示)。 对于基于压力的设备或任何具有空间信号强度分布的设备,可以代替TOUCH和WIDTH使用。
ABS_MT_ORIENTATION
接触椭圆的方向。该值应描述围绕触摸中心顺时针旋转的四分之一圈。有符号的值范围是任意的,但对于与曲面的Y轴(北)对齐的椭圆,应返回零;当将椭圆向左旋转时,应返回负值;当将椭圆向右旋转时,则应返回正值。当在正方向上与X轴对齐时,应返回最大范围; 当与X轴在负方向上对齐时,应返回-max范围。
默认情况下,触摸椭圆是对称的。 对于具有真正360度方位角的设备,报告的方位角必须超出最大范围,以表示超过四分之一圈。 对于倒置的手指,应返回最大* 2的范围。
如果接触区域是圆形或者在内核驱动中没有有效信息,方向可以被忽略。如果设备可以区分两个轴,但不能(唯一地)区分两个轴,则可以进行部分定向。在这种情况下,ABS_MT_ORIENTATION的取值范围为[0, 1][#f4]_。
ABS_MT_POSITION_X
接触椭圆中心表面X坐标。
ABS_MT_POSITION_Y
接触椭圆中心表面Y坐标。
ABS_MT_TOOL_X
接触工具的中心表面X坐标。如果设备不能区分想要的触点和工具本身,则可以忽略。
ABS_MT_TOOL_Y
接触工具的中心表面Y坐标。如果设备不能区分想要的触点和工具本身,则可以忽略。
以上四个位置值可用于将触摸位置与工具位置分开。如果两个位置都存在,则主工具轴指向接触点[#f1]_,否则,工具轴与触摸轴对其。
ABS_MT_TOOL_TYPE
接触工具类型。很多内核驱动不能分辨不同的工具类型,例如手指或笔。在这种情况下,该事件应该被忽略。协议当前主要支持MT_TOOL_FINGER,MT_TOOL_PEN和 MT_TOOL_PALM[#f2]_.
对于类型B设备,该事件由输入内核处理;驱动程序应该改用input_mt_report_slot_state()。一个触点的ABS_MT_TOOL_TYPE在一直触摸设备时可能发生改变,因为当工具首次出现时固件不能够确定正在使用哪个工具。
ABS_MT_BLOB_ID
BLOB_ID将几个数据包组合在一起,形成一个任意形状的触点。点序列形成定义接触形状的多边形。这是用于类型A设备的低级别匿名分组,不应与高级TrackingID 混淆[#f5] _。大部分的类型A设备没有这个blob功能,所以驱动可以安全地忽略这个事件。
ABS_MT_TRACKING_ID
TRACKING_ID识别一个触点并贯穿它的生命周期[#f5]_。TRACKING_ID的值范围应足够大,以确保在长时间内能唯一标识触点。 对于类型B的设备,此事件由输入内核处理;驱动程序应该改用input_mt_report_slot_state()。
事件计算
不同硬件的多样性不可避免地导致某些设备比其他设备更适合MT协议。 为了简化和统一映射,本节提供了如何计算某些事件的方法。
对于将触点报告为矩形的设备,无法获得带符号的方向。 假设X和Y是矩形矩形的边长,这是一个简单的公式,可以保留尽可能多的信息:
ABS_MT_TOUCH_MAJOR := max(X, Y)
ABS_MT_TOUCH_MINOR := min(X, Y)
ABS_MT_ORIENTATION := bool(X > Y)
ABS_MT_ORIENTATION的范围被设置为[0, 1],用于表示设备可以分辨手指沿着Y轴(0)和手指沿着X轴(1)。
对于Win8设备具有T和C坐标,位置映射为:
ABS_MT_POSITION_X := T_X
ABS_MT_POSITION_Y := T_Y
ABS_MT_TOOL_X := C_X
ABS_MT_TOOL_Y := C_Y
不幸的是,没有足够的信息去确定是触摸椭圆还是工具椭圆,因此必须采用近似值。 一种与早期用法兼容的简单方案是:
ABS_MT_TOUCH_MAJOR := min(X, Y)
ABS_MT_TOUCH_MINOR := <not used>
ABS_MT_ORIENTATION := <not used>
ABS_MT_WIDTH_MAJOR := min(X, Y) + distance(T, C)
ABS_MT_WIDTH_MINOR := min(X, Y)
原理:我们没有关于触摸椭圆的方向的信息,因此可以使用内接圆来近似它。 工具椭圆应与向量(T-C)对齐,因此直径必须随距离(T,C)增大。 最后,假设接触直径等于工具厚度,我们得出上面的公式。
## 手指跟踪
手指跟踪的过程,即为表面上的每个已启动接触分配唯一的trackingID,是欧几里得两部分匹配问题。在每个事件同步中,实际触点集与来自先前同步的触点集匹配。 完整的实现可以在下面找到[#f3]_。
## 手势
在创建手势事件的特定应用中,TOUCH和WIDTH参数可用于例如估计手指压力或区分食指和拇指。通过添加MINOR参数,您还可以区分手指是扫动手指还是手指,并且通过ORIENTATION,可以检测手指的扭曲。
注意
为了与已存在的应用保持兼容,手指数据包中报告的数据不得被识别为单点触摸事件。
对于类型A设备,所有手指数据都绕过输入过滤,因为相同类型的后续事件引用了不同的手指。
注释
- [#f1] 此外,(TOOL_X - POSITION_X)差值可用于模型倾斜。
- [#f2] 该列表当然可以扩展。
- [#f3] mtev项目:http://bitmath.org/code/mtdev/
- [#f4] 参考事件计算部分。
- [#f5] 参考手指跟踪部分
转载自原文链接, 如需删除请联系管理员。
原文链接:多点触控(MT)协议,转载请注明来源!