Commit b584efc9ea7575d3235cfd745e8a28201d2c37f6

Authored by Michael Hennerich
Committed by Dmitry Torokhov
1 parent 49327ad2bb

Input: ad7879 - prevent invalid finger data reports

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>

Showing 1 changed file with 27 additions and 5 deletions Side-by-side Diff

drivers/input/touchscreen/ad7879.c
... ... @@ -129,6 +129,9 @@
129 129 u16 cmd_crtl1;
130 130 u16 cmd_crtl2;
131 131 u16 cmd_crtl3;
  132 + int x;
  133 + int y;
  134 + int Rt;
132 135 };
133 136  
134 137 static int ad7879_read(struct ad7879 *ts, u8 reg)
135 138  
136 139  
... ... @@ -175,13 +178,32 @@
175 178 Rt /= z1;
176 179 Rt = (Rt + 2047) >> 12;
177 180  
178   - if (!timer_pending(&ts->timer))
  181 + /*
  182 + * Sample found inconsistent, pressure is beyond
  183 + * the maximum. Don't report it to user space.
  184 + */
  185 + if (Rt > ts->pressure_max)
  186 + return -EINVAL;
  187 +
  188 + /*
  189 + * Note that we delay reporting events by one sample.
  190 + * This is done to avoid reporting last sample of the
  191 + * touch sequence, which may be incomplete if finger
  192 + * leaves the surface before last reading is taken.
  193 + */
  194 + if (timer_pending(&ts->timer)) {
  195 + /* Touch continues */
179 196 input_report_key(input_dev, BTN_TOUCH, 1);
  197 + input_report_abs(input_dev, ABS_X, ts->x);
  198 + input_report_abs(input_dev, ABS_Y, ts->y);
  199 + input_report_abs(input_dev, ABS_PRESSURE, ts->Rt);
  200 + input_sync(input_dev);
  201 + }
180 202  
181   - input_report_abs(input_dev, ABS_X, x);
182   - input_report_abs(input_dev, ABS_Y, y);
183   - input_report_abs(input_dev, ABS_PRESSURE, Rt);
184   - input_sync(input_dev);
  203 + ts->x = x;
  204 + ts->y = y;
  205 + ts->Rt = Rt;
  206 +
185 207 return 0;
186 208 }
187 209