diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/input/mouse/alps.c | 254 | ||||
| -rw-r--r-- | drivers/input/mouse/alps.h | 1 |
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 | ||
| 42 | static const struct alps_model_info alps_model_data[] = { | 43 | static 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 | ||
| 111 | static 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 | |||
| 117 | static 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 | |||
| 86 | static void alps_process_packet(struct psmouse *psmouse) | 157 | static 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 | ||
| 259 | static 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 | |||
| 278 | static 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 | |||
| 358 | static 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 | |||
| 205 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | 387 | static 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 |
