diff options
Diffstat (limited to 'drivers/input/mouse/alps.c')
-rw-r--r-- | drivers/input/mouse/alps.c | 351 |
1 files changed, 291 insertions, 60 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f36110689aae..99d58764ef03 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). |
@@ -14,6 +15,7 @@ | |||
14 | * the Free Software Foundation. | 15 | * the Free Software Foundation. |
15 | */ | 16 | */ |
16 | 17 | ||
18 | #include <linux/slab.h> | ||
17 | #include <linux/input.h> | 19 | #include <linux/input.h> |
18 | #include <linux/serio.h> | 20 | #include <linux/serio.h> |
19 | #include <linux/libps2.h> | 21 | #include <linux/libps2.h> |
@@ -28,13 +30,16 @@ | |||
28 | #define dbg(format, arg...) do {} while (0) | 30 | #define dbg(format, arg...) do {} while (0) |
29 | #endif | 31 | #endif |
30 | 32 | ||
31 | #define ALPS_DUALPOINT 0x01 | 33 | #define ALPS_OLDPROTO 0x01 /* old style input */ |
32 | #define ALPS_WHEEL 0x02 | 34 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ |
33 | #define ALPS_FW_BK_1 0x04 | 35 | #define ALPS_PASS 0x04 /* device has a pass-through port */ |
34 | #define ALPS_4BTN 0x08 | 36 | |
35 | #define ALPS_OLDPROTO 0x10 | 37 | #define ALPS_WHEEL 0x08 /* hardware wheel present */ |
36 | #define ALPS_PASS 0x20 | 38 | #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ |
37 | #define ALPS_FW_BK_2 0x40 | 39 | #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ |
40 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ | ||
41 | #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with | ||
42 | 6-byte ALPS packet */ | ||
38 | 43 | ||
39 | static const struct alps_model_info alps_model_data[] = { | 44 | static const struct alps_model_info alps_model_data[] = { |
40 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | 45 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ |
@@ -55,8 +60,12 @@ static const struct alps_model_info alps_model_data[] = { | |||
55 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 60 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
56 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 61 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
57 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 62 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
58 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ | 63 | /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ |
59 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */ | 64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, |
65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, | ||
66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ | ||
67 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, | ||
68 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ | ||
60 | }; | 69 | }; |
61 | 70 | ||
62 | /* | 71 | /* |
@@ -66,42 +75,86 @@ static const struct alps_model_info alps_model_data[] = { | |||
66 | */ | 75 | */ |
67 | 76 | ||
68 | /* | 77 | /* |
69 | * ALPS abolute Mode - new format | 78 | * PS/2 packet format |
79 | * | ||
80 | * byte 0: 0 0 YSGN XSGN 1 M R L | ||
81 | * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 | ||
82 | * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
83 | * | ||
84 | * Note that the device never signals overflow condition. | ||
85 | * | ||
86 | * ALPS absolute Mode - new format | ||
70 | * | 87 | * |
71 | * byte 0: 1 ? ? ? 1 ? ? ? | 88 | * byte 0: 1 ? ? ? 1 ? ? ? |
72 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | 89 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 |
73 | * byte 2: 0 x10 x9 x8 x7 ? fin ges | 90 | * byte 2: 0 x10 x9 x8 x7 ? fin ges |
74 | * byte 3: 0 y9 y8 y7 1 M R L | 91 | * byte 3: 0 y9 y8 y7 1 M R L |
75 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | 92 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 |
76 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | 93 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 |
77 | * | 94 | * |
95 | * Dualpoint device -- interleaved packet format | ||
96 | * | ||
97 | * byte 0: 1 1 0 0 1 1 1 1 | ||
98 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | ||
99 | * byte 2: 0 x10 x9 x8 x7 0 fin ges | ||
100 | * byte 3: 0 0 YSGN XSGN 1 1 1 1 | ||
101 | * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 | ||
102 | * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
103 | * byte 6: 0 y9 y8 y7 1 m r l | ||
104 | * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 | ||
105 | * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 | ||
106 | * | ||
107 | * CAPITALS = stick, miniscules = touchpad | ||
108 | * | ||
78 | * ?'s can have different meanings on different models, | 109 | * ?'s can have different meanings on different models, |
79 | * such as wheel rotation, extra buttons, stick buttons | 110 | * such as wheel rotation, extra buttons, stick buttons |
80 | * on a dualpoint, etc. | 111 | * on a dualpoint, etc. |
81 | */ | 112 | */ |
82 | 113 | ||
114 | static bool alps_is_valid_first_byte(const struct alps_model_info *model, | ||
115 | unsigned char data) | ||
116 | { | ||
117 | return (data & model->mask0) == model->byte0; | ||
118 | } | ||
119 | |||
120 | static void alps_report_buttons(struct psmouse *psmouse, | ||
121 | struct input_dev *dev1, struct input_dev *dev2, | ||
122 | int left, int right, int middle) | ||
123 | { | ||
124 | struct input_dev *dev; | ||
125 | |||
126 | /* | ||
127 | * If shared button has already been reported on the | ||
128 | * other device (dev2) then this event should be also | ||
129 | * sent through that device. | ||
130 | */ | ||
131 | dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; | ||
132 | input_report_key(dev, BTN_LEFT, left); | ||
133 | |||
134 | dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; | ||
135 | input_report_key(dev, BTN_RIGHT, right); | ||
136 | |||
137 | dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; | ||
138 | input_report_key(dev, BTN_MIDDLE, middle); | ||
139 | |||
140 | /* | ||
141 | * Sync the _other_ device now, we'll do the first | ||
142 | * device later once we report the rest of the events. | ||
143 | */ | ||
144 | input_sync(dev2); | ||
145 | } | ||
146 | |||
83 | static void alps_process_packet(struct psmouse *psmouse) | 147 | static void alps_process_packet(struct psmouse *psmouse) |
84 | { | 148 | { |
85 | struct alps_data *priv = psmouse->private; | 149 | struct alps_data *priv = psmouse->private; |
150 | const struct alps_model_info *model = priv->i; | ||
86 | unsigned char *packet = psmouse->packet; | 151 | unsigned char *packet = psmouse->packet; |
87 | struct input_dev *dev = psmouse->dev; | 152 | struct input_dev *dev = psmouse->dev; |
88 | struct input_dev *dev2 = priv->dev2; | 153 | struct input_dev *dev2 = priv->dev2; |
89 | int x, y, z, ges, fin, left, right, middle; | 154 | int x, y, z, ges, fin, left, right, middle; |
90 | int back = 0, forward = 0; | 155 | int back = 0, forward = 0; |
91 | 156 | ||
92 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ | 157 | if (model->flags & ALPS_OLDPROTO) { |
93 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); | ||
94 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); | ||
95 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); | ||
96 | input_report_rel(dev2, REL_X, | ||
97 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | ||
98 | input_report_rel(dev2, REL_Y, | ||
99 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | ||
100 | input_sync(dev2); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | if (priv->i->flags & ALPS_OLDPROTO) { | ||
105 | left = packet[2] & 0x10; | 158 | left = packet[2] & 0x10; |
106 | right = packet[2] & 0x08; | 159 | right = packet[2] & 0x08; |
107 | middle = 0; | 160 | middle = 0; |
@@ -117,12 +170,12 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
117 | z = packet[5]; | 170 | z = packet[5]; |
118 | } | 171 | } |
119 | 172 | ||
120 | if (priv->i->flags & ALPS_FW_BK_1) { | 173 | if (model->flags & ALPS_FW_BK_1) { |
121 | back = packet[0] & 0x10; | 174 | back = packet[0] & 0x10; |
122 | forward = packet[2] & 4; | 175 | forward = packet[2] & 4; |
123 | } | 176 | } |
124 | 177 | ||
125 | if (priv->i->flags & ALPS_FW_BK_2) { | 178 | if (model->flags & ALPS_FW_BK_2) { |
126 | back = packet[3] & 4; | 179 | back = packet[3] & 4; |
127 | forward = packet[2] & 4; | 180 | forward = packet[2] & 4; |
128 | if ((middle = forward && back)) | 181 | if ((middle = forward && back)) |
@@ -132,25 +185,21 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
132 | ges = packet[2] & 1; | 185 | ges = packet[2] & 1; |
133 | fin = packet[2] & 2; | 186 | fin = packet[2] & 2; |
134 | 187 | ||
135 | if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) { | 188 | if ((model->flags & ALPS_DUALPOINT) && z == 127) { |
136 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); | 189 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); |
137 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); | 190 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); |
138 | 191 | ||
139 | input_report_key(dev2, BTN_LEFT, left); | 192 | alps_report_buttons(psmouse, dev2, dev, left, right, middle); |
140 | input_report_key(dev2, BTN_RIGHT, right); | ||
141 | input_report_key(dev2, BTN_MIDDLE, middle); | ||
142 | 193 | ||
143 | input_sync(dev); | ||
144 | input_sync(dev2); | 194 | input_sync(dev2); |
145 | return; | 195 | return; |
146 | } | 196 | } |
147 | 197 | ||
148 | input_report_key(dev, BTN_LEFT, left); | 198 | alps_report_buttons(psmouse, dev, dev2, left, right, middle); |
149 | input_report_key(dev, BTN_RIGHT, right); | ||
150 | input_report_key(dev, BTN_MIDDLE, middle); | ||
151 | 199 | ||
152 | /* Convert hardware tap to a reasonable Z value */ | 200 | /* Convert hardware tap to a reasonable Z value */ |
153 | if (ges && !fin) z = 40; | 201 | if (ges && !fin) |
202 | z = 40; | ||
154 | 203 | ||
155 | /* | 204 | /* |
156 | * A "tap and drag" operation is reported by the hardware as a transition | 205 | * A "tap and drag" operation is reported by the hardware as a transition |
@@ -166,8 +215,10 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
166 | } | 215 | } |
167 | priv->prev_fin = fin; | 216 | priv->prev_fin = fin; |
168 | 217 | ||
169 | if (z > 30) input_report_key(dev, BTN_TOUCH, 1); | 218 | if (z > 30) |
170 | if (z < 25) input_report_key(dev, BTN_TOUCH, 0); | 219 | input_report_key(dev, BTN_TOUCH, 1); |
220 | if (z < 25) | ||
221 | input_report_key(dev, BTN_TOUCH, 0); | ||
171 | 222 | ||
172 | if (z > 0) { | 223 | if (z > 0) { |
173 | input_report_abs(dev, ABS_X, x); | 224 | input_report_abs(dev, ABS_X, x); |
@@ -177,36 +228,186 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
177 | input_report_abs(dev, ABS_PRESSURE, z); | 228 | input_report_abs(dev, ABS_PRESSURE, z); |
178 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 229 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
179 | 230 | ||
180 | if (priv->i->flags & ALPS_WHEEL) | 231 | if (model->flags & ALPS_WHEEL) |
181 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); | 232 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); |
182 | 233 | ||
183 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 234 | if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
184 | input_report_key(dev, BTN_FORWARD, forward); | 235 | input_report_key(dev, BTN_FORWARD, forward); |
185 | input_report_key(dev, BTN_BACK, back); | 236 | input_report_key(dev, BTN_BACK, back); |
186 | } | 237 | } |
187 | 238 | ||
239 | if (model->flags & ALPS_FOUR_BUTTONS) { | ||
240 | input_report_key(dev, BTN_0, packet[2] & 4); | ||
241 | input_report_key(dev, BTN_1, packet[0] & 0x10); | ||
242 | input_report_key(dev, BTN_2, packet[3] & 4); | ||
243 | input_report_key(dev, BTN_3, packet[0] & 0x20); | ||
244 | } | ||
245 | |||
188 | input_sync(dev); | 246 | input_sync(dev); |
189 | } | 247 | } |
190 | 248 | ||
249 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, | ||
250 | unsigned char packet[], | ||
251 | bool report_buttons) | ||
252 | { | ||
253 | struct alps_data *priv = psmouse->private; | ||
254 | struct input_dev *dev2 = priv->dev2; | ||
255 | |||
256 | if (report_buttons) | ||
257 | alps_report_buttons(psmouse, dev2, psmouse->dev, | ||
258 | packet[0] & 1, packet[0] & 2, packet[0] & 4); | ||
259 | |||
260 | input_report_rel(dev2, REL_X, | ||
261 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | ||
262 | input_report_rel(dev2, REL_Y, | ||
263 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | ||
264 | |||
265 | input_sync(dev2); | ||
266 | } | ||
267 | |||
268 | static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | ||
269 | { | ||
270 | struct alps_data *priv = psmouse->private; | ||
271 | |||
272 | if (psmouse->pktcnt < 6) | ||
273 | return PSMOUSE_GOOD_DATA; | ||
274 | |||
275 | if (psmouse->pktcnt == 6) { | ||
276 | /* | ||
277 | * Start a timer to flush the packet if it ends up last | ||
278 | * 6-byte packet in the stream. Timer needs to fire | ||
279 | * psmouse core times out itself. 20 ms should be enough | ||
280 | * to decide if we are getting more data or not. | ||
281 | */ | ||
282 | mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); | ||
283 | return PSMOUSE_GOOD_DATA; | ||
284 | } | ||
285 | |||
286 | del_timer(&priv->timer); | ||
287 | |||
288 | if (psmouse->packet[6] & 0x80) { | ||
289 | |||
290 | /* | ||
291 | * Highest bit is set - that means we either had | ||
292 | * complete ALPS packet and this is start of the | ||
293 | * next packet or we got garbage. | ||
294 | */ | ||
295 | |||
296 | if (((psmouse->packet[3] | | ||
297 | psmouse->packet[4] | | ||
298 | psmouse->packet[5]) & 0x80) || | ||
299 | (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { | ||
300 | dbg("refusing packet %x %x %x %x " | ||
301 | "(suspected interleaved ps/2)\n", | ||
302 | psmouse->packet[3], psmouse->packet[4], | ||
303 | psmouse->packet[5], psmouse->packet[6]); | ||
304 | return PSMOUSE_BAD_DATA; | ||
305 | } | ||
306 | |||
307 | alps_process_packet(psmouse); | ||
308 | |||
309 | /* Continue with the next packet */ | ||
310 | psmouse->packet[0] = psmouse->packet[6]; | ||
311 | psmouse->pktcnt = 1; | ||
312 | |||
313 | } else { | ||
314 | |||
315 | /* | ||
316 | * High bit is 0 - that means that we indeed got a PS/2 | ||
317 | * packet in the middle of ALPS packet. | ||
318 | * | ||
319 | * There is also possibility that we got 6-byte ALPS | ||
320 | * packet followed by 3-byte packet from trackpoint. We | ||
321 | * can not distinguish between these 2 scenarios but | ||
322 | * becase the latter is unlikely to happen in course of | ||
323 | * normal operation (user would need to press all | ||
324 | * buttons on the pad and start moving trackpoint | ||
325 | * without touching the pad surface) we assume former. | ||
326 | * Even if we are wrong the wost thing that would happen | ||
327 | * the cursor would jump but we should not get protocol | ||
328 | * desynchronization. | ||
329 | */ | ||
330 | |||
331 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], | ||
332 | false); | ||
333 | |||
334 | /* | ||
335 | * Continue with the standard ALPS protocol handling, | ||
336 | * but make sure we won't process it as an interleaved | ||
337 | * packet again, which may happen if all buttons are | ||
338 | * pressed. To avoid this let's reset the 4th bit which | ||
339 | * is normally 1. | ||
340 | */ | ||
341 | psmouse->packet[3] = psmouse->packet[6] & 0xf7; | ||
342 | psmouse->pktcnt = 4; | ||
343 | } | ||
344 | |||
345 | return PSMOUSE_GOOD_DATA; | ||
346 | } | ||
347 | |||
348 | static void alps_flush_packet(unsigned long data) | ||
349 | { | ||
350 | struct psmouse *psmouse = (struct psmouse *)data; | ||
351 | |||
352 | serio_pause_rx(psmouse->ps2dev.serio); | ||
353 | |||
354 | if (psmouse->pktcnt == 6) { | ||
355 | |||
356 | /* | ||
357 | * We did not any more data in reasonable amount of time. | ||
358 | * Validate the last 3 bytes and process as a standard | ||
359 | * ALPS packet. | ||
360 | */ | ||
361 | if ((psmouse->packet[3] | | ||
362 | psmouse->packet[4] | | ||
363 | psmouse->packet[5]) & 0x80) { | ||
364 | dbg("refusing packet %x %x %x " | ||
365 | "(suspected interleaved ps/2)\n", | ||
366 | psmouse->packet[3], psmouse->packet[4], | ||
367 | psmouse->packet[5]); | ||
368 | } else { | ||
369 | alps_process_packet(psmouse); | ||
370 | } | ||
371 | psmouse->pktcnt = 0; | ||
372 | } | ||
373 | |||
374 | serio_continue_rx(psmouse->ps2dev.serio); | ||
375 | } | ||
376 | |||
191 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | 377 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) |
192 | { | 378 | { |
193 | struct alps_data *priv = psmouse->private; | 379 | struct alps_data *priv = psmouse->private; |
380 | const struct alps_model_info *model = priv->i; | ||
194 | 381 | ||
195 | if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ | 382 | if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ |
196 | if (psmouse->pktcnt == 3) { | 383 | if (psmouse->pktcnt == 3) { |
197 | alps_process_packet(psmouse); | 384 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
385 | true); | ||
198 | return PSMOUSE_FULL_PACKET; | 386 | return PSMOUSE_FULL_PACKET; |
199 | } | 387 | } |
200 | return PSMOUSE_GOOD_DATA; | 388 | return PSMOUSE_GOOD_DATA; |
201 | } | 389 | } |
202 | 390 | ||
203 | if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0) | 391 | /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ |
392 | |||
393 | if ((model->flags & ALPS_PS2_INTERLEAVED) && | ||
394 | psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { | ||
395 | return alps_handle_interleaved_ps2(psmouse); | ||
396 | } | ||
397 | |||
398 | if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { | ||
399 | dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", | ||
400 | psmouse->packet[0], model->mask0, model->byte0); | ||
204 | return PSMOUSE_BAD_DATA; | 401 | return PSMOUSE_BAD_DATA; |
402 | } | ||
205 | 403 | ||
206 | /* Bytes 2 - 6 should have 0 in the highest bit */ | 404 | /* Bytes 2 - 6 should have 0 in the highest bit */ |
207 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && | 405 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && |
208 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) | 406 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
407 | dbg("refusing packet[%i] = %x\n", | ||
408 | psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); | ||
209 | return PSMOUSE_BAD_DATA; | 409 | return PSMOUSE_BAD_DATA; |
410 | } | ||
210 | 411 | ||
211 | if (psmouse->pktcnt == 6) { | 412 | if (psmouse->pktcnt == 6) { |
212 | alps_process_packet(psmouse); | 413 | alps_process_packet(psmouse); |
@@ -393,15 +594,12 @@ static int alps_poll(struct psmouse *psmouse) | |||
393 | return 0; | 594 | return 0; |
394 | } | 595 | } |
395 | 596 | ||
396 | static int alps_hw_init(struct psmouse *psmouse, int *version) | 597 | static int alps_hw_init(struct psmouse *psmouse) |
397 | { | 598 | { |
398 | struct alps_data *priv = psmouse->private; | 599 | struct alps_data *priv = psmouse->private; |
600 | const struct alps_model_info *model = priv->i; | ||
399 | 601 | ||
400 | priv->i = alps_get_model(psmouse, version); | 602 | if ((model->flags & ALPS_PASS) && |
401 | if (!priv->i) | ||
402 | return -1; | ||
403 | |||
404 | if ((priv->i->flags & ALPS_PASS) && | ||
405 | alps_passthrough_mode(psmouse, true)) { | 603 | alps_passthrough_mode(psmouse, true)) { |
406 | return -1; | 604 | return -1; |
407 | } | 605 | } |
@@ -416,7 +614,7 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
416 | return -1; | 614 | return -1; |
417 | } | 615 | } |
418 | 616 | ||
419 | if ((priv->i->flags & ALPS_PASS) && | 617 | if ((model->flags & ALPS_PASS) && |
420 | alps_passthrough_mode(psmouse, false)) { | 618 | alps_passthrough_mode(psmouse, false)) { |
421 | return -1; | 619 | return -1; |
422 | } | 620 | } |
@@ -432,12 +630,15 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
432 | 630 | ||
433 | static int alps_reconnect(struct psmouse *psmouse) | 631 | static int alps_reconnect(struct psmouse *psmouse) |
434 | { | 632 | { |
633 | const struct alps_model_info *model; | ||
634 | |||
435 | psmouse_reset(psmouse); | 635 | psmouse_reset(psmouse); |
436 | 636 | ||
437 | if (alps_hw_init(psmouse, NULL)) | 637 | model = alps_get_model(psmouse, NULL); |
638 | if (!model) | ||
438 | return -1; | 639 | return -1; |
439 | 640 | ||
440 | return 0; | 641 | return alps_hw_init(psmouse); |
441 | } | 642 | } |
442 | 643 | ||
443 | static void alps_disconnect(struct psmouse *psmouse) | 644 | static void alps_disconnect(struct psmouse *psmouse) |
@@ -445,6 +646,7 @@ static void alps_disconnect(struct psmouse *psmouse) | |||
445 | struct alps_data *priv = psmouse->private; | 646 | struct alps_data *priv = psmouse->private; |
446 | 647 | ||
447 | psmouse_reset(psmouse); | 648 | psmouse_reset(psmouse); |
649 | del_timer_sync(&priv->timer); | ||
448 | input_unregister_device(priv->dev2); | 650 | input_unregister_device(priv->dev2); |
449 | kfree(priv); | 651 | kfree(priv); |
450 | } | 652 | } |
@@ -452,6 +654,7 @@ static void alps_disconnect(struct psmouse *psmouse) | |||
452 | int alps_init(struct psmouse *psmouse) | 654 | int alps_init(struct psmouse *psmouse) |
453 | { | 655 | { |
454 | struct alps_data *priv; | 656 | struct alps_data *priv; |
657 | const struct alps_model_info *model; | ||
455 | struct input_dev *dev1 = psmouse->dev, *dev2; | 658 | struct input_dev *dev1 = psmouse->dev, *dev2; |
456 | int version; | 659 | int version; |
457 | 660 | ||
@@ -461,35 +664,63 @@ int alps_init(struct psmouse *psmouse) | |||
461 | goto init_fail; | 664 | goto init_fail; |
462 | 665 | ||
463 | priv->dev2 = dev2; | 666 | priv->dev2 = dev2; |
667 | setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); | ||
668 | |||
464 | psmouse->private = priv; | 669 | psmouse->private = priv; |
465 | 670 | ||
466 | if (alps_hw_init(psmouse, &version)) | 671 | model = alps_get_model(psmouse, &version); |
672 | if (!model) | ||
673 | goto init_fail; | ||
674 | |||
675 | priv->i = model; | ||
676 | |||
677 | if (alps_hw_init(psmouse)) | ||
467 | goto init_fail; | 678 | goto init_fail; |
468 | 679 | ||
680 | /* | ||
681 | * Undo part of setup done for us by psmouse core since touchpad | ||
682 | * is not a relative device. | ||
683 | */ | ||
684 | __clear_bit(EV_REL, dev1->evbit); | ||
685 | __clear_bit(REL_X, dev1->relbit); | ||
686 | __clear_bit(REL_Y, dev1->relbit); | ||
687 | |||
688 | /* | ||
689 | * Now set up our capabilities. | ||
690 | */ | ||
469 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); | 691 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); |
470 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); | 692 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); |
471 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); | 693 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); |
472 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | | 694 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= |
473 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 695 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); |
474 | 696 | ||
475 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 697 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
476 | input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); | 698 | input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); |
477 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); | 699 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); |
478 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | 700 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); |
479 | 701 | ||
480 | if (priv->i->flags & ALPS_WHEEL) { | 702 | if (model->flags & ALPS_WHEEL) { |
481 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 703 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
482 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); | 704 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); |
483 | } | 705 | } |
484 | 706 | ||
485 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 707 | if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
486 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); | 708 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); |
487 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); | 709 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); |
488 | } | 710 | } |
489 | 711 | ||
712 | if (model->flags & ALPS_FOUR_BUTTONS) { | ||
713 | dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); | ||
714 | dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); | ||
715 | dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); | ||
716 | dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); | ||
717 | } else { | ||
718 | dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); | ||
719 | } | ||
720 | |||
490 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); | 721 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); |
491 | dev2->phys = priv->phys; | 722 | dev2->phys = priv->phys; |
492 | dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; | 723 | dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; |
493 | dev2->id.bustype = BUS_I8042; | 724 | dev2->id.bustype = BUS_I8042; |
494 | dev2->id.vendor = 0x0002; | 725 | dev2->id.vendor = 0x0002; |
495 | dev2->id.product = PSMOUSE_ALPS; | 726 | dev2->id.product = PSMOUSE_ALPS; |
@@ -497,9 +728,9 @@ int alps_init(struct psmouse *psmouse) | |||
497 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; | 728 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; |
498 | 729 | ||
499 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 730 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
500 | dev2->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 731 | dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
501 | dev2->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | | 732 | dev2->keybit[BIT_WORD(BTN_LEFT)] = |
502 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 733 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
503 | 734 | ||
504 | if (input_register_device(priv->dev2)) | 735 | if (input_register_device(priv->dev2)) |
505 | goto init_fail; | 736 | goto init_fail; |