diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2015-03-09 01:32:43 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-03-09 02:34:48 -0400 |
commit | ebc80840b850db72f7ae84fbcf77630ae5409629 (patch) | |
tree | 3d0f86bc4e2bb699bc194b49bef18a42005837b1 | |
parent | dc5465dc8a6d5cae8a0e1d8826bdcb2e4cb261ab (diff) |
Input: synaptics - handle spurious release of trackstick buttons
The Fimware 8.1 has a bug in which the extra buttons are only sent when the
ExtBit is 1. This should be fixed in a future FW update which should have
a bump of the minor version.
Cc: stable@vger.kernel.org
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r-- | drivers/input/mouse/synaptics.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index e78cc5578527..2f42a712f3e0 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -820,14 +820,36 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev, | |||
820 | } | 820 | } |
821 | } | 821 | } |
822 | 822 | ||
823 | static void synaptics_report_buttons(struct psmouse *psmouse, | 823 | static void synaptics_report_ext_buttons(struct psmouse *psmouse, |
824 | const struct synaptics_hw_state *hw) | 824 | const struct synaptics_hw_state *hw) |
825 | { | 825 | { |
826 | struct input_dev *dev = psmouse->dev; | 826 | struct input_dev *dev = psmouse->dev; |
827 | struct synaptics_data *priv = psmouse->private; | 827 | struct synaptics_data *priv = psmouse->private; |
828 | int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; | 828 | int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; |
829 | int i; | 829 | int i; |
830 | 830 | ||
831 | if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) | ||
832 | return; | ||
833 | |||
834 | /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */ | ||
835 | if (SYN_ID_FULL(priv->identity) == 0x801 && | ||
836 | !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02)) | ||
837 | return; | ||
838 | |||
839 | for (i = 0; i < ext_bits; i++) { | ||
840 | input_report_key(dev, BTN_0 + 2 * i, | ||
841 | hw->ext_buttons & (1 << i)); | ||
842 | input_report_key(dev, BTN_1 + 2 * i, | ||
843 | hw->ext_buttons & (1 << (i + ext_bits))); | ||
844 | } | ||
845 | } | ||
846 | |||
847 | static void synaptics_report_buttons(struct psmouse *psmouse, | ||
848 | const struct synaptics_hw_state *hw) | ||
849 | { | ||
850 | struct input_dev *dev = psmouse->dev; | ||
851 | struct synaptics_data *priv = psmouse->private; | ||
852 | |||
831 | input_report_key(dev, BTN_LEFT, hw->left); | 853 | input_report_key(dev, BTN_LEFT, hw->left); |
832 | input_report_key(dev, BTN_RIGHT, hw->right); | 854 | input_report_key(dev, BTN_RIGHT, hw->right); |
833 | 855 | ||
@@ -839,12 +861,7 @@ static void synaptics_report_buttons(struct psmouse *psmouse, | |||
839 | input_report_key(dev, BTN_BACK, hw->down); | 861 | input_report_key(dev, BTN_BACK, hw->down); |
840 | } | 862 | } |
841 | 863 | ||
842 | for (i = 0; i < ext_bits; i++) { | 864 | synaptics_report_ext_buttons(psmouse, hw); |
843 | input_report_key(dev, BTN_0 + 2 * i, | ||
844 | hw->ext_buttons & (1 << i)); | ||
845 | input_report_key(dev, BTN_1 + 2 * i, | ||
846 | hw->ext_buttons & (1 << (i + ext_bits))); | ||
847 | } | ||
848 | } | 865 | } |
849 | 866 | ||
850 | static void synaptics_report_slot(struct input_dev *dev, int slot, | 867 | static void synaptics_report_slot(struct input_dev *dev, int slot, |