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 还具有 trackpoint,它使用单独的数据包格式。它也是每个数据包 6 个字节。

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

请注意,当有 trackpoint 可用时,鼠标按钮也与触摸板或 trackpoint 相关联。在 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,默认值为 OFF。对于版本 2,默认值为“1”。

    打开数据包调试将使驱动程序在处理之前将收到的每个数据包转储到 syslog。请注意,这会生成大量数据!

  • paritycheck

    打开或关闭奇偶校验。

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

    硬件版本 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 之外,似乎几乎没有区别,后者不报告压力/宽度并且具有不同的数据一致性检查。

可能所有 param[0] <= 01 的版本都可以被认为是 4 字节/固件 1。除了 02.00.30 之外,< 02.08.00 的版本都可以被认为是 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 字节数据包格式

1 指和 3 指触摸共享相同的 6 字节数据包格式,不同之处在于 3 指触摸仅报告所有三个手指的中心位置。

固件将为 2 指触摸发送 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