9. Elantech 触摸板驱动

版权所有 (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net>

Steve Havelka 发现并提供了关于硬件版本 1 的额外信息

基于 Xandros 的 Woody 发来的补丁和 eeeuser.com 论坛用户 StewieGriffin 转发给我的补丁,提供了版本 2 (EeePC) 硬件支持

9.1. 简介

目前,Linux Elantech 触摸板驱动程序可识别四种不同的硬件版本,分别命名为版本 1、版本 2、版本 3 和版本 4。版本 1 在“较旧”的笔记本电脑中找到,每个数据包使用 4 个字节。版本 2 似乎是随着 EeePC 引入的,每个数据包使用 6 个字节,并提供额外的功能,例如两个手指的位置和触摸宽度。硬件版本 3 每个数据包使用 6 个字节(对于 2 个手指,则是两个 6 字节数据包的串联),并允许跟踪最多 3 个手指。硬件版本 4 每个数据包使用 6 个字节,可以将状态数据包与多个头部或移动数据包组合在一起。硬件版本 4 允许跟踪最多 5 个手指。

一些硬件版本 3 和版本 4 还有一个单独使用的数据包格式的轨迹球。它也是每个数据包 6 个字节。

该驱动程序尝试支持这两个硬件版本,并且应与 Xorg Synaptics 触摸板驱动程序及其图形配置实用程序兼容。

请注意,鼠标按钮也与触摸板或轨迹球相关联(如果有轨迹球)。在 xorg 中禁用触摸板 (TouchPadOff=0) 也将禁用与触摸板关联的按钮。

此外,可以通过调整其某些内部寄存器的内容来更改触摸板的操作。这些寄存器由驱动程序表示为 /sys/bus/serio/drivers/psmouse/serio? 下的 sysfs 条目,可以从中读取和写入。

目前,只有硬件版本 1 的寄存器得到了一定程度的理解。硬件版本 2 似乎使用了一些相同的寄存器,但不知道寄存器中的位是否代表相同的东西或可能已更改其含义。

最重要的是,某些寄存器设置仅在触摸板处于相对模式而不是绝对模式时才有效。由于 Linux Elantech 触摸板驱动程序始终将硬件置于绝对模式,因此并非下面提到的所有信息都可以立即使用。但是,由于没有免费提供的 Elantech 文档,因此无论如何都会在此处提供信息,以保持完整性。

9.2. 额外旋钮

目前,Linux Elantech 触摸板驱动程序在 /sys/bus/serio/drivers/psmouse/serio? 下为用户提供了三个额外的旋钮。

  • debug

    打开或关闭不同级别的调试。

    通过将“0”回显到此文件,所有调试都将关闭。

    目前,值“1”将打开一些基本调试,值“2”将打开数据包调试。对于硬件版本 1,默认值为关闭。对于版本 2,默认值为“1”。

    打开数据包调试将使驱动程序在处理每个接收到的数据包之前将其转储到系统日志中。请注意,这可能会生成大量数据!

  • paritycheck

    打开或关闭奇偶校验。

    通过将“0”回显到此文件,将关闭奇偶校验。任何非零值都会将其打开。对于硬件版本 1,默认值为打开。对于版本 2,默认值为关闭。

    硬件版本 1 通过计算每个数据包最后 3 个字节的奇偶校验位来提供基本的数据完整性验证。驱动程序可以检查这些位并拒绝任何似乎已损坏的数据包。使用此旋钮,您可以绕过该检查。

    硬件版本 2 不提供相同的奇偶校验位。只能进行一些基本的数据一致性检查。目前,默认情况下禁用检查。目前,即使打开它也不会有任何作用。

  • crc_enabled

    将 crc_enabled 设置为 0/1。“crc_enabled”的名称是此完整性检查的正式名称,即使它不是实际的循环冗余检查。

    根据 crc_enabled 的状态,驱动程序会对硬件版本 3 和 4 执行某些基本的数据完整性验证。驱动程序将拒绝任何似乎已损坏的数据包。使用此旋钮,可以使用此旋钮更改 crc_enabled 的状态。

    读取 crc_enabled 值将显示活动值。将“0”或“1”回显到此文件会将状态设置为“0”或“1”。

9.3. 区分硬件版本

要检测硬件版本,请读取版本号为 param[0].param[1].param[2]

4 bytes version: (after the arrow is the name given in the Dell-provided driver)
02.00.22 => EF013
02.06.00 => EF019

在实践中,似乎有更多版本,例如 00.01.64、01.00.21、02.00.00、02.00.04、02.00.06

6 bytes:
02.00.30 => EF113
02.08.00 => EF023
02.08.XX => EF123
02.0B.00 => EF215
04.01.XX => Scroll_EF051
04.02.XX => EF051

在实践中,似乎有更多版本,例如 04.03.01、04.04.11。除了 EF113 之外,似乎几乎没有区别,EF113 不报告压力/宽度,并且具有不同的数据一致性检查。

可能所有 param[0] <= 01 的版本都可以视为 4 字节/固件 1。版本 < 02.08.00(02.00.30 除外)视为 4 字节/固件 2。所有 >= 02.08.00 的版本都可以视为 6 个字节。

9.4. 硬件版本 1

9.4.1. 寄存器

通过将十六进制值回显到寄存器,可以更改其内容。

例如

echo -n 0x16 > reg_10
  • reg_10

    bit   7   6   5   4   3   2   1   0
          B   C   T   D   L   A   S   E
    
          E: 1 = enable smart edges unconditionally
          S: 1 = enable smart edges only when dragging
          A: 1 = absolute mode (needs 4 byte packets, see reg_11)
          L: 1 = enable drag lock (see reg_22)
          D: 1 = disable dynamic resolution
          T: 1 = disable tapping
          C: 1 = enable corner tap
          B: 1 = swap left and right button
    
  • reg_11

    bit   7   6   5   4   3   2   1   0
          1   0   0   H   V   1   F   P
    
          P: 1 = enable parity checking for relative mode
          F: 1 = enable native 4 byte packet mode
          V: 1 = enable vertical scroll area
          H: 1 = enable horizontal scroll area
    
  • reg_20

    single finger width?
    
  • reg_21

    scroll area width (small: 0x40 ... wide: 0xff)
    
  • reg_22

    drag lock time out (short: 0x14 ... long: 0xfe;
                        0xff = tap again to release)
    
  • reg_23

    tap make timeout?
    
  • reg_24

    tap release timeout?
    
  • reg_25

    smart edge cursor speed (0x02 = slow, 0x03 = medium, 0x04 = fast)
    
  • reg_26

    smart edge activation area width?
    

9.4.2. 本机相对模式 4 字节数据包格式

字节 0

bit   7   6   5   4   3   2   1   0
      c   c  p2  p1   1   M   R   L

      L, R, M = 1 when Left, Right, Middle mouse button pressed
         some models have M as byte 3 odd parity bit
      when parity checking is enabled (reg_11, P = 1):
         p1..p2 = byte 1 and 2 odd parity bit
      c = 1 when corner tap detected

字节 1

bit   7   6   5   4   3   2   1   0
     dx7 dx6 dx5 dx4 dx3 dx2 dx1 dx0

      dx7..dx0 = x movement;   positive = right, negative = left
      byte 1 = 0xf0 when corner tap detected

字节 2

bit   7   6   5   4   3   2   1   0
     dy7 dy6 dy5 dy4 dy3 dy2 dy1 dy0

      dy7..dy0 = y movement;   positive = up,    negative = down

字节 3

parity checking enabled (reg_11, P = 1):

   bit   7   6   5   4   3   2   1   0
         w   h  n1  n0  ds3 ds2 ds1 ds0

         normally:
            ds3..ds0 = scroll wheel amount and direction
                       positive = down or left
                       negative = up or right
         when corner tap detected:
            ds0 = 1 when top right corner tapped
            ds1 = 1 when bottom right corner tapped
            ds2 = 1 when bottom left corner tapped
            ds3 = 1 when top left corner tapped
         n1..n0 = number of fingers on touchpad
            only models with firmware 2.x report this, models with
            firmware 1.x seem to map one, two and three finger taps
            directly to L, M and R mouse buttons
         h = 1 when horizontal scroll action
         w = 1 when wide finger touch?

otherwise (reg_11, P = 0):

   bit   7   6   5   4   3   2   1   0
        ds7 ds6 ds5 ds4 ds3 ds2 ds1 ds0

         ds7..ds0 = vertical scroll amount and direction
                    negative = up
                    positive = down

9.4.3. 本机绝对模式 4 字节数据包格式

EF013 和 EF019 有一个特殊的行为(由于固件中的错误?),当 1 个手指触摸时,必须丢弃前 2 个位置报告。每当报告不同数量的手指时,此计数都会重置。

字节 0

firmware version 1.x:

   bit   7   6   5   4   3   2   1   0
         D   U  p1  p2   1  p3   R   L

         L, R = 1 when Left, Right mouse button pressed
         p1..p3 = byte 1..3 odd parity bit
         D, U = 1 when rocker switch pressed Up, Down

firmware version 2.x:

   bit   7   6   5   4   3   2   1   0
        n1  n0  p2  p1   1  p3   R   L

         L, R = 1 when Left, Right mouse button pressed
         p1..p3 = byte 1..3 odd parity bit
         n1..n0 = number of fingers on touchpad

字节 1

firmware version 1.x:

   bit   7   6   5   4   3   2   1   0
         f   0  th  tw  x9  x8  y9  y8

         tw = 1 when two finger touch
         th = 1 when three finger touch
         f  = 1 when finger touch

firmware version 2.x:

   bit   7   6   5   4   3   2   1   0
         .   .   .   .  x9  x8  y9  y8

字节 2

bit   7   6   5   4   3   2   1   0
     x7  x6  x5  x4  x3  x2  x1  x0

      x9..x0 = absolute x value (horizontal)

字节 3

bit   7   6   5   4   3   2   1   0
     y7  y6  y5  y4  y3  y2  y1  y0

      y9..y0 = absolute y value (vertical)

9.5. 硬件版本 2

9.5.1. 寄存器

通过将十六进制值回显到寄存器,可以更改其内容。

例如

echo -n 0x56 > reg_10
  • reg_10

    bit   7   6   5   4   3   2   1   0
          0   1   0   1   0   1   D   0
    
          D: 1 = enable drag and drop
    
  • reg_11

    bit   7   6   5   4   3   2   1   0
          1   0   0   0   S   0   1   0
    
          S: 1 = enable vertical scroll
    
  • reg_21

    unknown (0x00)
    
  • reg_22

    drag and drop release time out (short: 0x70 ... long 0x7e;
                              0x7f = never i.e. tap again to release)
    

9.5.2. 本机绝对模式 6 字节数据包格式

9.5.2.1. 奇偶校验和数据包重新同步

没有奇偶校验,但是可以执行一些一致性检查。

例如,对于 EF113

SA1= packet[0];
A1 = packet[1];
B1 = packet[2];
SB1= packet[3];
C1 = packet[4];
D1 = packet[5];
if( (((SA1 & 0x3C) != 0x3C) && ((SA1 & 0xC0) != 0x80)) || // check Byte 1
    (((SA1 & 0x0C) != 0x0C) && ((SA1 & 0xC0) == 0x80)) || // check Byte 1 (one finger pressed)
    (((SA1 & 0xC0) != 0x80) && (( A1 & 0xF0) != 0x00)) || // check Byte 2
    (((SB1 & 0x3E) != 0x38) && ((SA1 & 0xC0) != 0x80)) || // check Byte 4
    (((SB1 & 0x0E) != 0x08) && ((SA1 & 0xC0) == 0x80)) || // check Byte 4 (one finger pressed)
    (((SA1 & 0xC0) != 0x80) && (( C1 & 0xF0) != 0x00))  ) // check Byte 5
        // error detected

对于所有其他版本,只有一些常量位

if( ((packet[0] & 0x0C) != 0x04) ||
    ((packet[3] & 0x0f) != 0x02) )
        // error detected

如果检测到错误,则所有数据包都将移动一位(并且丢弃 packet[0])。

9.5.2.2. 单指/三指触摸

字节 0

bit   7   6   5   4   3   2   1   0
      n1  n0  w3  w2   .   .   R   L

      L, R = 1 when Left, Right mouse button pressed
      n1..n0 = number of fingers on touchpad

字节 1

bit   7   6   5   4   3   2   1   0
      p7  p6  p5  p4 x11 x10 x9  x8

字节 2

bit   7   6   5   4   3   2   1   0
      x7  x6  x5  x4  x3  x2  x1  x0

      x11..x0 = absolute x value (horizontal)

字节 3

bit   7   6   5   4   3   2   1   0
      n4  vf  w1  w0   .   .   .  b2

      n4 = set if more than 3 fingers (only in 3 fingers mode)
      vf = a kind of flag ? (only on EF123, 0 when finger is over one
           of the buttons, 1 otherwise)
      w3..w0 = width of the finger touch (not EF113)
      b2 (on EF113 only, 0 otherwise), b2.R.L indicates one button pressed:
             0 = none
             1 = Left
             2 = Right
             3 = Middle (Left and Right)
             4 = Forward
             5 = Back
             6 = Another one
             7 = Another one

字节 4

bit   7   6   5   4   3   2   1   0
     p3  p1  p2  p0  y11 y10 y9  y8

      p7..p0 = pressure (not EF113)

字节 5

bit   7   6   5   4   3   2   1   0
     y7  y6  y5  y4  y3  y2  y1  y0

      y11..y0 = absolute y value (vertical)

9.5.2.3. 双指触摸

请注意,这两对坐标并不是两个手指的精确坐标,而只是左下和右上坐标对。因此,实际的手指可能位于由这两个点定义的正方形的另一条对角线上。

字节 0

bit   7   6   5   4   3   2   1   0
     n1  n0  ay8 ax8  .   .   R   L

      L, R = 1 when Left, Right mouse button pressed
      n1..n0 = number of fingers on touchpad

字节 1

bit   7   6   5   4   3   2   1   0
     ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0

      ax8..ax0 = lower-left finger absolute x value

字节 2

bit   7   6   5   4   3   2   1   0
     ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0

      ay8..ay0 = lower-left finger absolute y value

字节 3

bit   7   6   5   4   3   2   1   0
      .   .  by8 bx8  .   .   .   .

字节 4

bit   7   6   5   4   3   2   1   0
     bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0

      bx8..bx0 = upper-right finger absolute x value

字节 5

bit   7   6   5   4   3   2   1   0
     by7 by8 by5 by4 by3 by2 by1 by0

      by8..by0 = upper-right finger absolute y value

9.6. 硬件版本 3

9.6.1. 寄存器

  • reg_10

    bit   7   6   5   4   3   2   1   0
          0   0   0   0   R   F   T   A
    
          A: 1 = enable absolute tracking
          T: 1 = enable two finger mode auto correct
          F: 1 = disable ABS Position Filter
          R: 1 = enable real hardware resolution
    

9.6.2. 本机绝对模式 6 字节数据包格式

单指和三指触摸共享相同的 6 字节数据包格式,只是三指触摸仅报告所有三个手指的中心位置。

固件会为双指触摸发送 12 个字节的数据。

关于防抖:如果盒子电源不稳定或有其他电力问题,或者手指数量发生变化,F/W 将发送“防抖数据包”来通知驱动程序硬件处于防抖状态。防抖数据包具有以下签名

byte 0: 0xc4
byte 1: 0xff
byte 2: 0xff
byte 3: 0x02
byte 4: 0xff
byte 5: 0xff

当我们遇到这种类型的数据包时,我们只需忽略它。

9.6.2.1. 单指/三指触摸

字节 0

bit   7   6   5   4   3   2   1   0
     n1  n0  w3  w2   0   1   R   L

     L, R = 1 when Left, Right mouse button pressed
     n1..n0 = number of fingers on touchpad

字节 1

bit   7   6   5   4   3   2   1   0
     p7  p6  p5  p4 x11 x10  x9  x8

字节 2

bit   7   6   5   4   3   2   1   0
     x7  x6  x5  x4  x3  x2  x1  x0

     x11..x0 = absolute x value (horizontal)

字节 3

bit   7   6   5   4   3   2   1   0
      0   0  w1  w0   0   0   1   0

      w3..w0 = width of the finger touch

字节 4

bit   7   6   5   4   3   2   1   0
     p3  p1  p2  p0  y11 y10 y9  y8

     p7..p0 = pressure

字节 5

bit   7   6   5   4   3   2   1   0
     y7  y6  y5  y4  y3  y2  y1  y0

     y11..y0 = absolute y value (vertical)

9.6.2.2. 双指触摸

双指触摸的数据包格式完全相同,只是硬件发送两个 6 字节数据包。第一个数据包包含第一个手指的数据,第二个数据包包含第二个手指的数据。因此,对于双指触摸,总共发送 12 个字节。

9.7. 硬件版本 4

9.7.1. 寄存器

  • reg_07

    bit   7   6   5   4   3   2   1   0
          0   0   0   0   0   0   0   A
    
          A: 1 = enable absolute tracking
    

9.7.2. 原生绝对模式 6 字节数据包格式

v4 硬件是一个真正的多点触控触摸板,能够跟踪多达 5 根手指。不幸的是,由于 PS/2 的带宽有限,其数据包格式相当复杂。

每当手指的数量或身份发生变化时,硬件会发送一个状态数据包来指示触摸板上有多少根手指以及是哪些手指,然后是头部数据包或运动数据包。头部数据包包含手指 ID、手指位置(绝对 x, y 值)、宽度和压力。运动数据包包含两个手指的位置增量。

例如,当状态数据包告诉触摸板上有 2 根手指时,我们可以预期接下来会有两个头部数据包。如果手指状态没有改变,接下来的数据包将是运动数据包,仅发送手指位置的增量,直到我们收到一个状态数据包。

一个例外是单指触摸。当状态数据包告诉我们只有一根手指时,硬件只会随后发送头部数据包。

9.7.2.1. 状态数据包

字节 0

bit   7   6   5   4   3   2   1   0
      .   .   .   .   0   1   R   L

      L, R = 1 when Left, Right mouse button pressed

字节 1

bit   7   6   5   4   3   2   1   0
      .   .   . ft4 ft3 ft2 ft1 ft0

      ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad

字节 2

not used

字节 3

bit   7   6   5   4   3   2   1   0
      .   .   .   1   0   0   0   0

      constant bits

字节 4

bit   7   6   5   4   3   2   1   0
      p   .   .   .   .   .   .   .

      p = 1 for palm

字节 5

not used

9.7.2.2. 头部数据包

字节 0

bit   7   6   5   4   3   2   1   0
     w3  w2  w1  w0   0   1   R   L

     L, R = 1 when Left, Right mouse button pressed
     w3..w0 = finger width (spans how many trace lines)

字节 1

bit   7   6   5   4   3   2   1   0
     p7  p6  p5  p4 x11 x10  x9  x8

字节 2

bit   7   6   5   4   3   2   1   0
     x7  x6  x5  x4  x3  x2  x1  x0

     x11..x0 = absolute x value (horizontal)

字节 3

bit   7   6   5   4   3   2   1   0
    id2 id1 id0   1   0   0   0   1

    id2..id0 = finger id

字节 4

bit   7   6   5   4   3   2   1   0
     p3  p1  p2  p0  y11 y10 y9  y8

     p7..p0 = pressure

字节 5

bit   7   6   5   4   3   2   1   0
     y7  y6  y5  y4  y3  y2  y1  y0

     y11..y0 = absolute y value (vertical)

9.7.2.3. 运动数据包

字节 0

bit   7   6   5   4   3   2   1   0
    id2 id1 id0   w   0   1   R   L

    L, R = 1 when Left, Right mouse button pressed
    id2..id0 = finger id
    w = 1 when delta overflows (> 127 or < -128), in this case
    firmware sends us (delta x / 5) and (delta y  / 5)

字节 1

bit   7   6   5   4   3   2   1   0
     x7  x6  x5  x4  x3  x2  x1  x0

     x7..x0 = delta x (two's complement)

字节 2

bit   7   6   5   4   3   2   1   0
     y7  y6  y5  y4  y3  y2  y1  y0

     y7..y0 = delta y (two's complement)

字节 3

bit   7   6   5   4   3   2   1   0
    id2 id1 id0   1   0   0   1   0

    id2..id0 = finger id

字节 4

bit   7   6   5   4   3   2   1   0
     x7  x6  x5  x4  x3  x2  x1  x0

     x7..x0 = delta x (two's complement)

字节 5

bit   7   6   5   4   3   2   1   0
     y7  y6  y5  y4  y3  y2  y1  y0

     y7..y0 = delta y (two's complement)

     byte 0 ~ 2 for one finger
     byte 3 ~ 5 for another

9.8. 指点杆(适用于硬件版本 3 和 4)

9.8.1. 寄存器

尚未识别出特殊的寄存器。

9.8.2. 原生相对模式 6 字节数据包格式

9.8.2.1. 状态数据包

字节 0

bit   7   6   5   4   3   2   1   0
      0   0  sx  sy   0   M   R   L

字节 1

bit   7   6   5   4   3   2   1   0
    ~sx   0   0   0   0   0   0   0

字节 2

bit   7   6   5   4   3   2   1   0
    ~sy   0   0   0   0   0   0   0

字节 3

bit   7   6   5   4   3   2   1   0
      0   0 ~sy ~sx   0   1   1   0

字节 4

bit   7   6   5   4   3   2   1   0
     x7  x6  x5  x4  x3  x2  x1  x0

字节 5

bit   7   6   5   4   3   2   1   0
     y7  y6  y5  y4  y3  y2  y1  y0


      x and y are written in two's complement spread
          over 9 bits with sx/sy the relative top bit and
          x7..x0 and y7..y0 the lower bits.
      ~sx is the inverse of sx, ~sy is the inverse of sy.
      The sign of y is opposite to what the input driver
          expects for a relative movement