diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/mouse/synaptics.c | 68 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 11 |
2 files changed, 63 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) { |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index e594af0b264b..fb2e076738ae 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -78,6 +78,11 @@ | |||
78 | * 2 0x08 image sensor image sensor tracks 5 fingers, but only | 78 | * 2 0x08 image sensor image sensor tracks 5 fingers, but only |
79 | * reports 2. | 79 | * reports 2. |
80 | * 2 0x20 report min query 0x0f gives min coord reported | 80 | * 2 0x20 report min query 0x0f gives min coord reported |
81 | * 2 0x80 forcepad forcepad is a variant of clickpad that | ||
82 | * does not have physical buttons but rather | ||
83 | * uses pressure above certain threshold to | ||
84 | * report primary clicks. Forcepads also have | ||
85 | * clickpad bit set. | ||
81 | */ | 86 | */ |
82 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ | 87 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ |
83 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ | 88 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ |
@@ -86,6 +91,7 @@ | |||
86 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) | 91 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) |
87 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) | 92 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) |
88 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) | 93 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) |
94 | #define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000) | ||
89 | 95 | ||
90 | /* synaptics modes query bits */ | 96 | /* synaptics modes query bits */ |
91 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 97 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
@@ -177,6 +183,11 @@ struct synaptics_data { | |||
177 | */ | 183 | */ |
178 | struct synaptics_hw_state agm; | 184 | struct synaptics_hw_state agm; |
179 | bool agm_pending; /* new AGM packet received */ | 185 | bool agm_pending; /* new AGM packet received */ |
186 | |||
187 | /* ForcePad handling */ | ||
188 | unsigned long press_start; | ||
189 | bool press; | ||
190 | bool report_press; | ||
180 | }; | 191 | }; |
181 | 192 | ||
182 | void synaptics_module_init(void); | 193 | void synaptics_module_init(void); |