diff options
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
-rw-r--r-- | drivers/input/mouse/synaptics.c | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index e8573c68f77e..fd23181c1fb7 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -629,10 +629,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
629 | ((buf[0] & 0x04) >> 1) | | 629 | ((buf[0] & 0x04) >> 1) | |
630 | ((buf[3] & 0x04) >> 2)); | 630 | ((buf[3] & 0x04) >> 2)); |
631 | 631 | ||
632 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | ||
633 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && | ||
634 | hw->w == 2) { | ||
635 | synaptics_parse_agm(buf, priv, hw); | ||
636 | return 1; | ||
637 | } | ||
638 | |||
639 | hw->x = (((buf[3] & 0x10) << 8) | | ||
640 | ((buf[1] & 0x0f) << 8) | | ||
641 | buf[4]); | ||
642 | hw->y = (((buf[3] & 0x20) << 7) | | ||
643 | ((buf[1] & 0xf0) << 4) | | ||
644 | buf[5]); | ||
645 | hw->z = buf[2]; | ||
646 | |||
632 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 647 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
633 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 648 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
634 | 649 | ||
635 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 650 | if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) { |
651 | /* | ||
652 | * ForcePads, like Clickpads, use middle button | ||
653 | * bits to report primary button clicks. | ||
654 | * Unfortunately they report primary button not | ||
655 | * only when user presses on the pad above certain | ||
656 | * threshold, but also when there are more than one | ||
657 | * finger on the touchpad, which interferes with | ||
658 | * out multi-finger gestures. | ||
659 | */ | ||
660 | if (hw->z == 0) { | ||
661 | /* No contacts */ | ||
662 | priv->press = priv->report_press = false; | ||
663 | } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { | ||
664 | /* | ||
665 | * Single-finger touch with pressure above | ||
666 | * the threshold. If pressure stays long | ||
667 | * enough, we'll start reporting primary | ||
668 | * button. We rely on the device continuing | ||
669 | * sending data even if finger does not | ||
670 | * move. | ||
671 | */ | ||
672 | if (!priv->press) { | ||
673 | priv->press_start = jiffies; | ||
674 | priv->press = true; | ||
675 | } else if (time_after(jiffies, | ||
676 | priv->press_start + | ||
677 | msecs_to_jiffies(50))) { | ||
678 | priv->report_press = true; | ||
679 | } | ||
680 | } else { | ||
681 | priv->press = false; | ||
682 | } | ||
683 | |||
684 | hw->left = priv->report_press; | ||
685 | |||
686 | } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | ||
636 | /* | 687 | /* |
637 | * Clickpad's button is transmitted as middle button, | 688 | * Clickpad's button is transmitted as middle button, |
638 | * however, since it is primary button, we will report | 689 | * however, since it is primary button, we will report |
@@ -651,21 +702,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
651 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; | 702 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; |
652 | } | 703 | } |
653 | 704 | ||
654 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | ||
655 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && | ||
656 | hw->w == 2) { | ||
657 | synaptics_parse_agm(buf, priv, hw); | ||
658 | return 1; | ||
659 | } | ||
660 | |||
661 | hw->x = (((buf[3] & 0x10) << 8) | | ||
662 | ((buf[1] & 0x0f) << 8) | | ||
663 | buf[4]); | ||
664 | hw->y = (((buf[3] & 0x20) << 7) | | ||
665 | ((buf[1] & 0xf0) << 4) | | ||
666 | buf[5]); | ||
667 | hw->z = buf[2]; | ||
668 | |||
669 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && | 705 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && |
670 | ((buf[0] ^ buf[3]) & 0x02)) { | 706 | ((buf[0] ^ buf[3]) & 0x02)) { |
671 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { | 707 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { |