(Linux内核)多点触控 (MT) 协议(A类、B类)/触摸屏协议【multi-touch-protocol.txt】

翻译自 https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt

多点触控 (MT) 协议

版权所有 © 2009-2010 Henrik Rydberg <rydberg@euromail.se>


介绍

为了充分利用新的多点触控和多用户设备的全部功能,需要一种方式来报告来多个触摸点的详细数据(即与设备表面直接接触的对象)。 本文档描述了多点触控 (MT) 协议,该协议允许内核驱动程序报告任意数量的触摸点的详细信息。

该协议根据硬件的能力分为两种类型。 对于只处理匿名接触点(A 类)的设备,协议描述了如何将所有触点的原始数据发送给接收方。 对于能够跟踪并识别接触点(B 类)的设备,该协议描述了如何通过事件槽(slot)发送单个触点的更新给接收方。


协议使用

触点的详细信息分割为多个 ABS_MT 事件的数据包按顺序发送, 只有 ABS_MT 事件被识别为触控点数据包的一部分。 由于当前的单点触控 (ST) 应用程序忽略了这些事件,因此可以在现有驱动程序中的 ST 协议之上实现 MT 协议。

A 类设备的驱动程序通过在每个数据包末尾调用 input_mt_sync() 来分隔触控点数据包。 这会生成一个 SYN_MT_REPORT 事件,该事件指示接收方接受当前触控点数据并准备接收另一个触控点数据。

B 型设备的驱动程序通过在每个数据包的开头调用 input_mt_slot() 来分隔联系数据包,并以 slot作为参数。 这会生成一个 ABS_MT_SLOT 事件,该事件指示接收方准备更新给定的slot信息。

两类驱动程序都通过调用通常的 input_sync() 函数来标记多点触控传输的结束。 这指示接收方对自上次 EV_SYN/SYN_REPORT 以来累积的事件做出响应,并准备接收一组新的事件/数据包。

无状态 A 类协议和有状态 B 类槽协议的主要区别在于使用可识别触控点来减少发送到用户空间的数据量。 slot 协议需要使用 ABS_MT_TRACKING_ID,它由硬件提供或从原始数据计算[^5]。

对于 A 类设备,内核驱动程序会对当前触摸屏的所有触控点的进行枚举并生成触控点数据包。 数据包出现在事件流中的顺序并不重要。 事件过滤和手指跟踪留给用户空间实现。

对于 B 类设备,内核驱动程序会将一个slot信息与每个识别的触控点相关联,并使用该slot信息来传播该触控点的状态更改。 通过修改关联的slot信息ABS_MT_TRACKING_ID 来实现触点的创建、替换和销毁。一个非负的可跟踪 id 被解释为一个触控点,值为 -1 则表示不使用的slot信息。 之前没出现的可跟踪 id 应该视为新的,不再出现的可跟踪 id 应该视为已被删除。 因为只传递更改的部分,所以每个出现过的触控点的完整状态必须保留在接收端,收到 MT 事件后,只需更新当前slot信息的对应属性。

有些设备能识别和(或)跟踪的接触点数量比它能报告给驱动程序的数量更多,此类设备的驱动程序应将每一个硬件报告的触控点与一个B类设备的slot信息相关联。当已经关联了slot信息的触控点发生变化时,驱动程序应更改其ABS_MT_TRACKING_ID 的值使该slot信息无效,如果硬件发出信号表明它正在跟踪的触控点比当前报告的要多,则驱动程序应使用 BTN_TOOL_*TAP 事件来通知用户空间当前硬件正在跟踪的触控点总数。要完成这个操作,驱动程序应通过显式发送相应的 BTN_TOOL_*TAP 事件并在调用 input_mt_report_pointer_emulation() 时将 use_count 设置为 false 。驱动程序应该只通告硬件所报告的所有slot信息。用户空间可以通过留意 “最大支持的 BTN_TOOL_*TAP 事件” 是否大于 “ABS_MT_SLOT 绝对坐标信息中报告的 B 类slot信息的总数” 来检测驱动程序可以报告的总点数是否多于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 将被输入核心丢弃,导致没有零接触事件(zero-contact event )到达用户空间。


协议示例 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 方向移动触点(id为45)后的序列:

ABS_MT_SLOT 0
ABS_MT_POSITION_X x[0]
SYN_REPORT

以下是解除ABS_MT_SLOT 为 0 的触点后的顺序:

ABS_MT_TRACKING_ID -1
SYN_REPORT

被修改的slot已经是0,所以省略了ABS_MT_SLOT。 该消息删除了slot 0 与触点(id为45)的关联,从而破坏了触点(id为45), 并释放slot 0 以重新用于另一个触摸点。

最后,这是解除第二次接触后的顺序:

ABS_MT_SLOT 1
ABS_MT_TRACKING_ID -1
SYN_REPORT

事件使用

定义了一组具有所需属性的 ABS_MT 事件。 事件被分为几类,以允许部分实现。 最小集由 ABS_MT_POSITION_XABS_MT_POSITION_Y 组成,允许跟踪多个触摸点。 如果设备支持,ABS_MT_TOUCH_MAJORABS_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的比值总是小于unity,与接触压力有关。对于基于压力的设备,ABS_MT_PRESSURE 可用于提供接触区域的压力。能够接触悬停的设备可以使用 ABS_MT_DISTANCE 来指示接触和表面之间的距离。

	  Linux MT                               Win8
         __________                     _______________________
        /          \                   |                       |
       /            \                  |                       |
      /     ____     \                 |                       |
     /     /    \     \                |                       |
     \     \  a  \     \               |       a               |
      \     \____/      \              |                       |
       \                 \             |                       |
        \        b        \            |           b           |
         \                 \           |                       |
          \                 \          |                       |
           \                 \         |                       |
            \                /         |                       |
             \              /          |                       |
              \            /           |                       |
               \__________/            |_______________________|

