diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2009-11-17 01:12:22 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-11-20 03:52:13 -0500 |
commit | 71bb21b677e89a2b438b804231f92b779beda5d7 (patch) | |
tree | 4bd0e84c5bd2010907022ec11eb3995bfbef57fe /drivers/input/mouse/alps.c | |
parent | 315eb996d5505112b22452ccbc7e01fb02eaae81 (diff) |
Input: ALPS - add support for touchpads with 4-directional button
The touchpad on Acer Aspire 5720, 5520 and some other Aspire models
(signature 0x73, 0x02, 0x50) has a button that can be rocked in 4
different directions. Make the driver to generate BTN_0..BTN_3 events
in response. The Synaptics driver by default maps BTN_0 and BTN_1 to
up and down, so there should be no visible changes with the old setup
that generated BTN_FORWARD and BTN_BACK (also mapped to up and down).
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/mouse/alps.c')
-rw-r--r-- | drivers/input/mouse/alps.c | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f36110689aae..a3f492a50850 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -28,13 +28,16 @@ | |||
28 | #define dbg(format, arg...) do {} while (0) | 28 | #define dbg(format, arg...) do {} while (0) |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define ALPS_DUALPOINT 0x01 | 31 | |
32 | #define ALPS_WHEEL 0x02 | 32 | #define ALPS_OLDPROTO 0x01 /* old style input */ |
33 | #define ALPS_FW_BK_1 0x04 | 33 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ |
34 | #define ALPS_4BTN 0x08 | 34 | #define ALPS_PASS 0x04 /* device has a pass-through port */ |
35 | #define ALPS_OLDPROTO 0x10 | 35 | |
36 | #define ALPS_PASS 0x20 | 36 | #define ALPS_WHEEL 0x08 /* hardware wheel present */ |
37 | #define ALPS_FW_BK_2 0x40 | 37 | #define ALPS_FW_BK_1 0x10 /* 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 */ | ||
40 | |||
38 | 41 | ||
39 | static const struct alps_model_info alps_model_data[] = { | 42 | static const struct alps_model_info alps_model_data[] = { |
40 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | 43 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ |
@@ -56,7 +59,7 @@ static const struct alps_model_info alps_model_data[] = { | |||
56 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 59 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
57 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 60 | { { 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 */ | 61 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ |
59 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */ | 62 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ |
60 | }; | 63 | }; |
61 | 64 | ||
62 | /* | 65 | /* |
@@ -83,6 +86,7 @@ static const struct alps_model_info alps_model_data[] = { | |||
83 | static void alps_process_packet(struct psmouse *psmouse) | 86 | static void alps_process_packet(struct psmouse *psmouse) |
84 | { | 87 | { |
85 | struct alps_data *priv = psmouse->private; | 88 | struct alps_data *priv = psmouse->private; |
89 | const struct alps_model_info *model = priv->i; | ||
86 | unsigned char *packet = psmouse->packet; | 90 | unsigned char *packet = psmouse->packet; |
87 | struct input_dev *dev = psmouse->dev; | 91 | struct input_dev *dev = psmouse->dev; |
88 | struct input_dev *dev2 = priv->dev2; | 92 | struct input_dev *dev2 = priv->dev2; |
@@ -101,7 +105,7 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
101 | return; | 105 | return; |
102 | } | 106 | } |
103 | 107 | ||
104 | if (priv->i->flags & ALPS_OLDPROTO) { | 108 | if (model->flags & ALPS_OLDPROTO) { |
105 | left = packet[2] & 0x10; | 109 | left = packet[2] & 0x10; |
106 | right = packet[2] & 0x08; | 110 | right = packet[2] & 0x08; |
107 | middle = 0; | 111 | middle = 0; |
@@ -117,12 +121,12 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
117 | z = packet[5]; | 121 | z = packet[5]; |
118 | } | 122 | } |
119 | 123 | ||
120 | if (priv->i->flags & ALPS_FW_BK_1) { | 124 | if (model->flags & ALPS_FW_BK_1) { |
121 | back = packet[0] & 0x10; | 125 | back = packet[0] & 0x10; |
122 | forward = packet[2] & 4; | 126 | forward = packet[2] & 4; |
123 | } | 127 | } |
124 | 128 | ||
125 | if (priv->i->flags & ALPS_FW_BK_2) { | 129 | if (model->flags & ALPS_FW_BK_2) { |
126 | back = packet[3] & 4; | 130 | back = packet[3] & 4; |
127 | forward = packet[2] & 4; | 131 | forward = packet[2] & 4; |
128 | if ((middle = forward && back)) | 132 | if ((middle = forward && back)) |
@@ -132,7 +136,7 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
132 | ges = packet[2] & 1; | 136 | ges = packet[2] & 1; |
133 | fin = packet[2] & 2; | 137 | fin = packet[2] & 2; |
134 | 138 | ||
135 | if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) { | 139 | if ((model->flags & ALPS_DUALPOINT) && z == 127) { |
136 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); | 140 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); |
137 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); | 141 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); |
138 | 142 | ||
@@ -150,7 +154,8 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
150 | input_report_key(dev, BTN_MIDDLE, middle); | 154 | input_report_key(dev, BTN_MIDDLE, middle); |
151 | 155 | ||
152 | /* Convert hardware tap to a reasonable Z value */ | 156 | /* Convert hardware tap to a reasonable Z value */ |
153 | if (ges && !fin) z = 40; | 157 | if (ges && !fin) |
158 | z = 40; | ||
154 | 159 | ||
155 | /* | 160 | /* |
156 | * A "tap and drag" operation is reported by the hardware as a transition | 161 | * A "tap and drag" operation is reported by the hardware as a transition |
@@ -166,8 +171,10 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
166 | } | 171 | } |
167 | priv->prev_fin = fin; | 172 | priv->prev_fin = fin; |
168 | 173 | ||
169 | if (z > 30) input_report_key(dev, BTN_TOUCH, 1); | 174 | if (z > 30) |
170 | if (z < 25) input_report_key(dev, BTN_TOUCH, 0); | 175 | input_report_key(dev, BTN_TOUCH, 1); |
176 | if (z < 25) | ||
177 | input_report_key(dev, BTN_TOUCH, 0); | ||
171 | 178 | ||
172 | if (z > 0) { | 179 | if (z > 0) { |
173 | input_report_abs(dev, ABS_X, x); | 180 | input_report_abs(dev, ABS_X, x); |
@@ -177,14 +184,21 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
177 | input_report_abs(dev, ABS_PRESSURE, z); | 184 | input_report_abs(dev, ABS_PRESSURE, z); |
178 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 185 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
179 | 186 | ||
180 | if (priv->i->flags & ALPS_WHEEL) | 187 | if (model->flags & ALPS_WHEEL) |
181 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); | 188 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); |
182 | 189 | ||
183 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 190 | if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
184 | input_report_key(dev, BTN_FORWARD, forward); | 191 | input_report_key(dev, BTN_FORWARD, forward); |
185 | input_report_key(dev, BTN_BACK, back); | 192 | input_report_key(dev, BTN_BACK, back); |
186 | } | 193 | } |
187 | 194 | ||
195 | if (model->flags & ALPS_FOUR_BUTTONS) { | ||
196 | input_report_key(dev, BTN_0, packet[2] & 4); | ||
197 | input_report_key(dev, BTN_1, packet[0] & 0x10); | ||
198 | input_report_key(dev, BTN_2, packet[3] & 4); | ||
199 | input_report_key(dev, BTN_3, packet[0] & 0x20); | ||
200 | } | ||
201 | |||
188 | input_sync(dev); | 202 | input_sync(dev); |
189 | } | 203 | } |
190 | 204 | ||
@@ -393,15 +407,12 @@ static int alps_poll(struct psmouse *psmouse) | |||
393 | return 0; | 407 | return 0; |
394 | } | 408 | } |
395 | 409 | ||
396 | static int alps_hw_init(struct psmouse *psmouse, int *version) | 410 | static int alps_hw_init(struct psmouse *psmouse) |
397 | { | 411 | { |
398 | struct alps_data *priv = psmouse->private; | 412 | struct alps_data *priv = psmouse->private; |
413 | const struct alps_model_info *model = priv->i; | ||
399 | 414 | ||
400 | priv->i = alps_get_model(psmouse, version); | 415 | 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)) { | 416 | alps_passthrough_mode(psmouse, true)) { |
406 | return -1; | 417 | return -1; |
407 | } | 418 | } |
@@ -416,7 +427,7 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
416 | return -1; | 427 | return -1; |
417 | } | 428 | } |
418 | 429 | ||
419 | if ((priv->i->flags & ALPS_PASS) && | 430 | if ((model->flags & ALPS_PASS) && |
420 | alps_passthrough_mode(psmouse, false)) { | 431 | alps_passthrough_mode(psmouse, false)) { |
421 | return -1; | 432 | return -1; |
422 | } | 433 | } |
@@ -432,12 +443,15 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
432 | 443 | ||
433 | static int alps_reconnect(struct psmouse *psmouse) | 444 | static int alps_reconnect(struct psmouse *psmouse) |
434 | { | 445 | { |
446 | const struct alps_model_info *model; | ||
447 | |||
435 | psmouse_reset(psmouse); | 448 | psmouse_reset(psmouse); |
436 | 449 | ||
437 | if (alps_hw_init(psmouse, NULL)) | 450 | model = alps_get_model(psmouse, NULL); |
451 | if (!model) | ||
438 | return -1; | 452 | return -1; |
439 | 453 | ||
440 | return 0; | 454 | return alps_hw_init(psmouse); |
441 | } | 455 | } |
442 | 456 | ||
443 | static void alps_disconnect(struct psmouse *psmouse) | 457 | static void alps_disconnect(struct psmouse *psmouse) |
@@ -452,6 +466,7 @@ static void alps_disconnect(struct psmouse *psmouse) | |||
452 | int alps_init(struct psmouse *psmouse) | 466 | int alps_init(struct psmouse *psmouse) |
453 | { | 467 | { |
454 | struct alps_data *priv; | 468 | struct alps_data *priv; |
469 | const struct alps_model_info *model; | ||
455 | struct input_dev *dev1 = psmouse->dev, *dev2; | 470 | struct input_dev *dev1 = psmouse->dev, *dev2; |
456 | int version; | 471 | int version; |
457 | 472 | ||
@@ -463,33 +478,48 @@ int alps_init(struct psmouse *psmouse) | |||
463 | priv->dev2 = dev2; | 478 | priv->dev2 = dev2; |
464 | psmouse->private = priv; | 479 | psmouse->private = priv; |
465 | 480 | ||
466 | if (alps_hw_init(psmouse, &version)) | 481 | model = alps_get_model(psmouse, &version); |
482 | if (!model) | ||
483 | goto init_fail; | ||
484 | |||
485 | priv->i = model; | ||
486 | |||
487 | if (alps_hw_init(psmouse)) | ||
467 | goto init_fail; | 488 | goto init_fail; |
468 | 489 | ||
469 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); | 490 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); |
470 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); | 491 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); |
471 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); | 492 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); |
472 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | | 493 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= |
473 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 494 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); |
474 | 495 | ||
475 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 496 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
476 | input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); | 497 | input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); |
477 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); | 498 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); |
478 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | 499 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); |
479 | 500 | ||
480 | if (priv->i->flags & ALPS_WHEEL) { | 501 | if (model->flags & ALPS_WHEEL) { |
481 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 502 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
482 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); | 503 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); |
483 | } | 504 | } |
484 | 505 | ||
485 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 506 | if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
486 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); | 507 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); |
487 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); | 508 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); |
488 | } | 509 | } |
489 | 510 | ||
511 | if (model->flags & ALPS_FOUR_BUTTONS) { | ||
512 | dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); | ||
513 | dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); | ||
514 | dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); | ||
515 | dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); | ||
516 | } else { | ||
517 | dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); | ||
518 | } | ||
519 | |||
490 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); | 520 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); |
491 | dev2->phys = priv->phys; | 521 | dev2->phys = priv->phys; |
492 | dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; | 522 | dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; |
493 | dev2->id.bustype = BUS_I8042; | 523 | dev2->id.bustype = BUS_I8042; |
494 | dev2->id.vendor = 0x0002; | 524 | dev2->id.vendor = 0x0002; |
495 | dev2->id.product = PSMOUSE_ALPS; | 525 | dev2->id.product = PSMOUSE_ALPS; |
@@ -497,9 +527,9 @@ int alps_init(struct psmouse *psmouse) | |||
497 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; | 527 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; |
498 | 528 | ||
499 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 529 | 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); | 530 | 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) | | 531 | dev2->keybit[BIT_WORD(BTN_LEFT)] = |
502 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 532 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
503 | 533 | ||
504 | if (input_register_device(priv->dev2)) | 534 | if (input_register_device(priv->dev2)) |
505 | goto init_fail; | 535 | goto init_fail; |