aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/mouse/alps.c254
-rw-r--r--drivers/input/mouse/alps.h1
2 files changed, 228 insertions, 27 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index b03e7e0b4099..f93c2c0daf1f 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -5,6 +5,7 @@
5 * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> 5 * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
6 * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> 6 * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
7 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> 7 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
8 * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
8 * 9 *
9 * ALPS detection, tap switching and status querying info is taken from 10 * ALPS detection, tap switching and status querying info is taken from
10 * tpconfig utility (by C. Scott Ananian and Bruce Kall). 11 * tpconfig utility (by C. Scott Ananian and Bruce Kall).
@@ -28,7 +29,6 @@
28#define dbg(format, arg...) do {} while (0) 29#define dbg(format, arg...) do {} while (0)
29#endif 30#endif
30 31
31
32#define ALPS_OLDPROTO 0x01 /* old style input */ 32#define ALPS_OLDPROTO 0x01 /* old style input */
33#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ 33#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
34#define ALPS_PASS 0x04 /* device has a pass-through port */ 34#define ALPS_PASS 0x04 /* device has a pass-through port */
@@ -37,7 +37,8 @@
37#define ALPS_FW_BK_1 0x10 /* front & back buttons present */ 37#define ALPS_FW_BK_1 0x10 /* front & back buttons present */
38#define ALPS_FW_BK_2 0x20 /* front & back buttons present */ 38#define ALPS_FW_BK_2 0x20 /* front & back buttons present */
39#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ 39#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
40 40#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
41 6-byte ALPS packet */
41 42
42static const struct alps_model_info alps_model_data[] = { 43static const struct alps_model_info alps_model_data[] = {
43 { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ 44 { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -58,7 +59,9 @@ static const struct alps_model_info alps_model_data[] = {
58 { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ 59 { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
59 { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, 60 { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
60 { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ 61 { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
61 { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ 62 /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
63 { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf,
64 ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
62 { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ 65 { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */
63}; 66};
64 67
@@ -69,20 +72,88 @@ static const struct alps_model_info alps_model_data[] = {
69 */ 72 */
70 73
71/* 74/*
72 * ALPS abolute Mode - new format 75 * PS/2 packet format
76 *
77 * byte 0: 0 0 YSGN XSGN 1 M R L
78 * byte 1: X7 X6 X5 X4 X3 X2 X1 X0
79 * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
80 *
81 * Note that the device never signals overflow condition.
82 *
83 * ALPS absolute Mode - new format
73 * 84 *
74 * byte 0: 1 ? ? ? 1 ? ? ? 85 * byte 0: 1 ? ? ? 1 ? ? ?
75 * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 86 * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
76 * byte 2: 0 x10 x9 x8 x7 ? fin ges 87 * byte 2: 0 x10 x9 x8 x7 ? fin ges
77 * byte 3: 0 y9 y8 y7 1 M R L 88 * byte 3: 0 y9 y8 y7 1 M R L
78 * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 89 * byte 4: 0 y6 y5 y4 y3 y2 y1 y0
79 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 90 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0
80 * 91 *
92 * Dualpoint device -- interleaved packet format
93 *
94 * byte 0: 1 1 0 0 1 1 1 1
95 * byte 1: 0 x6 x5 x4 x3 x2 x1 x0
96 * byte 2: 0 x10 x9 x8 x7 0 fin ges
97 * byte 3: 0 0 YSGN XSGN 1 1 1 1
98 * byte 4: X7 X6 X5 X4 X3 X2 X1 X0
99 * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
100 * byte 6: 0 y9 y8 y7 1 m r l
101 * byte 7: 0 y6 y5 y4 y3 y2 y1 y0
102 * byte 8: 0 z6 z5 z4 z3 z2 z1 z0
103 *
104 * CAPITALS = stick, miniscules = touchpad
105 *
81 * ?'s can have different meanings on different models, 106 * ?'s can have different meanings on different models,
82 * such as wheel rotation, extra buttons, stick buttons 107 * such as wheel rotation, extra buttons, stick buttons
83 * on a dualpoint, etc. 108 * on a dualpoint, etc.
84 */ 109 */
85 110
111static bool alps_is_valid_first_byte(const struct alps_model_info *model,
112 unsigned char data)
113{
114 return (data & model->mask0) == model->byte0;
115}
116
117static void alps_report_buttons(struct psmouse *psmouse,
118 struct input_dev *dev1, struct input_dev *dev2,
119 int left, int right, int middle)
120{
121 struct alps_data *priv = psmouse->private;
122 const struct alps_model_info *model = priv->i;
123
124 if (model->flags & ALPS_PS2_INTERLEAVED) {
125 struct input_dev *dev;
126
127 /*
128 * If shared button has already been reported on the
129 * other device (dev2) then this event should be also
130 * sent through that device.
131 */
132 dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1;
133 input_report_key(dev, BTN_LEFT, left);
134
135 dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1;
136 input_report_key(dev, BTN_RIGHT, right);
137
138 dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1;
139 input_report_key(dev, BTN_MIDDLE, middle);
140
141 /*
142 * Sync the _other_ device now, we'll do the first
143 * device later once we report the rest of the events.
144 */
145 input_sync(dev2);
146 } else {
147 /*
148 * For devices with non-interleaved packets we know what
149 * device buttons belong to so we can simply report them.
150 */
151 input_report_key(dev1, BTN_LEFT, left);
152 input_report_key(dev1, BTN_RIGHT, right);
153 input_report_key(dev1, BTN_MIDDLE, middle);
154 }
155}
156
86static void alps_process_packet(struct psmouse *psmouse) 157static void alps_process_packet(struct psmouse *psmouse)
87{ 158{
88 struct alps_data *priv = psmouse->private; 159 struct alps_data *priv = psmouse->private;
@@ -93,18 +164,6 @@ static void alps_process_packet(struct psmouse *psmouse)
93 int x, y, z, ges, fin, left, right, middle; 164 int x, y, z, ges, fin, left, right, middle;
94 int back = 0, forward = 0; 165 int back = 0, forward = 0;
95 166
96 if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
97 input_report_key(dev2, BTN_LEFT, packet[0] & 1);
98 input_report_key(dev2, BTN_RIGHT, packet[0] & 2);
99 input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
100 input_report_rel(dev2, REL_X,
101 packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
102 input_report_rel(dev2, REL_Y,
103 packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
104 input_sync(dev2);
105 return;
106 }
107
108 if (model->flags & ALPS_OLDPROTO) { 167 if (model->flags & ALPS_OLDPROTO) {
109 left = packet[2] & 0x10; 168 left = packet[2] & 0x10;
110 right = packet[2] & 0x08; 169 right = packet[2] & 0x08;
@@ -140,18 +199,13 @@ static void alps_process_packet(struct psmouse *psmouse)
140 input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); 199 input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
141 input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); 200 input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
142 201
143 input_report_key(dev2, BTN_LEFT, left); 202 alps_report_buttons(psmouse, dev2, dev, left, right, middle);
144 input_report_key(dev2, BTN_RIGHT, right);
145 input_report_key(dev2, BTN_MIDDLE, middle);
146 203
147 input_sync(dev);
148 input_sync(dev2); 204 input_sync(dev2);
149 return; 205 return;
150 } 206 }
151 207
152 input_report_key(dev, BTN_LEFT, left); 208 alps_report_buttons(psmouse, dev, dev2, left, right, middle);
153 input_report_key(dev, BTN_RIGHT, right);
154 input_report_key(dev, BTN_MIDDLE, middle);
155 209
156 /* Convert hardware tap to a reasonable Z value */ 210 /* Convert hardware tap to a reasonable Z value */
157 if (ges && !fin) 211 if (ges && !fin)
@@ -202,25 +256,168 @@ static void alps_process_packet(struct psmouse *psmouse)
202 input_sync(dev); 256 input_sync(dev);
203} 257}
204 258
259static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
260 unsigned char packet[],
261 bool report_buttons)
262{
263 struct alps_data *priv = psmouse->private;
264 struct input_dev *dev2 = priv->dev2;
265
266 if (report_buttons)
267 alps_report_buttons(psmouse, dev2, psmouse->dev,
268 packet[0] & 1, packet[0] & 2, packet[0] & 4);
269
270 input_report_rel(dev2, REL_X,
271 packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
272 input_report_rel(dev2, REL_Y,
273 packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
274
275 input_sync(dev2);
276}
277
278static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
279{
280 struct alps_data *priv = psmouse->private;
281
282 if (psmouse->pktcnt < 6)
283 return PSMOUSE_GOOD_DATA;
284
285 if (psmouse->pktcnt == 6) {
286 /*
287 * Start a timer to flush the packet if it ends up last
288 * 6-byte packet in the stream. Timer needs to fire
289 * psmouse core times out itself. 20 ms should be enough
290 * to decide if we are getting more data or not.
291 */
292 mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
293 return PSMOUSE_GOOD_DATA;
294 }
295
296 del_timer(&priv->timer);
297
298 if (psmouse->packet[6] & 0x80) {
299
300 /*
301 * Highest bit is set - that means we either had
302 * complete ALPS packet and this is start of the
303 * next packet or we got garbage.
304 */
305
306 if (((psmouse->packet[3] |
307 psmouse->packet[4] |
308 psmouse->packet[5]) & 0x80) ||
309 (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
310 dbg("refusing packet %x %x %x %x "
311 "(suspected interleaved ps/2)\n",
312 psmouse->packet[3], psmouse->packet[4],
313 psmouse->packet[5], psmouse->packet[6]);
314 return PSMOUSE_BAD_DATA;
315 }
316
317 alps_process_packet(psmouse);
318
319 /* Continue with the next packet */
320 psmouse->packet[0] = psmouse->packet[6];
321 psmouse->pktcnt = 1;
322
323 } else {
324
325 /*
326 * High bit is 0 - that means that we indeed got a PS/2
327 * packet in the middle of ALPS packet.
328 *
329 * There is also possibility that we got 6-byte ALPS
330 * packet followed by 3-byte packet from trackpoint. We
331 * can not distinguish between these 2 scenarios but
332 * becase the latter is unlikely to happen in course of
333 * normal operation (user would need to press all
334 * buttons on the pad and start moving trackpoint
335 * without touching the pad surface) we assume former.
336 * Even if we are wrong the wost thing that would happen
337 * the cursor would jump but we should not get protocol
338 * desynchronization.
339 */
340
341 alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
342 false);
343
344 /*
345 * Continue with the standard ALPS protocol handling,
346 * but make sure we won't process it as an interleaved
347 * packet again, which may happen if all buttons are
348 * pressed. To avoid this let's reset the 4th bit which
349 * is normally 1.
350 */
351 psmouse->packet[3] = psmouse->packet[6] & 0xf7;
352 psmouse->pktcnt = 4;
353 }
354
355 return PSMOUSE_GOOD_DATA;
356}
357
358static void alps_flush_packet(unsigned long data)
359{
360 struct psmouse *psmouse = (struct psmouse *)data;
361
362 serio_pause_rx(psmouse->ps2dev.serio);
363
364 if (psmouse->pktcnt == 6) {
365
366 /*
367 * We did not any more data in reasonable amount of time.
368 * Validate the last 3 bytes and process as a standard
369 * ALPS packet.
370 */
371 if ((psmouse->packet[3] |
372 psmouse->packet[4] |
373 psmouse->packet[5]) & 0x80) {
374 dbg("refusing packet %x %x %x "
375 "(suspected interleaved ps/2)\n",
376 psmouse->packet[3], psmouse->packet[4],
377 psmouse->packet[5]);
378 } else {
379 alps_process_packet(psmouse);
380 }
381 psmouse->pktcnt = 0;
382 }
383
384 serio_continue_rx(psmouse->ps2dev.serio);
385}
386
205static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) 387static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
206{ 388{
207 struct alps_data *priv = psmouse->private; 389 struct alps_data *priv = psmouse->private;
390 const struct alps_model_info *model = priv->i;
208 391
209 if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ 392 if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
210 if (psmouse->pktcnt == 3) { 393 if (psmouse->pktcnt == 3) {
211 alps_process_packet(psmouse); 394 alps_report_bare_ps2_packet(psmouse, psmouse->packet,
395 true);
212 return PSMOUSE_FULL_PACKET; 396 return PSMOUSE_FULL_PACKET;
213 } 397 }
214 return PSMOUSE_GOOD_DATA; 398 return PSMOUSE_GOOD_DATA;
215 } 399 }
216 400
217 if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0) 401 /* Check for PS/2 packet stuffed in the middle of ALPS packet. */
402
403 if ((model->flags & ALPS_PS2_INTERLEAVED) &&
404 psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
405 return alps_handle_interleaved_ps2(psmouse);
406 }
407
408 if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
409 dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
410 psmouse->packet[0], model->mask0, model->byte0);
218 return PSMOUSE_BAD_DATA; 411 return PSMOUSE_BAD_DATA;
412 }
219 413
220 /* Bytes 2 - 6 should have 0 in the highest bit */ 414 /* Bytes 2 - 6 should have 0 in the highest bit */
221 if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && 415 if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
222 (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) 416 (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
417 dbg("refusing packet[%i] = %x\n",
418 psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
223 return PSMOUSE_BAD_DATA; 419 return PSMOUSE_BAD_DATA;
420 }
224 421
225 if (psmouse->pktcnt == 6) { 422 if (psmouse->pktcnt == 6) {
226 alps_process_packet(psmouse); 423 alps_process_packet(psmouse);
@@ -459,6 +656,7 @@ static void alps_disconnect(struct psmouse *psmouse)
459 struct alps_data *priv = psmouse->private; 656 struct alps_data *priv = psmouse->private;
460 657
461 psmouse_reset(psmouse); 658 psmouse_reset(psmouse);
659 del_timer_sync(&priv->timer);
462 input_unregister_device(priv->dev2); 660 input_unregister_device(priv->dev2);
463 kfree(priv); 661 kfree(priv);
464} 662}
@@ -476,6 +674,8 @@ int alps_init(struct psmouse *psmouse)
476 goto init_fail; 674 goto init_fail;
477 675
478 priv->dev2 = dev2; 676 priv->dev2 = dev2;
677 setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
678
479 psmouse->private = priv; 679 psmouse->private = priv;
480 680
481 model = alps_get_model(psmouse, &version); 681 model = alps_get_model(psmouse, &version);
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index bc87936fee1a..904ed8b3c8be 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -23,6 +23,7 @@ struct alps_data {
23 char phys[32]; /* Phys */ 23 char phys[32]; /* Phys */
24 const struct alps_model_info *i;/* Info */ 24 const struct alps_model_info *i;/* Info */
25 int prev_fin; /* Finger bit from previous packet */ 25 int prev_fin; /* Finger bit from previous packet */
26 struct timer_list timer;
26}; 27};
27 28
28#ifdef CONFIG_MOUSE_PS2_ALPS 29#ifdef CONFIG_MOUSE_PS2_ALPS