除了 MAJOR 参数外,触摸和手指区域的椭圆形状可以通过添加 MINOR 参数来描述,使得 MAJOR 和 MINOR 是椭圆的长轴和短轴。 触摸椭圆的方向可以用 ORIENTATION 参数描述,手指椭圆的方向由向量 (a - b) 给出。

对于 A 类设备,可以通过 ABS_MT_BLOB_ID 进一步指定触摸形状。

ABS_MT_TOOL_TYPE 可用于指定触摸工具是手指还是笔或其他东西。 最后,ABS_MT_TRACKING_ID 事件可用于随时间跟踪识别的联系人。

在type B协议中,ABS_MT_TOOL_TYPE和ABS_MT_TRACKING_ID由input core隐式处理; 驱动程序应改为调用 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
接触工具主轴的长度,以表面为单位。 这应该理解为工具本身的大小。 假定接触和接近工具的方向相同[4]。

ABS_MT_WIDTH_MINOR
接触工具的短轴的长度,以表面为单位。 如果是圆形,则省略。

上述四个值可用于获取有关触摸点的附加信息。 比率 ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR 近似于压力的概念。 手和手掌的手指都有不同的特征宽度。

ABS_MT_PRESSURE
接触面积上的压力,以任意单位表示。 对于基于压力的设备或任何具有空间信号强度分布的设备,可以使用它来代替 TOUCH 和 WIDTH。

ABS_MT_DISTANCE
接触点和曲面之间的距离(以表面为单位)。 零距离意味着触点正在接触表面。 正数表示触点悬停在表面上方。

ABS_MT_ORIENTATION
接触点椭圆的方向。该值应描述围绕触摸中心顺时针旋转的有符号四分之一。带符号的值范围是任意的,但是对于与曲面的 Y 轴对齐的椭圆应该返回零,当椭圆向左旋转时返回负值,当椭圆向右旋转时返回正值。当与 X 轴完全对齐时,应返回最大范围。
默认情况下,触摸点椭圆是对称的。对于能够真正 360 度定向的设备,报告的方向必须超过最大范围以指示超过四分之一转。对于倒置的手指,应该返回 range max * 2。
如果触摸区域是圆形的,或者内核驱动程序中没有该信息,则可以省略方向。如果设备可以区分两个轴,但不能(唯一)介于两者之间的任何值,则可以支持部分方向。在这种情况下,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 坐标。 如果设备无法区分预期的接触点和工具本身,则省略。

这四个位置值可用于将触摸位置与工具位置分开。 如果两个位置都存在,则主工具轴指向接触点 [1]。 否则,工具轴与触摸轴对齐。

BS_MT_TOOL_TYPE
接近工具的类型。许多内核驱动程序无法区分不同的工具类型,例如手指或笔。在这种情况下,应省略该事件。该协议目前支持 MT_TOOL_FINGER、MT_TOOL_PEN 和 MT_TOOL_PALM [2]。对于 B 类设备,此事件由输入内核处理;驱动程序应改为使用 input_mt_report_slot_state()。
触摸点的 ABS_MT_TOOL_TYPE 可能会随着时间的推移而改变,但仍会触摸设备,因为固件可能无法在首次出现时确定正在使用的工具。

ABS_MT_BLOB_ID
BLOB_ID 将多个数据包组合成一个任意形状的触摸点。点序列形成定义接触形状的多边形。这是 A 类设备的低级匿名分组,不应与高级 trackingID 混淆。大多数 A 类设备没有 blob 功能,因此驱动程序可以安全地忽略此事件。

BS_MT_TRACKING_ID
TRACKING_ID 在其整个生命周期中标识发起的联系。 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) 的手指。

对于同时具有 T 和 C 坐标的 win8 设备,位置映射为

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,是一个欧几里得二分匹配问题。 在每次事件同步时,实际联系人集合与来自先前同步的联系人集合匹配。 完整的实现可以在 [3] 中找到。

手势

在创建手势事件的具体应用中,TOUCH 和 WIDTH 参数可用于例如近似手指压力或区分食指和拇指。 通过添加 MINOR 参数,还可以区分扫过的手指和指向的手指,并且通过 ORIENTATION,可以检测到手指的扭曲。

笔记

为了与现有应用程序保持兼容,手指数据包中报告的数据不得被识别为单点触摸事件。
对于 A 类设备,所有手指数据都会绕过输入过滤,因为相同类型的后续事件涉及不同的手指。
例如使用 A 类协议,请参阅 bcm5974 驱动程序。 例如使用 B 类协议,请参阅 hid-egalax 驱动程序。


[1] 此外,差异 (TOOL_X - POSITION_X) 可用于模拟倾斜。
[2] 该列表当然可以扩展。
[3] mtdev 项目:http://bitmath.org/code/mtdev/。
[4] 参见事件计算部分。
[5] 参见手指追踪部分。

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值