diff options
-rw-r--r-- | drivers/input/mouse/synaptics.c | 47 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 5 |
2 files changed, 41 insertions, 11 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 9d599eb79f17..ecc7811cbd46 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -579,18 +579,22 @@ static int synaptics_is_pt_packet(unsigned char *buf) | |||
579 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; | 579 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; |
580 | } | 580 | } |
581 | 581 | ||
582 | static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) | 582 | static void synaptics_pass_pt_packet(struct psmouse *psmouse, |
583 | struct serio *ptport, | ||
584 | unsigned char *packet) | ||
583 | { | 585 | { |
586 | struct synaptics_data *priv = psmouse->private; | ||
584 | struct psmouse *child = serio_get_drvdata(ptport); | 587 | struct psmouse *child = serio_get_drvdata(ptport); |
585 | 588 | ||
586 | if (child && child->state == PSMOUSE_ACTIVATED) { | 589 | if (child && child->state == PSMOUSE_ACTIVATED) { |
587 | serio_interrupt(ptport, packet[1], 0); | 590 | serio_interrupt(ptport, packet[1] | priv->pt_buttons, 0); |
588 | serio_interrupt(ptport, packet[4], 0); | 591 | serio_interrupt(ptport, packet[4], 0); |
589 | serio_interrupt(ptport, packet[5], 0); | 592 | serio_interrupt(ptport, packet[5], 0); |
590 | if (child->pktsize == 4) | 593 | if (child->pktsize == 4) |
591 | serio_interrupt(ptport, packet[2], 0); | 594 | serio_interrupt(ptport, packet[2], 0); |
592 | } else | 595 | } else { |
593 | serio_interrupt(ptport, packet[1], 0); | 596 | serio_interrupt(ptport, packet[1], 0); |
597 | } | ||
594 | } | 598 | } |
595 | 599 | ||
596 | static void synaptics_pt_activate(struct psmouse *psmouse) | 600 | static void synaptics_pt_activate(struct psmouse *psmouse) |
@@ -847,6 +851,7 @@ static void synaptics_report_ext_buttons(struct psmouse *psmouse, | |||
847 | struct input_dev *dev = psmouse->dev; | 851 | struct input_dev *dev = psmouse->dev; |
848 | struct synaptics_data *priv = psmouse->private; | 852 | struct synaptics_data *priv = psmouse->private; |
849 | int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; | 853 | int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; |
854 | char buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
850 | int i; | 855 | int i; |
851 | 856 | ||
852 | if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) | 857 | if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) |
@@ -857,12 +862,30 @@ static void synaptics_report_ext_buttons(struct psmouse *psmouse, | |||
857 | !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02)) | 862 | !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02)) |
858 | return; | 863 | return; |
859 | 864 | ||
860 | for (i = 0; i < ext_bits; i++) { | 865 | if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) { |
861 | input_report_key(dev, BTN_0 + 2 * i, | 866 | for (i = 0; i < ext_bits; i++) { |
862 | hw->ext_buttons & (1 << i)); | 867 | input_report_key(dev, BTN_0 + 2 * i, |
863 | input_report_key(dev, BTN_1 + 2 * i, | 868 | hw->ext_buttons & (1 << i)); |
864 | hw->ext_buttons & (1 << (i + ext_bits))); | 869 | input_report_key(dev, BTN_1 + 2 * i, |
870 | hw->ext_buttons & (1 << (i + ext_bits))); | ||
871 | } | ||
872 | return; | ||
865 | } | 873 | } |
874 | |||
875 | /* | ||
876 | * This generation of touchpads has the trackstick buttons | ||
877 | * physically wired to the touchpad. Re-route them through | ||
878 | * the pass-through interface. | ||
879 | */ | ||
880 | if (!priv->pt_port) | ||
881 | return; | ||
882 | |||
883 | /* The trackstick expects at most 3 buttons */ | ||
884 | priv->pt_buttons = SYN_CAP_EXT_BUTTON_STICK_L(hw->ext_buttons) | | ||
885 | SYN_CAP_EXT_BUTTON_STICK_R(hw->ext_buttons) << 1 | | ||
886 | SYN_CAP_EXT_BUTTON_STICK_M(hw->ext_buttons) << 2; | ||
887 | |||
888 | synaptics_pass_pt_packet(psmouse, priv->pt_port, buf); | ||
866 | } | 889 | } |
867 | 890 | ||
868 | static void synaptics_report_buttons(struct psmouse *psmouse, | 891 | static void synaptics_report_buttons(struct psmouse *psmouse, |
@@ -1459,7 +1482,8 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) | |||
1459 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && | 1482 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && |
1460 | synaptics_is_pt_packet(psmouse->packet)) { | 1483 | synaptics_is_pt_packet(psmouse->packet)) { |
1461 | if (priv->pt_port) | 1484 | if (priv->pt_port) |
1462 | synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); | 1485 | synaptics_pass_pt_packet(psmouse, priv->pt_port, |
1486 | psmouse->packet); | ||
1463 | } else | 1487 | } else |
1464 | synaptics_process_packet(psmouse); | 1488 | synaptics_process_packet(psmouse); |
1465 | 1489 | ||
@@ -1561,8 +1585,9 @@ static void set_input_params(struct psmouse *psmouse, | |||
1561 | __set_bit(BTN_BACK, dev->keybit); | 1585 | __set_bit(BTN_BACK, dev->keybit); |
1562 | } | 1586 | } |
1563 | 1587 | ||
1564 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 1588 | if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) |
1565 | __set_bit(BTN_0 + i, dev->keybit); | 1589 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) |
1590 | __set_bit(BTN_0 + i, dev->keybit); | ||
1566 | 1591 | ||
1567 | __clear_bit(EV_REL, dev->evbit); | 1592 | __clear_bit(EV_REL, dev->evbit); |
1568 | __clear_bit(REL_X, dev->relbit); | 1593 | __clear_bit(REL_X, dev->relbit); |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 8d3761ce8f54..f39539c70219 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -111,6 +111,10 @@ | |||
111 | #define SYN_CAP_EXT_BUTTONS_STICK(ex10) ((ex10) & 0x010000) | 111 | #define SYN_CAP_EXT_BUTTONS_STICK(ex10) ((ex10) & 0x010000) |
112 | #define SYN_CAP_SECUREPAD(ex10) ((ex10) & 0x020000) | 112 | #define SYN_CAP_SECUREPAD(ex10) ((ex10) & 0x020000) |
113 | 113 | ||
114 | #define SYN_CAP_EXT_BUTTON_STICK_L(eb) (!!((eb) & 0x01)) | ||
115 | #define SYN_CAP_EXT_BUTTON_STICK_M(eb) (!!((eb) & 0x02)) | ||
116 | #define SYN_CAP_EXT_BUTTON_STICK_R(eb) (!!((eb) & 0x04)) | ||
117 | |||
114 | /* synaptics modes query bits */ | 118 | /* synaptics modes query bits */ |
115 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 119 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
116 | #define SYN_MODE_RATE(m) ((m) & (1 << 6)) | 120 | #define SYN_MODE_RATE(m) ((m) & (1 << 6)) |
@@ -192,6 +196,7 @@ struct synaptics_data { | |||
192 | bool disable_gesture; /* disable gestures */ | 196 | bool disable_gesture; /* disable gestures */ |
193 | 197 | ||
194 | struct serio *pt_port; /* Pass-through serio port */ | 198 | struct serio *pt_port; /* Pass-through serio port */ |
199 | unsigned char pt_buttons; /* Pass-through buttons */ | ||
195 | 200 | ||
196 | struct synaptics_mt_state mt_state; /* Current mt finger state */ | 201 | struct synaptics_mt_state mt_state; /* Current mt finger state */ |
197 | bool mt_state_lost; /* mt_state may be incorrect */ | 202 | bool mt_state_lost; /* mt_state may be incorrect */ |