aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/alps.c79
-rw-r--r--drivers/input/mouse/alps.h2
2 files changed, 75 insertions, 6 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4c6a72d3d48..ecd93894c80 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -604,10 +604,54 @@ static void alps_process_packet_v3(struct psmouse *psmouse)
604 604
605static void alps_process_packet_v4(struct psmouse *psmouse) 605static void alps_process_packet_v4(struct psmouse *psmouse)
606{ 606{
607 struct alps_data *priv = psmouse->private;
607 unsigned char *packet = psmouse->packet; 608 unsigned char *packet = psmouse->packet;
608 struct input_dev *dev = psmouse->dev; 609 struct input_dev *dev = psmouse->dev;
610 int offset;
609 int x, y, z; 611 int x, y, z;
610 int left, right; 612 int left, right;
613 int x1, y1, x2, y2;
614 int fingers = 0;
615 unsigned int x_bitmap, y_bitmap;
616
617 /*
618 * v4 has a 6-byte encoding for bitmap data, but this data is
619 * broken up between 3 normal packets. Use priv->multi_packet to
620 * track our position in the bitmap packet.
621 */
622 if (packet[6] & 0x40) {
623 /* sync, reset position */
624 priv->multi_packet = 0;
625 }
626
627 if (WARN_ON_ONCE(priv->multi_packet > 2))
628 return;
629
630 offset = 2 * priv->multi_packet;
631 priv->multi_data[offset] = packet[6];
632 priv->multi_data[offset + 1] = packet[7];
633
634 if (++priv->multi_packet > 2) {
635 priv->multi_packet = 0;
636
637 x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) |
638 ((priv->multi_data[3] & 0x60) << 3) |
639 ((priv->multi_data[0] & 0x3f) << 2) |
640 ((priv->multi_data[1] & 0x60) >> 5);
641 y_bitmap = ((priv->multi_data[5] & 0x01) << 10) |
642 ((priv->multi_data[3] & 0x1f) << 5) |
643 (priv->multi_data[1] & 0x1f);
644
645 fingers = alps_process_bitmap(x_bitmap, y_bitmap,
646 &x1, &y1, &x2, &y2);
647
648 /* Store MT data.*/
649 priv->fingers = fingers;
650 priv->x1 = x1;
651 priv->x2 = x2;
652 priv->y1 = y1;
653 priv->y2 = y2;
654 }
611 655
612 left = packet[4] & 0x01; 656 left = packet[4] & 0x01;
613 right = packet[4] & 0x02; 657 right = packet[4] & 0x02;
@@ -617,21 +661,44 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
617 y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); 661 y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
618 z = packet[5] & 0x7f; 662 z = packet[5] & 0x7f;
619 663
664 /*
665 * If there were no contacts in the bitmap, use ST
666 * points in MT reports.
667 * If there were two contacts or more, report MT data.
668 */
669 if (priv->fingers < 2) {
670 x1 = x;
671 y1 = y;
672 fingers = z > 0 ? 1 : 0;
673 } else {
674 fingers = priv->fingers;
675 x1 = priv->x1;
676 x2 = priv->x2;
677 y1 = priv->y1;
678 y2 = priv->y2;
679 }
680
620 if (z >= 64) 681 if (z >= 64)
621 input_report_key(dev, BTN_TOUCH, 1); 682 input_report_key(dev, BTN_TOUCH, 1);
622 else 683 else
623 input_report_key(dev, BTN_TOUCH, 0); 684 input_report_key(dev, BTN_TOUCH, 0);
624 685
686 alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
687
688 input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
689 input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
690 input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
691 input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
692
693 input_report_key(dev, BTN_LEFT, left);
694 input_report_key(dev, BTN_RIGHT, right);
695
625 if (z > 0) { 696 if (z > 0) {
626 input_report_abs(dev, ABS_X, x); 697 input_report_abs(dev, ABS_X, x);
627 input_report_abs(dev, ABS_Y, y); 698 input_report_abs(dev, ABS_Y, y);
628 } 699 }
629 input_report_abs(dev, ABS_PRESSURE, z); 700 input_report_abs(dev, ABS_PRESSURE, z);
630 701
631 input_report_key(dev, BTN_TOOL_FINGER, z > 0);
632 input_report_key(dev, BTN_LEFT, left);
633 input_report_key(dev, BTN_RIGHT, right);
634
635 input_sync(dev); 702 input_sync(dev);
636} 703}
637 704
@@ -1557,6 +1624,7 @@ int alps_init(struct psmouse *psmouse)
1557 input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); 1624 input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
1558 break; 1625 break;
1559 case ALPS_PROTO_V3: 1626 case ALPS_PROTO_V3:
1627 case ALPS_PROTO_V4:
1560 set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); 1628 set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
1561 input_mt_init_slots(dev1, 2); 1629 input_mt_init_slots(dev1, 2);
1562 input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); 1630 input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0);
@@ -1565,8 +1633,7 @@ int alps_init(struct psmouse *psmouse)
1565 set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); 1633 set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
1566 set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); 1634 set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
1567 set_bit(BTN_TOOL_QUADTAP, dev1->keybit); 1635 set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
1568 /* fall through */ 1636
1569 case ALPS_PROTO_V4:
1570 input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); 1637 input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0);
1571 input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); 1638 input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0);
1572 break; 1639 break;
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index a00a4ab92a0..ae1ac354c77 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -39,6 +39,8 @@ struct alps_data {
39 int prev_fin; /* Finger bit from previous packet */ 39 int prev_fin; /* Finger bit from previous packet */
40 int multi_packet; /* Multi-packet data in progress */ 40 int multi_packet; /* Multi-packet data in progress */
41 unsigned char multi_data[6]; /* Saved multi-packet data */ 41 unsigned char multi_data[6]; /* Saved multi-packet data */
42 int x1, x2, y1, y2; /* Coordinates from last MT report */
43 int fingers; /* Number of fingers from MT report */
42 u8 quirks; 44 u8 quirks;
43 struct timer_list timer; 45 struct timer_list timer;
44}; 46};