jjzjj

Linux 驱动开发 六十六:多点触控(MT)协议

lqonlylove 2024-01-18 原文

文档路径:Documentation\input\multi-touch-protocol.txt

一、介绍

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

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

注意:MT 协议类型A已过时,所有内核驱动程序都已转换为使用类型 B

二、协议使用

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

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

B 类设备的驱动程序通过调用 input_mt_slot() 在每个包的开头以 slot 作为参数来分离事件包。这将生成一个 ABS_MT_SLOT 事件,该事件指示接收器为给定事件槽的更新做好准备。

所有驱动程序都通过调用常用的 input_sync() 函数来标记多点触摸传输的结束。这指示接收端处理自上一次 EV_SYN/SYN_REPORT 以来累积的事件,并准备接收一组新的事件包。

无状态类型 A 协议和有状态类型 B 事件槽协议之间的主要区别在于使用可识别触摸点来减少发送到用户空间的数据量。事件槽协议需要使用 ABS_MT_TRACKING_ID,它可以由硬件提供,也可以从原始数据 [#f5]_ 中计算。

对于 A 类设备,内核驱动程序应该生成当前在表面上的全部不可跟踪触摸点的任意枚举。数据包在事件流中出现的顺序并不重要。事件过滤和手指跟踪留给用户空间 [#f3]_

对于 B 类设备,内核驱动程序应该将一个事件槽与每个识别的触摸点关联起来,并使用该事件槽传播触摸点的更改。触摸点的创建、替换和销毁是通过修改相关事件槽的 ABS_MT_TRACKING_ID 实现的。非负跟踪id被解释为触摸点,值 -1 表示未使用的槽位。以前不存在的跟踪 id 被认为是新的,不再存在的跟踪id被认为是删除的。由于只有更改被传播,每个发起的事件槽的完整状态必须驻留在接收端。在接收 MT 事件时,只需更新当前槽位的适当属性。

有些设备识别和/或跟踪的触摸点比它们可以报告给驱动程序的要多。这种设备的驱动程序应该将一个 B 型事件槽与硬件报告的每个接触点关联起来。每当与事件槽相关联的触摸点的身份发生变化时,驱动程序应该通过更改其 ABS_MT_TRACKING_ID 使该事件槽失效。如果硬件信号显示它正在跟踪的触摸点比它当前报告的要多,驱动程序应该使用 BTN_TOOL_*TAP 事件来通知用户空间当前硬件正在跟踪的触摸点总数。驱动程序应该通过显式发送相应的 BTN_TOOL_*TAP 事件并在调用 input_mt_report_pointer_emulation() 时将 use_count 设置为 false 来实现这一点。驱动程序应该只发布硬件能够报告的事件槽数量。用户空间可以通过注意到支持的最大 BTN_TOOL_*TAP 事件大于 ABS_MT_SLOT 轴的 absinfo 中报告的 B 类型槽的总数,从而检测到驱动程序报告的总接触数比槽数多。

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

如果驱动报告 BTN_TOUCHABS_PRESSUREABS_MT 事件外,最后一个 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

下面是在 0 号槽位上抬起触点后的顺序:

   ABS_MT_TRACKING_ID -1
   SYN_REPORT

被修改的槽位已经为 0,因此 ABS_MT_SLOT 被省略。该消息解除了 0 号槽位与 45 号接触点的关联,从而破坏 45 号接触点,释放 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 分别提供接触区域和接近工具的大小。

TOUCHWIDTH 参数有一个几何解释;想象一下,透过窗户看到有人轻轻地把手指放在玻璃上。你会看到两个区域,一个内部区域由手指接触玻璃的部分组成,另一个外部区域由手指的周长组成。触摸区域的中心(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 的比值总是小于单位,这与接触压力有关。对于基于压力的器件,ABS_MT_PRESSURE 可以用来提供接触区域的压力。能够接触悬停的设备可以使用 ABS_MT_DISTANCE 来指示接触点与表面之间的距离。


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


除了 MAJOR 参数,还可以通过添加 MINOR 参数来描述触摸和手指区域的椭圆形,例如 MAJORMINOR 是椭圆的长轴和小轴。触摸椭圆的方向可以用 orientation 参数描述,手指椭圆的方向由向量(a-b)给出。

对于 A 类设备,触摸形状的进一步规范可以通过 ABS_MT_BLOB_ID 实现。

ABS_MT_TOOL_TYPE 可用于指定触摸工具是手指、钢笔还是其他工具。最后,ABS_MT_TRACKING_ID 事件可以用于跟踪已识别的触摸点。

B 型协议中,ABS_MT_TOOL_TYPEABS_MT_TRACKING_ID 由输入核心隐式处理;驱动程序应该调用 input_mt_report_slot_state()

六、事件语义

1、ABS_MT_TOUCH_MAJOR

触点主轴的长度。长度应以表面单位表示。如果曲面的分辨率是 X 乘以Y,那么 ABS_MT_TOUCH_MAJOR 的最大可能值是 (X^2 + Y^2),对角线 [#f4]_

2、ABS_MT_TOUCH_MINOR

接触轴的长度,以表面单位表示。如果接触是圆形的,这个事件可以省略 [#f4]_

3、ABS_MT_WIDTH_MAJOR

接触工具主轴的长度,以表面单位表示。这应该被理解为工具本身的大小。触点的方向和接触的工具假设是相同的 [#f4]_

4、ABS_MT_WIDTH_MINOR

接触工具小轴的长度,以表面单位表示。省略 if 循环 [#f4]_

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

5、ABS_MT_PRESSURE

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

6、ABS_MT_DISTANCE

接触面与表面之间的距离,以表面单位表示。零距离表示触点接触表面。正数表示接触者在水面上方盘旋。

7、ABS_MT_ORIENTATION

接触椭圆的方向。该值应该描述围绕触控中心顺时针旋转的四分之一圈。带符号的值范围是任意的,但是对于与曲面的 Y 轴(北)对齐的椭圆应该返回零,当椭圆向左旋转时返回负值,当椭圆向右旋转时返回正值。当与 X 轴正方向对齐时,应返回范围 max;当与 X 轴负方向对齐时,应返回 -max 范围。

默认情况下,触摸点是对称的。对于能够真正 360 度方向的设备,报告的方向必须超过最大范围,以表明超过 1/4 转。对于倒置的手指,应该返回范围 max*2

如果触摸区域是圆形的,或者如果该信息在内核驱动程序中不可用,则可以省略定向。部分方向支持是可能的,如果设备可以区分两个轴,但不能(唯一地)区分中间的任何值。在这种情况下, ABS_MT_ORIENTATION 的范围应该是 [0,1] [#f4]_

8、ABS_MT_POSITION_X

接触椭圆中心的曲面 X 坐标。

9、ABS_MT_POSITION_Y

接触椭圆中心的面 Y 坐标。

10、ABS_MT_TOOL_X

接触工具中心的曲面 X 坐标。如果设备不能区分预期的触点和工具本身,则省略。

11、ABS_MT_TOOL_Y

接触工具中心的平面 Y 坐标。如果设备不能区分预期的触点和工具本身,则省略。

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

12、ABS_MT_TOOL_TYPE

接触工具的类型。许多内核驱动程序不能区分不同的工具类型,例如手指或钢笔。在这种情况下,应该省略该事件。协议目前主要支持 MT_TOOL_FINGERMT_TOOL_PENMT_TOOL_PALM [#f2]_。对于 B 类设备,此事件由输入核心处理;驱动程序应该使用 input_mt_report_slot_state()。接触点的 ABS_MT_TOOL_TYPE 可能随着时间的推移而改变,但仍然接触设备,因为固件可能无法确定哪个工具在第一次出现时正在使用。

13、ABS_MT_BLOB_ID

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

14、ABS_MT_TRACKING_ID

TRACKING_ID 在其生命周期中标识一个发起的接触点 [#f5]_TRACKING_ID 的取值范围应该足够大,以确保在较长一段时间内保持的接触点的唯一标识。对于 B 类设备,此事件由输入核心处理;驱动程序应该使用 input_mt_report_slot_state()

七、事件计算

不同的硬件群不可避免地会导致一些设备比其他设备更适合 MT 协议。为了简化和统一映射,本节给出如何计算某些事件的方法。

对于报告触点为矩形形状的设备,无法获得有符号的方向。假设 XY 是接触矩形的边长,下面是一个简单的公式,它尽可能保留了最多的信息:

   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)。

对于同时具有 TC 坐标的 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,是一个欧氏二部匹配问题。在每次事件同步时,实际触摸点集将与前一次同步中的触摸点集匹配。完整的实现可以在 [#f3]_ 中找到。

九、手势

在创建手势事件的特定应用中,TOUCHWIDTH 参数可用于近似手指压力或区分食指和拇指。通过添加 MINOR 参数,还可以区分扫指和指向的手指,通过 ORIENTATION,可以检测手指的扭曲。

十、注意事项

为了与现有的应用程序保持兼容,手指包中报告的数据不能被识别为单点触摸事件。

对于 A 类设备,所有手指数据都绕过输入过滤,因为相同类型的后续事件引用不同的手指。

… [#f1] 此外,差异(TOOL_X - POSITION_X)可以用来建模倾斜。
… [#f2] 当然,这个清单还可以扩展。
… [#f3] mtdev 项目:http://bitmath.org/code/mtdev/。
… [#f4] 请参阅有关事件计算的部分。
… [#f5] 参见手指追踪部分。

有关Linux 驱动开发 六十六:多点触控(MT)协议的更多相关文章

  1. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  2. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  3. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  5. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  6. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  7. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  10. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

随机推荐