Input: ad7879 - prevent invalid finger data reports
authorMichael Hennerich <michael.hennerich@analog.com>
Thu, 28 Oct 2010 21:59:05 +0000 (14:59 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 29 Oct 2010 05:32:50 +0000 (22:32 -0700)
Considering following scenario - the touch is present on the screen
at the beginning of the last conversion sequence, but by the time
the last sequence is finished, the finger is lift off. The AD7879 data
available interrupt signals (DAV) completion, however some X,Y values
are not valid because the screen inputs were floating during the
acquisition.

The AD7877 acts differently here, since it only asserts DAV if the
touch is still present when the conversion sequence finished.

Based on the fact that this can only happen in the last sample of the
repeated conversion sequence, we simply skip the last (short glitches
are filtered by the AD7879 internal median and average filters).
This doesn't cause noticeable side effects, since the minimum conversion
interval is 9.44ms. We receive ~100 waypoint samples per second, so we
simply delay the result by 9.44ms.

We also reject samples where pressure is greater than pressure_max.

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/touchscreen/ad7879.c

index ba6f0bd1e762e494961f6eab23204fb37eff63c0..bc3b5187f3a391504f275567d7143e878dda5c9b 100644 (file)
@@ -129,6 +129,9 @@ struct ad7879 {
        u16                     cmd_crtl1;
        u16                     cmd_crtl2;
        u16                     cmd_crtl3;
+       int                     x;
+       int                     y;
+       int                     Rt;
 };
 
 static int ad7879_read(struct ad7879 *ts, u8 reg)
@@ -175,13 +178,32 @@ static int ad7879_report(struct ad7879 *ts)
                Rt /= z1;
                Rt = (Rt + 2047) >> 12;
 
-               if (!timer_pending(&ts->timer))
+               /*
+                * Sample found inconsistent, pressure is beyond
+                * the maximum. Don't report it to user space.
+                */
+               if (Rt > ts->pressure_max)
+                       return -EINVAL;
+
+               /*
+                * Note that we delay reporting events by one sample.
+                * This is done to avoid reporting last sample of the
+                * touch sequence, which may be incomplete if finger
+                * leaves the surface before last reading is taken.
+                */
+               if (timer_pending(&ts->timer)) {
+                       /* Touch continues */
                        input_report_key(input_dev, BTN_TOUCH, 1);
+                       input_report_abs(input_dev, ABS_X, ts->x);
+                       input_report_abs(input_dev, ABS_Y, ts->y);
+                       input_report_abs(input_dev, ABS_PRESSURE, ts->Rt);
+                       input_sync(input_dev);
+               }
+
+               ts->x = x;
+               ts->y = y;
+               ts->Rt = Rt;
 
-               input_report_abs(input_dev, ABS_X, x);
-               input_report_abs(input_dev, ABS_Y, y);
-               input_report_abs(input_dev, ABS_PRESSURE, Rt);
-               input_sync(input_dev);
                return 0;
        }