aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/mouse/trackpoint.c50
-rw-r--r--drivers/input/mouse/trackpoint.h5
2 files changed, 55 insertions, 0 deletions
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 3bd8fdf56cd3..070702ef3105 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -18,6 +18,9 @@
#include "psmouse.h"
#include "trackpoint.h"
+static bool trackpoint_middle_cancel;
+module_param_named(trackpoint_middle_cancel, trackpoint_middle_cancel, bool, 0444);
+
static const char * const trackpoint_variants[] = {
[TP_VARIANT_IBM] = "IBM",
[TP_VARIANT_ALPS] = "ALPS",
@@ -27,6 +30,46 @@ static const char * const trackpoint_variants[] = {
[TP_VARIANT_SYNAPTICS] = "Synaptics",
};
+static u8 trackpoint_cancel_buttons(struct trackpoint_data *tp, u8 buttons)
+{
+ u8 previous = tp->cancel_last_buttons;
+ u8 raw = buttons;
+ u8 pressed = raw & ~previous & (BIT(0) | BIT(1));
+
+ tp->cancel_consumed_buttons &= raw;
+
+ if (!tp->cancel_middle && (raw & BIT(2)) && (previous & BIT(2)) && pressed) {
+ tp->cancel_middle = true;
+ tp->cancel_consumed_buttons |= pressed;
+ }
+
+ if (tp->cancel_middle) {
+ if (!(raw & BIT(2)) && (previous & BIT(2)))
+ tp->cancel_middle = false;
+ buttons &= ~BIT(2);
+ }
+ buttons &= ~tp->cancel_consumed_buttons;
+
+ tp->cancel_last_buttons = raw;
+ return buttons;
+}
+
+static psmouse_ret_t trackpoint_process_byte(struct psmouse *psmouse)
+{
+ struct trackpoint_data *tp = psmouse->private;
+ u8 buttons;
+
+ if (psmouse->pktcnt < psmouse->pktsize)
+ return PSMOUSE_GOOD_DATA;
+
+ buttons = trackpoint_cancel_buttons(tp, psmouse->packet[0]);
+ psmouse_report_standard_buttons(psmouse->dev, buttons);
+ psmouse_report_standard_motion(psmouse->dev, psmouse->packet);
+ input_sync(psmouse->dev);
+
+ return PSMOUSE_FULL_PACKET;
+}
+
/*
* Power-on Reset: Resets all trackpoint parameters, including RAM values,
* to defaults.
@@ -381,6 +424,10 @@ static int trackpoint_reconnect(struct psmouse *psmouse)
int error;
bool was_reset;
+ tp->cancel_last_buttons = 0;
+ tp->cancel_middle = false;
+ tp->cancel_consumed_buttons = 0;
+
error = trackpoint_start_protocol(psmouse, NULL, NULL);
if (error)
return error;
@@ -516,6 +563,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
psmouse_warn(psmouse, "Failed to enable doubletap: %d\n", error);
}
+ if (trackpoint_middle_cancel)
+ psmouse->protocol_handler = trackpoint_process_byte;
+
return 0;
}
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index 3e03cdb39449..9b276a123c15 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -156,6 +156,11 @@ struct trackpoint_data {
u8 ztime, jenks;
u8 drift_time;
+ /* middle button cancelation */
+ u8 cancel_last_buttons;
+ u8 cancel_consumed_buttons;
+ bool cancel_middle;
+
/* toggles */
bool press_to_select;
bool skipback;