diff options
author | Kevin Cernekee <cernekee@gmail.com> | 2013-02-14 01:26:11 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-02-14 12:18:25 -0500 |
commit | f85e5001cce0298a44e35e2f8acbf9abeadb6c03 (patch) | |
tree | 0dc2551cc497f6049e4e397e35fb1d6778c7d721 | |
parent | 7a9f73e75cd0dcd320166aa340141893bd1848d1 (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.c | 101 | ||||
-rw-r--r-- | drivers/input/mouse/alps.h | 38 |
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 | ||
450 | static 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 | |||
461 | static 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 | |||
450 | static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) | 482 | static 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 | */ | ||
79 | struct 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; |