aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/hgpk.c106
-rw-r--r--drivers/input/mouse/hgpk.h2
2 files changed, 88 insertions, 20 deletions
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index 222594742c39..b54f074ec307 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -40,6 +40,8 @@
40#include "psmouse.h" 40#include "psmouse.h"
41#include "hgpk.h" 41#include "hgpk.h"
42 42
43#define ILLEGAL_XY 999999
44
43static bool tpdebug; 45static bool tpdebug;
44module_param(tpdebug, bool, 0644); 46module_param(tpdebug, bool, 0644);
45MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); 47MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
@@ -47,9 +49,10 @@ MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
47static int recalib_delta = 100; 49static int recalib_delta = 100;
48module_param(recalib_delta, int, 0644); 50module_param(recalib_delta, int, 0644);
49MODULE_PARM_DESC(recalib_delta, 51MODULE_PARM_DESC(recalib_delta,
50 "packets containing a delta this large will cause a recalibration."); 52 "packets containing a delta this large will be discarded, and a "
53 "recalibration may be scheduled.");
51 54
52static int jumpy_delay = 1000; 55static int jumpy_delay = 20;
53module_param(jumpy_delay, int, 0644); 56module_param(jumpy_delay, int, 0644);
54MODULE_PARM_DESC(jumpy_delay, 57MODULE_PARM_DESC(jumpy_delay,
55 "delay (ms) before recal after jumpiness detected"); 58 "delay (ms) before recal after jumpiness detected");
@@ -96,25 +99,76 @@ static int hgpk_mode_from_name(const char *buf, int len)
96} 99}
97 100
98/* 101/*
99 * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" 102 * see if new value is within 20% of half of old value
100 * above the pad and still have it send packets. This causes a jump cursor 103 */
101 * when one places their finger on the pad. We can probably detect the 104static int approx_half(int curr, int prev)
102 * jump as we see a large deltas (>= 100px). In mouse mode, I've been 105{
103 * unable to even come close to 100px deltas during normal usage, so I think 106 int belowhalf, abovehalf;
104 * this threshold is safe. If a large delta occurs, trigger a recalibration. 107
108 if (curr < 5 || prev < 5)
109 return 0;
110
111 belowhalf = (prev * 8) / 20;
112 abovehalf = (prev * 12) / 20;
113
114 return belowhalf < curr && curr <= abovehalf;
115}
116
117/*
118 * Throw out oddly large delta packets, and any that immediately follow whose
119 * values are each approximately half of the previous. It seems that the ALPS
120 * firmware emits errant packets, and they get averaged out slowly.
105 */ 121 */
106static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) 122static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y)
107{ 123{
108 struct hgpk_data *priv = psmouse->private; 124 struct hgpk_data *priv = psmouse->private;
125 int avx, avy;
126 bool do_recal = false;
127
128 avx = abs(x);
129 avy = abs(y);
130
131 /* discard if too big, or half that but > 4 times the prev delta */
132 if (avx > recalib_delta ||
133 (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) {
134 hgpk_err(psmouse, "detected %dpx jump in x\n", x);
135 priv->xbigj = avx;
136 } else if (approx_half(avx, priv->xbigj)) {
137 hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x);
138 priv->xbigj = avx;
139 priv->xsaw_secondary++;
140 } else {
141 if (priv->xbigj && priv->xsaw_secondary > 1)
142 do_recal = true;
143 priv->xbigj = 0;
144 priv->xsaw_secondary = 0;
145 }
109 146
110 if (abs(x) > recalib_delta || abs(y) > recalib_delta) { 147 if (avy > recalib_delta ||
111 hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n", 148 (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) {
112 recalib_delta, x, y); 149 hgpk_err(psmouse, "detected %dpx jump in y\n", y);
113 /* My car gets forty rods to the hogshead and that's the 150 priv->ybigj = avy;
114 * way I likes it! */ 151 } else if (approx_half(avy, priv->ybigj)) {
152 hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y);
153 priv->ybigj = avy;
154 priv->ysaw_secondary++;
155 } else {
156 if (priv->ybigj && priv->ysaw_secondary > 1)
157 do_recal = true;
158 priv->ybigj = 0;
159 priv->ysaw_secondary = 0;
160 }
161
162 priv->xlast = avx;
163 priv->ylast = avy;
164
165 if (do_recal && jumpy_delay) {
166 hgpk_err(psmouse, "scheduling recalibration\n");
115 psmouse_queue_work(psmouse, &priv->recalib_wq, 167 psmouse_queue_work(psmouse, &priv->recalib_wq,
116 msecs_to_jiffies(jumpy_delay)); 168 msecs_to_jiffies(jumpy_delay));
117 } 169 }
170
171 return priv->xbigj || priv->ybigj;
118} 172}
119 173
120static void hgpk_reset_spew_detection(struct hgpk_data *priv) 174static void hgpk_reset_spew_detection(struct hgpk_data *priv)
@@ -131,6 +185,9 @@ static void hgpk_reset_hack_state(struct psmouse *psmouse)
131 struct hgpk_data *priv = psmouse->private; 185 struct hgpk_data *priv = psmouse->private;
132 186
133 priv->abs_x = priv->abs_y = -1; 187 priv->abs_x = priv->abs_y = -1;
188 priv->xlast = priv->ylast = ILLEGAL_XY;
189 priv->xbigj = priv->ybigj = 0;
190 priv->xsaw_secondary = priv->ysaw_secondary = 0;
134 hgpk_reset_spew_detection(priv); 191 hgpk_reset_spew_detection(priv);
135} 192}
136 193
@@ -322,7 +379,7 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
322 * tracking so that we don't erroneously detect a jump on next press. 379 * tracking so that we don't erroneously detect a jump on next press.
323 */ 380 */
324 if (!down) { 381 if (!down) {
325 hgpk_reset_hack_state(priv); 382 hgpk_reset_hack_state(psmouse);
326 goto done; 383 goto done;
327 } 384 }
328 385
@@ -346,10 +403,14 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse)
346 403
347 /* Don't apply hacks in PT mode, it seems reliable */ 404 /* Don't apply hacks in PT mode, it seems reliable */
348 if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) { 405 if (priv->mode != HGPK_MODE_PENTABLET && priv->abs_x != -1) {
349 hgpk_jumpy_hack(psmouse, 406 int x_diff = priv->abs_x - x;
350 priv->abs_x - x, priv->abs_y - y); 407 int y_diff = priv->abs_y - y;
351 hgpk_spewing_hack(psmouse, left, right, 408 if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) {
352 priv->abs_x - x, priv->abs_y - y); 409 if (tpdebug)
410 hgpk_dbg(psmouse, "discarding\n");
411 goto done;
412 }
413 hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff);
353 } 414 }
354 415
355 input_report_abs(idev, ABS_X, x); 416 input_report_abs(idev, ABS_X, x);
@@ -370,7 +431,12 @@ static void hgpk_process_simple_packet(struct psmouse *psmouse)
370 int x = packet[1] - ((packet[0] << 4) & 0x100); 431 int x = packet[1] - ((packet[0] << 4) & 0x100);
371 int y = ((packet[0] << 3) & 0x100) - packet[2]; 432 int y = ((packet[0] << 3) & 0x100) - packet[2];
372 433
373 hgpk_jumpy_hack(psmouse, x, y); 434 if (hgpk_discard_decay_hack(psmouse, x, y)) {
435 if (tpdebug)
436 hgpk_dbg(psmouse, "discarding\n");
437 return;
438 }
439
374 hgpk_spewing_hack(psmouse, left, right, x, y); 440 hgpk_spewing_hack(psmouse, left, right, x, y);
375 441
376 if (tpdebug) 442 if (tpdebug)
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h
index bccdb26dca49..311c0e87fcbf 100644
--- a/drivers/input/mouse/hgpk.h
+++ b/drivers/input/mouse/hgpk.h
@@ -42,6 +42,8 @@ struct hgpk_data {
42 struct delayed_work recalib_wq; 42 struct delayed_work recalib_wq;
43 int abs_x, abs_y; 43 int abs_x, abs_y;
44 int dupe_count; 44 int dupe_count;
45 int xbigj, ybigj, xlast, ylast; /* jumpiness detection */
46 int xsaw_secondary, ysaw_secondary; /* jumpiness detection */
45}; 47};
46 48
47#define hgpk_dbg(psmouse, format, arg...) \ 49#define hgpk_dbg(psmouse, format, arg...) \