diff options
-rw-r--r-- | drivers/input/mouse/synaptics.c | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 9567a708aa64..e78cc5578527 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -658,6 +658,18 @@ static void synaptics_parse_agm(const unsigned char buf[], | |||
658 | priv->agm_pending = true; | 658 | priv->agm_pending = true; |
659 | } | 659 | } |
660 | 660 | ||
661 | static void synaptics_parse_ext_buttons(const unsigned char buf[], | ||
662 | struct synaptics_data *priv, | ||
663 | struct synaptics_hw_state *hw) | ||
664 | { | ||
665 | unsigned int ext_bits = | ||
666 | (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; | ||
667 | unsigned int ext_mask = GENMASK(ext_bits - 1, 0); | ||
668 | |||
669 | hw->ext_buttons = buf[4] & ext_mask; | ||
670 | hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits; | ||
671 | } | ||
672 | |||
661 | static bool is_forcepad; | 673 | static bool is_forcepad; |
662 | 674 | ||
663 | static int synaptics_parse_hw_state(const unsigned char buf[], | 675 | static int synaptics_parse_hw_state(const unsigned char buf[], |
@@ -744,28 +756,9 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
744 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; | 756 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; |
745 | } | 757 | } |
746 | 758 | ||
747 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && | 759 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 0 && |
748 | ((buf[0] ^ buf[3]) & 0x02)) { | 760 | ((buf[0] ^ buf[3]) & 0x02)) { |
749 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { | 761 | synaptics_parse_ext_buttons(buf, priv, hw); |
750 | default: | ||
751 | /* | ||
752 | * if nExtBtn is greater than 8 it should be | ||
753 | * considered invalid and treated as 0 | ||
754 | */ | ||
755 | break; | ||
756 | case 8: | ||
757 | hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0; | ||
758 | hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0; | ||
759 | case 6: | ||
760 | hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0; | ||
761 | hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0; | ||
762 | case 4: | ||
763 | hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0; | ||
764 | hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0; | ||
765 | case 2: | ||
766 | hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0; | ||
767 | hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0; | ||
768 | } | ||
769 | } | 762 | } |
770 | } else { | 763 | } else { |
771 | hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); | 764 | hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); |
@@ -832,6 +825,7 @@ static void synaptics_report_buttons(struct psmouse *psmouse, | |||
832 | { | 825 | { |
833 | struct input_dev *dev = psmouse->dev; | 826 | struct input_dev *dev = psmouse->dev; |
834 | 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; | ||
835 | int i; | 829 | int i; |
836 | 830 | ||
837 | input_report_key(dev, BTN_LEFT, hw->left); | 831 | input_report_key(dev, BTN_LEFT, hw->left); |
@@ -845,8 +839,12 @@ static void synaptics_report_buttons(struct psmouse *psmouse, | |||
845 | input_report_key(dev, BTN_BACK, hw->down); | 839 | input_report_key(dev, BTN_BACK, hw->down); |
846 | } | 840 | } |
847 | 841 | ||
848 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 842 | for (i = 0; i < ext_bits; i++) { |
849 | input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); | 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 | } | ||
850 | } | 848 | } |
851 | 849 | ||
852 | static void synaptics_report_slot(struct input_dev *dev, int slot, | 850 | static void synaptics_report_slot(struct input_dev *dev, int slot, |