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 /drivers/input | |
| 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>
Diffstat (limited to 'drivers/input')
| -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; | ||
