Touchpad driver changes

From OLPC
Jump to: navigation, search

Since touchpad misbehavior on the XO has recently risen in priority again, a fresh round of work has been done on the touchpad driver. The following (lengthy) notes describe the resulting changes, and hopefully serve as documentation of a sort.

If you're impatient, an experimental kernel with a new touchpad driver built-in is available for testing, below.

This driver has been incorporated into later (F11) software builds, including 10.1.1 and 10.1.2 and the paraguay stream of builds.

Intro:

There's been a history of problematic operation of the touchpad on the XO-1. Newer models have a pad from Synaptics, which works quite well, but there are about a million (really) laptops in the field equipped with an ALPS "HGPK" touchpad, which has been resistant to attempts to get it it to work properly. The symptoms include unexpected cursor jumps, continuous mouse traffic with no finger applied to the pad, and other misbehavior. (Three known touchpad issues)

This page doesn't attempt to talk about older, non-production versions of the touchpad that may be found on rev A and rev B models of the XO. Earlier touchpads had additional misbehaviors that aren't of interest here.

[ Note: the "now" version of the driver described here is current as of 2009-08-27. I'll try and keep this page up to date as the driver evolves -- certainly until it's deployed -- but wiki-rot may set in at some point, as usual. The before version is that which was originally on the "testing" branch of the olpc-2.6 kernel tree, and which was used for the 802 kernel build. The now version is on "olpc-2.6.30" and (the head of the) "testing" branch. -pgf ]

Miscalibration Symptoms

These symptoms can usually be cleared up with a recalibration of the touchpad -- recalibration is a step which tells the touchpad to resynchronize with its current, neutral environment. Recalibration can be done manually (i.e., the so-called "four finger salute", or automatically either by the touchpad itself, or invoked by the linux kernel driver. For a successful recalibration to take place, it's important that the pad be clean, and dry, and that there be no finger or hand contact during the recalibration. (It's actually quite important that the pad remain clean and dry in operation, as well.) Recalibration is complicated by the fact that there is no success or failure result from a recalibration -- either it was done correctly, and the touchpad will now "behave", or it wasn't, and the touchpad may continue misbehaving, or even misbehave in a new and different way. ALPS tells us that the recalibration itself takes about 50ms.

(The official datasheet is File:KGDMFA001-non-confidential.pdf.

Big Jumps:

Sometimes the touchpad will erroneously report large (sometimes huge) motion jumps -- large enough that they would be very difficult for a finger to actually generate. Recently we noticed that these jumps have a "decay" property to them -- if the the X direction jumps by, say 110 pixels, then the next packet will report a 55 px jump, the next 27 pixels, the next 13, etc, often continuing until the pattern becomes lost in noise and roundoff error.

before

We used to simply detect big jumps ( > 100px), and schedule a recalibration for the future (1 second). We did not discard the packet.

now

We now detect a jump (>60px), and discard it. We will also detect and discard jumps at half of that threshold, as long as they are at least 4x larger than the packet immediately preceding. Following this, if the motion in the next packet is close to (within 20%) half the size, we discard it as well. We repeat this until the next packet offset falls outside the 20% window. At this point, if we've discarded at least 3 packets in this manner, we schedule a recalibration. (All of the above decisions are applied to X and Y values independently.)

tuneables

discard_threshold
Packets with a motion delta at least this big will be discarded, as well as other related packets as described above.
jumpy_delay
After such a jump sequence is detected, a recalibration will be scheduled in 'jumpy_delay' milliseconds. Since jumps are usually associated with actual press events, the delay gives some time for the finger to be lifted, though there's no way of checking whether this actually occurs. If set to 0, no recalibration will be attempted.

Soft Packet Spew:

A "soft" spew is one in which mouse data is received continuously, with almost no movement associated with the data. The packets received will all specify either no motion, or perhaps -1 or +1 pixels, but over time the average will stay very close to zero -- certainly less than 3 pixels.

before

We used to watch 100 packets to see if the net movement was below 3 pixels in any direction. If this condition was not met, we would reset our counters and watch the next 100 packets. 100 packets represents at least 1.2 seconds of spew (at 12ms/packet).

now

We now maintain a moving average, so that the most recent N packets are summed. In addition, N has been reduced to around 40, which represents a minimum of just .5 seconds of spew.

tuneables

spew_delay
After a soft packet spew is detected, a recalibrate will be scheduled in 'spew_delay' milliseconds. If set to 0, no recalibration will be attempted. Since there's no reason to believe a finger is on the pad during a spew, this delay defaults to 1ms.


Tethered Cursor (or, Hard Packet Spew):

Sometimes the mouse cursor will appear to be tethered to the screen, almost as if by a rubber band. When a finger approaches, the cursor will move to meet it (or sometimes, move away), but when the finger is removed, the cursor will move right back to where it was before.

There's currently no code in place to detect this condition, though a little more is known about the cause. (see below.)

Post-recalibration Delay, Collision Detection, and Retries

Since the presence of a finger on the touchpad will prevent a successful recalibration, it's tempting to try and determine whether that was the case.

before

As an attempt to infer whether a just-completed calibration had been successful, the time between the recalibration and the next packet arrival was checked. Any touchpad traffic within 2 seconds after recalibration caused scheduling of another (1 second in the future). If the touchpad is in heavy use (picture a desperate user trying to regain control of their cursor), multiple recalibrations might be scheduled.

now

Evidence from packet logs indicates that the above scheme may cause as many problems as it solves. We now take the approach that if a recalibration failed, then we'll discover that in due course, and that we don't need to try and intuit whether a finger was near the pad during the critical 50ms. No collision detection is attempted, and no rescheduling is done.

tuneables

recal_guard_time
If a packet is received within this many ms after a recalibration, the recalibration will be rescheduled. The default is 0, which suppresses retries.
post_interrupt_delay
If a recalibration is to be rescheduled (after it has been presumed to be "interrupted"), this determines when it will occur. (ms)


X11 acceleration

At a much higher level than the linux device driver, X11 controls the scaling of finger movements to cursor movements. The "xset" command can be used to cause finger movements to result in relatively larger or smaller cursor motions.

before

There is a line in /usr/bin/olpc-session (from the olpc-utils package) which runs "xset 7/4 0". The second argument to xset is a threshold -- after the mouse moves that many pixels, then the fractional first argument is applied to the motion.

now

One would think that a threshold of '0' might cause behavior very similar to '1', but unfortunately that is not the case -- '0' seems to be special. Changing the xset line to "xset 7/4 1" results in much more predictable motion. This does nothing for touchpad recalibration, of course -- it's purely an improvement in useability, for when the touchpad is behaving correctly.


Experiments with "advanced" mode

The touchpad is currently being used in standard "mouse mode". in this mode, position is received in 3-byte packets, containing relative motion for X and Y, and two button bits. If packets are being received, it's because the finger is down -- there is no notion of "up" or "down" other than that packets are being received at all. And, in particular, there is no indication of "pressure", or relative force of the press.

In "advanced" mode, the touchpad will send 6 byte packets. The X and Y data is sent in absolute (instead of relative) values (hence part of the need for more bits), there exists the possibility of enabling the pressure tablet (?) (PT) mode, and in addition to an explicit "down" bit, there is a 4 bit value representing pressure.

As an experiment, the current driver was converted to use advanced mode. (I should say "reconverted", because early versions of the touchpad driver, which supported both the pressure and capacitive HGPK modes, used advanced mode. Pressure tablet support, and advanced mode, were dropped for stability reasons. The recent work implemented a much simpler version of this (no PT mode), in hopes of avoiding some of the previous instability.) Because much of the existing code assumes, and relies on getting relative motion values, the absolute values returned from the touchpad were immediately converted to relative offsets before being passed to the rest of the code.

Two things were learned: a) The pressure value returned in this mode is not of much use in helping determine that the touchpad is misbehaving. We had thought that perhaps if pressure data were available, that "lighter" pressure values might correlate well with jumps, or packet spew -- perhaps we could simply ignore all data with pressure less than some threshold. This turned out not to be the case -- packet spew can sometimes occur reporting with early full pressure, and when the touchpad is functioning properly, a moving finger may report fairly low pressure.

