diff options
-rw-r--r-- | drivers/input/mouse/hgpk.c | 106 | ||||
-rw-r--r-- | drivers/input/mouse/hgpk.h | 2 |
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 | |||
43 | static bool tpdebug; | 45 | static bool tpdebug; |
44 | module_param(tpdebug, bool, 0644); | 46 | module_param(tpdebug, bool, 0644); |
45 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | 47 | MODULE_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."); | |||
47 | static int recalib_delta = 100; | 49 | static int recalib_delta = 100; |
48 | module_param(recalib_delta, int, 0644); | 50 | module_param(recalib_delta, int, 0644); |
49 | MODULE_PARM_DESC(recalib_delta, | 51 | MODULE_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 | ||
52 | static int jumpy_delay = 1000; | 55 | static int jumpy_delay = 20; |
53 | module_param(jumpy_delay, int, 0644); | 56 | module_param(jumpy_delay, int, 0644); |
54 | MODULE_PARM_DESC(jumpy_delay, | 57 | MODULE_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 | 104 | static 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 | */ |
106 | static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) | 122 | static 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 | ||
120 | static void hgpk_reset_spew_detection(struct hgpk_data *priv) | 174 | static 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...) \ |