aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2013-02-14 01:26:11 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-02-14 12:18:25 -0500
commitf85e5001cce0298a44e35e2f8acbf9abeadb6c03 (patch)
tree0dc2551cc497f6049e4e397e35fb1d6778c7d721
parent7a9f73e75cd0dcd320166aa340141893bd1848d1 (diff)
Input: ALPS - make the V3 packet field decoder "pluggable"
A number of different ALPS touchpad protocols can reuse alps_process_touchpad_packet_v3() with small tweaks to the bitfield decoding. Create a new priv->decode_fields() callback that handles the per-model differences. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> Tested-by: Dave Turvene <dturvene@dahetral.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/mouse/alps.c101
-rw-r--r--drivers/input/mouse/alps.h38
2 files changed, 95 insertions, 44 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 2cd8be774f91..270b7deefe5b 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -447,17 +447,49 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
447 return; 447 return;
448} 448}
449 449
450static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
451{
452 f->left = !!(p[3] & 0x01);
453 f->right = !!(p[3] & 0x02);
454 f->middle = !!(p[3] & 0x04);
455
456 f->ts_left = !!(p[3] & 0x10);
457 f->ts_right = !!(p[3] & 0x20);
458 f->ts_middle = !!(p[3] & 0x40);
459}
460
461static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p)
462{
463 f->first_mp = !!(p[4] & 0x40);
464 f->is_mp = !!(p[0] & 0x40);
465
466 f->fingers = (p[5] & 0x3) + 1;
467 f->x_map = ((p[4] & 0x7e) << 8) |
468 ((p[1] & 0x7f) << 2) |
469 ((p[0] & 0x30) >> 4);
470 f->y_map = ((p[3] & 0x70) << 4) |
471 ((p[2] & 0x7f) << 1) |
472 (p[4] & 0x01);
473
474 f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
475 ((p[0] & 0x30) >> 4);
476 f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
477 f->z = p[5] & 0x7f;
478
479 alps_decode_buttons_v3(f, p);
480}
481
450static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) 482static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
451{ 483{
452 struct alps_data *priv = psmouse->private; 484 struct alps_data *priv = psmouse->private;
453 unsigned char *packet = psmouse->packet; 485 unsigned char *packet = psmouse->packet;
454 struct input_dev *dev = psmouse->dev; 486 struct input_dev *dev = psmouse->dev;
455 struct input_dev *dev2 = priv->dev2; 487 struct input_dev *dev2 = priv->dev2;
456 int x, y, z;
457 int left, right, middle;
458 int x1 = 0, y1 = 0, x2 = 0, y2 = 0; 488 int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
459 int fingers = 0, bmap_fingers; 489 int fingers = 0, bmap_fingers;
460 unsigned int x_bitmap, y_bitmap; 490 struct alps_fields f;
491
492 priv->decode_fields(&f, packet);
461 493
462 /* 494 /*
463 * There's no single feature of touchpad position and bitmap packets 495 * There's no single feature of touchpad position and bitmap packets
@@ -472,17 +504,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
472 * packet. Check for this, and when it happens process the 504 * packet. Check for this, and when it happens process the
473 * position packet as usual. 505 * position packet as usual.
474 */ 506 */
475 if (packet[0] & 0x40) { 507 if (f.is_mp) {
476 fingers = (packet[5] & 0x3) + 1; 508 fingers = f.fingers;
477 x_bitmap = ((packet[4] & 0x7e) << 8) |
478 ((packet[1] & 0x7f) << 2) |
479 ((packet[0] & 0x30) >> 4);
480 y_bitmap = ((packet[3] & 0x70) << 4) |
481 ((packet[2] & 0x7f) << 1) |
482 (packet[4] & 0x01);
483
484 bmap_fingers = alps_process_bitmap(priv, 509 bmap_fingers = alps_process_bitmap(priv,
485 x_bitmap, y_bitmap, 510 f.x_map, f.y_map,
486 &x1, &y1, &x2, &y2); 511 &x1, &y1, &x2, &y2);
487 512
488 /* 513 /*
@@ -493,7 +518,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
493 fingers = bmap_fingers; 518 fingers = bmap_fingers;
494 519
495 /* Now process position packet */ 520 /* Now process position packet */
496 packet = priv->multi_data; 521 priv->decode_fields(&f, priv->multi_data);
497 } else { 522 } else {
498 priv->multi_packet = 0; 523 priv->multi_packet = 0;
499 } 524 }
@@ -507,10 +532,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
507 * out misidentified bitmap packets, we reject anything with this 532 * out misidentified bitmap packets, we reject anything with this
508 * bit set. 533 * bit set.
509 */ 534 */
510 if (packet[0] & 0x40) 535 if (f.is_mp)
511 return; 536 return;
512 537
513 if (!priv->multi_packet && (packet[4] & 0x40)) { 538 if (!priv->multi_packet && f.first_mp) {
514 priv->multi_packet = 1; 539 priv->multi_packet = 1;
515 memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); 540 memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
516 return; 541 return;
@@ -518,22 +543,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
518 543
519 priv->multi_packet = 0; 544 priv->multi_packet = 0;
520 545
521 left = packet[3] & 0x01;
522 right = packet[3] & 0x02;
523 middle = packet[3] & 0x04;
524
525 x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) |
526 ((packet[0] & 0x30) >> 4);
527 y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f);
528 z = packet[5] & 0x7f;
529
530 /* 546 /*
531 * Sometimes the hardware sends a single packet with z = 0 547 * Sometimes the hardware sends a single packet with z = 0
532 * in the middle of a stream. Real releases generate packets 548 * in the middle of a stream. Real releases generate packets
533 * with x, y, and z all zero, so these seem to be flukes. 549 * with x, y, and z all zero, so these seem to be flukes.
534 * Ignore them. 550 * Ignore them.
535 */ 551 */
536 if (x && y && !z) 552 if (f.x && f.y && !f.z)
537 return; 553 return;
538 554
539 /* 555 /*
@@ -541,12 +557,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
541 * to rely on ST data. 557 * to rely on ST data.
542 */ 558 */
543 if (!fingers) { 559 if (!fingers) {
544 x1 = x; 560 x1 = f.x;
545 y1 = y; 561 y1 = f.y;
546 fingers = z > 0 ? 1 : 0; 562 fingers = f.z > 0 ? 1 : 0;
547 } 563 }
548 564
549 if (z >= 64) 565 if (f.z >= 64)
550 input_report_key(dev, BTN_TOUCH, 1); 566 input_report_key(dev, BTN_TOUCH, 1);
551 else 567 else
552 input_report_key(dev, BTN_TOUCH, 0); 568 input_report_key(dev, BTN_TOUCH, 0);
@@ -555,26 +571,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
555 571
556 input_mt_report_finger_count(dev, fingers); 572 input_mt_report_finger_count(dev, fingers);
557 573
558 input_report_key(dev, BTN_LEFT, left); 574 input_report_key(dev, BTN_LEFT, f.left);
559 input_report_key(dev, BTN_RIGHT, right); 575 input_report_key(dev, BTN_RIGHT, f.right);
560 input_report_key(dev, BTN_MIDDLE, middle); 576 input_report_key(dev, BTN_MIDDLE, f.middle);
561 577
562 if (z > 0) { 578 if (f.z > 0) {
563 input_report_abs(dev, ABS_X, x); 579 input_report_abs(dev, ABS_X, f.x);
564 input_report_abs(dev, ABS_Y, y); 580 input_report_abs(dev, ABS_Y, f.y);
565 } 581 }
566 input_report_abs(dev, ABS_PRESSURE, z); 582 input_report_abs(dev, ABS_PRESSURE, f.z);
567 583
568 input_sync(dev); 584 input_sync(dev);
569 585
570 if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { 586 if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
571 left = packet[3] & 0x10; 587 input_report_key(dev2, BTN_LEFT, f.ts_left);
572 right = packet[3] & 0x20; 588 input_report_key(dev2, BTN_RIGHT, f.ts_right);
573 middle = packet[3] & 0x40; 589 input_report_key(dev2, BTN_MIDDLE, f.ts_middle);
574
575 input_report_key(dev2, BTN_LEFT, left);
576 input_report_key(dev2, BTN_RIGHT, right);
577 input_report_key(dev2, BTN_MIDDLE, middle);
578 input_sync(dev2); 590 input_sync(dev2);
579 } 591 }
580} 592}
@@ -1428,6 +1440,7 @@ static void alps_set_defaults(struct alps_data *priv)
1428 priv->hw_init = alps_hw_init_v3; 1440 priv->hw_init = alps_hw_init_v3;
1429 priv->process_packet = alps_process_packet_v3; 1441 priv->process_packet = alps_process_packet_v3;
1430 priv->set_abs_params = alps_set_abs_params_mt; 1442 priv->set_abs_params = alps_set_abs_params_mt;
1443 priv->decode_fields = alps_decode_pinnacle;
1431 priv->nibble_commands = alps_v3_nibble_commands; 1444 priv->nibble_commands = alps_v3_nibble_commands;
1432 priv->addr_command = PSMOUSE_CMD_RESET_WRAP; 1445 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
1433 break; 1446 break;
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 5e638be33dc9..970480551b6e 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -60,6 +60,42 @@ struct alps_nibble_commands {
60}; 60};
61 61
62/** 62/**
63 * struct alps_fields - decoded version of the report packet
64 * @x_map: Bitmap of active X positions for MT.
65 * @y_map: Bitmap of active Y positions for MT.
66 * @fingers: Number of fingers for MT.
67 * @x: X position for ST.
68 * @y: Y position for ST.
69 * @z: Z position for ST.
70 * @first_mp: Packet is the first of a multi-packet report.
71 * @is_mp: Packet is part of a multi-packet report.
72 * @left: Left touchpad button is active.
73 * @right: Right touchpad button is active.
74 * @middle: Middle touchpad button is active.
75 * @ts_left: Left trackstick button is active.
76 * @ts_right: Right trackstick button is active.
77 * @ts_middle: Middle trackstick button is active.
78 */
79struct alps_fields {
80 unsigned int x_map;
81 unsigned int y_map;
82 unsigned int fingers;
83 unsigned int x;
84 unsigned int y;
85 unsigned int z;
86 unsigned int first_mp:1;
87 unsigned int is_mp:1;
88
89 unsigned int left:1;
90 unsigned int right:1;
91 unsigned int middle:1;
92
93 unsigned int ts_left:1;
94 unsigned int ts_right:1;
95 unsigned int ts_middle:1;
96};
97
98/**
63 * struct alps_data - private data structure for the ALPS driver 99 * struct alps_data - private data structure for the ALPS driver
64 * @dev2: "Relative" device used to report trackstick or mouse activity. 100 * @dev2: "Relative" device used to report trackstick or mouse activity.
65 * @phys: Physical path for the relative device. 101 * @phys: Physical path for the relative device.
@@ -78,6 +114,7 @@ struct alps_nibble_commands {
78 * @y_bits: Number of Y bits in the MT bitmap. 114 * @y_bits: Number of Y bits in the MT bitmap.
79 * @hw_init: Protocol-specific hardware init function. 115 * @hw_init: Protocol-specific hardware init function.
80 * @process_packet: Protocol-specific function to process a report packet. 116 * @process_packet: Protocol-specific function to process a report packet.
117 * @decode_fields: Protocol-specific function to read packet bitfields.
81 * @set_abs_params: Protocol-specific function to configure the input_dev. 118 * @set_abs_params: Protocol-specific function to configure the input_dev.
82 * @prev_fin: Finger bit from previous packet. 119 * @prev_fin: Finger bit from previous packet.
83 * @multi_packet: Multi-packet data in progress. 120 * @multi_packet: Multi-packet data in progress.
@@ -107,6 +144,7 @@ struct alps_data {
107 144
108 int (*hw_init)(struct psmouse *psmouse); 145 int (*hw_init)(struct psmouse *psmouse);
109 void (*process_packet)(struct psmouse *psmouse); 146 void (*process_packet)(struct psmouse *psmouse);
147 void (*decode_fields)(struct alps_fields *f, unsigned char *p);
110 void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); 148 void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1);
111 149
112 int prev_fin; 150 int prev_fin;