b) The explanation for the "tethered cursor" effect (described above) became more obvious with the touchpad operating in 6-byte mode, reporting absolute, rather than relative, motions. In this mode, when that condition occurs, the data shows a continuous stream of packets, all containing exactly the same absolute X and Y coordinates. In other words, the touchpad believes it's being forced (as if by an invisible finger) to a specific location. When a "real" finger is applied, the reported location will drift to it, but when removed, the touchpad resumes spewing the earlier fixed coordinates. The stream of packets can be perturbed, but not eliminated. Clearly the same phsyical condition must occur whether in 6-byte or 3-byte modes -- but in 3-byte mode, when this condition occurs, the null-valued relative reports are likely filtered out by the touchpad firmware. The result in 3-byte mode is that no packets are received at all, unless a finger is applied, in which case one gets the drifting "tethered" cursor.

Unfortunately, while advanced (6-byte) mode might allow detecting the hard spew (tethered cursor) case, it turns out that the motion reports from the touchpad contain many duplicate values, which seem in some cases as if they have replaced actual intermediate values which one might have expected. So jumps tend to be bigger (triggering our miscalibration heuristics) and cursor motion erratic. For this reason, along with the added complexity of the driver, we won't be enabling advanced mode for an initial field upgrade.



Trial Kernel with new driver

A tarball containing a new kernel rpm, and a small installation script, can be found here:

http://dev.laptop.org/~pgf/touchpad/tpad_kernel-c7d5d12.tar

and the source here:

http://dev.laptop.org/git/olpc-2.6/tree/drivers/input/mouse/hgpk.c?h=olpc-2.6.31

This kernel has had limited testing in the field. You almost certainly won't find that the touchpad behaves worse than it does currently. We're interested in knowing whether you think it's much better.

Remember that the solutions we've implemented are heuristics designed to a) guess when the touchpad is in trouble, b) force a recalibration, but c) not too often. This can't be done perfectly, but hopefully you'll find the new behavior an improvement.

To install:

  • Ensure that the laptop has had security disabled.
  • untar the contents of the above file onto a USB key.
  • "cd /media/XXXX", and run "./install_tpad.sh". This will install the new kernel rpm, and will also adjust the X11 setting for the mouse acceleration.
  • Restart the laptop, and let us know what you think.

Guidelines for touchpad use

For all touchpads, but especially for this one, it's important to observe the following rules:

  • Never let more than one finger at a time be in contact with the pad, and never rest a hand or finger on the touchpad while doing something else. Even if a second finger or hand hovers too closely it can cause misbehavior.
  • Keep the touchpad, and your hands, clean and dry.