summaryrefslogtreecommitdiff
path: root/drivers/input/rmi4/rmi_f03.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2017-02-08 00:26:45 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2017-02-09 13:01:34 -0800
commit81dec809aa728798c3ebff18c3d2d678237273aa (patch)
treea60e4a786645739776741b2f2b6b37082e1edee4 /drivers/input/rmi4/rmi_f03.c
parentbf3e8502eefdbb7ac1b8163e5c3acdcb505ae745 (diff)
Input: synaptics-rmi4 - forward upper mechanical buttons to PS/2 guest
On the latest series of ThinkPads, the button events for the TrackPoint are reported through the touchpad itself as opposed to the TrackPoint device. In order to report these buttons properly, we need to forward them to the TrackPoint device and notify psmouse to send the button presses/releases. Signed-off-by: Lyude Paul <thatslyude@gmail.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/rmi4/rmi_f03.c')
-rw-r--r--drivers/input/rmi4/rmi_f03.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
index 9a1b099b72e0..77dad045a468 100644
--- a/drivers/input/rmi4/rmi_f03.c
+++ b/drivers/input/rmi4/rmi_f03.c
@@ -26,15 +26,53 @@
#define RMI_F03_BYTES_PER_DEVICE_SHIFT 4
#define RMI_F03_QUEUE_LENGTH 0x0F
+#define PSMOUSE_OOB_EXTRA_BTNS 0x01
+
struct f03_data {
struct rmi_function *fn;
struct serio *serio;
+ unsigned int overwrite_buttons;
+
u8 device_count;
u8 rx_queue_length;
};
+int rmi_f03_overwrite_button(struct rmi_function *fn, unsigned int button,
+ int value)
+{
+ struct f03_data *f03 = dev_get_drvdata(&fn->dev);
+ unsigned int bit;
+
+ if (button < BTN_LEFT || button > BTN_MIDDLE)
+ return -EINVAL;
+
+ bit = BIT(button - BTN_LEFT);
+
+ if (value)
+ f03->overwrite_buttons |= bit;
+ else
+ f03->overwrite_buttons &= ~bit;
+
+ return 0;
+}
+
+void rmi_f03_commit_buttons(struct rmi_function *fn)
+{
+ struct f03_data *f03 = dev_get_drvdata(&fn->dev);
+ struct serio *serio = f03->serio;
+
+ serio_pause_rx(serio);
+ if (serio->drv) {
+ serio->drv->interrupt(serio, PSMOUSE_OOB_EXTRA_BTNS,
+ SERIO_OOB_DATA);
+ serio->drv->interrupt(serio, f03->overwrite_buttons,
+ SERIO_OOB_DATA);
+ }
+ serio_continue_rx(serio);
+}
+
static int rmi_f03_pt_write(struct serio *id, unsigned char val)
{
struct f03_data *f03 = id->port_data;