diff options
| -rw-r--r-- | drivers/input/mouse/trackpoint.c | 50 | ||||
| -rw-r--r-- | drivers/input/mouse/trackpoint.h | 5 |
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; |
