aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/hgpk.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse/hgpk.c')
-rw-r--r--drivers/input/mouse/hgpk.c122
1 files changed, 91 insertions, 31 deletions
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index 3d33d958a122..222594742c39 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -54,7 +54,7 @@ module_param(jumpy_delay, int, 0644);
54MODULE_PARM_DESC(jumpy_delay, 54MODULE_PARM_DESC(jumpy_delay,
55 "delay (ms) before recal after jumpiness detected"); 55 "delay (ms) before recal after jumpiness detected");
56 56
57static int spew_delay = 1000; 57static int spew_delay = 1;
58module_param(spew_delay, int, 0644); 58module_param(spew_delay, int, 0644);
59MODULE_PARM_DESC(spew_delay, 59MODULE_PARM_DESC(spew_delay,
60 "delay (ms) before recal after packet spew detected"); 60 "delay (ms) before recal after packet spew detected");
@@ -117,6 +117,23 @@ static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y)
117 } 117 }
118} 118}
119 119
120static void hgpk_reset_spew_detection(struct hgpk_data *priv)
121{
122 priv->spew_count = 0;
123 priv->dupe_count = 0;
124 priv->x_tally = 0;
125 priv->y_tally = 0;
126 priv->spew_flag = NO_SPEW;
127}
128
129static void hgpk_reset_hack_state(struct psmouse *psmouse)
130{
131 struct hgpk_data *priv = psmouse->private;
132
133 priv->abs_x = priv->abs_y = -1;
134 hgpk_reset_spew_detection(priv);
135}
136
120/* 137/*
121 * We have no idea why this particular hardware bug occurs. The touchpad 138 * We have no idea why this particular hardware bug occurs. The touchpad
122 * will randomly start spewing packets without anything touching the 139 * will randomly start spewing packets without anything touching the
@@ -142,20 +159,57 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
142 if (l || r) 159 if (l || r)
143 return; 160 return;
144 161
162 /* don't track spew if the workaround feature has been turned off */
163 if (!spew_delay)
164 return;
165
166 if (abs(x) > 3 || abs(y) > 3) {
167 /* no spew, or spew ended */
168 hgpk_reset_spew_detection(priv);
169 return;
170 }
171
172 /* Keep a tally of the overall delta to the cursor position caused by
173 * the spew */
145 priv->x_tally += x; 174 priv->x_tally += x;
146 priv->y_tally += y; 175 priv->y_tally += y;
147 176
148 if (++priv->count > 100) { 177 switch (priv->spew_flag) {
178 case NO_SPEW:
179 /* we're not spewing, but this packet might be the start */
180 priv->spew_flag = MAYBE_SPEWING;
181
182 /* fall-through */
183
184 case MAYBE_SPEWING:
185 priv->spew_count++;
186
187 if (priv->spew_count < SPEW_WATCH_COUNT)
188 break;
189
190 /* excessive spew detected, request recalibration */
191 priv->spew_flag = SPEW_DETECTED;
192
193 /* fall-through */
194
195 case SPEW_DETECTED:
196 /* only recalibrate when the overall delta to the cursor
197 * is really small. if the spew is causing significant cursor
198 * movement, it is probably a case of the user moving the
199 * cursor very slowly across the screen. */
149 if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { 200 if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
150 hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n", 201 hgpk_err(psmouse, "packet spew detected (%d,%d)\n",
151 priv->x_tally, priv->y_tally); 202 priv->x_tally, priv->y_tally);
203 priv->spew_flag = RECALIBRATING;
152 psmouse_queue_work(psmouse, &priv->recalib_wq, 204 psmouse_queue_work(psmouse, &priv->recalib_wq,
153 msecs_to_jiffies(spew_delay)); 205 msecs_to_jiffies(spew_delay));
154 } 206 }
155 /* reset every 100 packets */ 207
156 priv->count = 0; 208 break;
157 priv->x_tally = 0; 209 case RECALIBRATING:
158 priv->y_tally = 0; 210 /* we already detected a spew and requested a recalibration,
211 * just wait for the queue to kick into action. */
212 break;
159 } 213 }
160} 214}
161 215
@@ -267,30 +321,43 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
267 * If this packet says that the finger was removed, reset our position 321 * If this packet says that the finger was removed, reset our position
268 * tracking so that we don't erroneously detect a jump on next press. 322 * tracking so that we don't erroneously detect a jump on next press.
269 */ 323 */
270 if (!down) 324 if (!down) {
271 priv->abs_x = priv->abs_y = -1; 325 hgpk_reset_hack_state(priv);
326 goto done;
327 }
272 328
273 /* 329 /*
274 * Report position if finger/pen is down, but weed out duplicate 330 * Weed out duplicate packets (we get quite a few, and they mess up
275 * packets (we get quite a few in this mode, and they mess up our 331 * our jump detection)
276 * jump detection.
277 */ 332 */
278 if (down && (x != priv->abs_x || y != priv->abs_y)) { 333 if (x == priv->abs_x && y == priv->abs_y) {
279 334 if (++priv->dupe_count > SPEW_WATCH_COUNT) {
280 /* Don't apply hacks in PT mode, it seems reliable */ 335 if (tpdebug)
281 if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) { 336 hgpk_dbg(psmouse, "hard spew detected\n");
282 hgpk_jumpy_hack(psmouse, 337 priv->spew_flag = RECALIBRATING;
283 priv->abs_x - x, priv->abs_y - y); 338 psmouse_queue_work(psmouse, &priv->recalib_wq,
284 hgpk_spewing_hack(psmouse, left, right, 339 msecs_to_jiffies(spew_delay));
285 priv->abs_x - x, priv->abs_y - y);
286 } 340 }
341 goto done;
342 }
287 343
288 input_report_abs(idev, ABS_X, x); 344 /* not a duplicate, continue with position reporting */
289 input_report_abs(idev, ABS_Y, y); 345 priv->dupe_count = 0;
290 priv->abs_x = x; 346
291 priv->abs_y = y; 347 /* Don't apply hacks in PT mode, it seems reliable */
348 if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) {
349 hgpk_jumpy_hack(psmouse,
350 priv->abs_x - x, priv->abs_y - y);
351 hgpk_spewing_hack(psmouse, left, right,
352 priv->abs_x - x, priv->abs_y - y);
292 } 353 }
293 354
355 input_report_abs(idev, ABS_X, x);
356 input_report_abs(idev, ABS_Y, y);
357 priv->abs_x = x;
358 priv->abs_y = y;
359
360done:
294 input_sync(idev); 361 input_sync(idev);
295} 362}
296 363
@@ -462,13 +529,6 @@ static void hgpk_setup_input_device(struct input_dev *input,
462 } 529 }
463} 530}
464 531
465static void hgpk_reset_hack_state(struct psmouse *psmouse)
466{
467 struct hgpk_data *priv = psmouse->private;
468
469 priv->abs_x = priv->abs_y = -1;
470}
471
472static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate) 532static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate)
473{ 533{
474 int err; 534 int err;