aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/alps.c
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2009-11-17 01:12:22 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-11-20 03:52:13 -0500
commit71bb21b677e89a2b438b804231f92b779beda5d7 (patch)
tree4bd0e84c5bd2010907022ec11eb3995bfbef57fe /drivers/input/mouse/alps.c
parent315eb996d5505112b22452ccbc7e01fb02eaae81 (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.c100
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
39static const struct alps_model_info alps_model_data[] = { 42static 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[] = {
83static void alps_process_packet(struct psmouse *psmouse) 86static 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
396static int alps_hw_init(struct psmouse *psmouse, int *version) 410static 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
433static int alps_reconnect(struct psmouse *psmouse) 444static 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
443static void alps_disconnect(struct psmouse *psmouse) 457static void alps_disconnect(struct psmouse *psmouse)
@@ -452,6 +466,7 @@ static void alps_disconnect(struct psmouse *psmouse)
452int alps_init(struct psmouse *psmouse) 466int 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;