lkml.org 
[lkml]   [2023]   [Nov]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.15 10/22] HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround
    Date
    From: Mikhail Khvainitski <me@khvoinitsky.org>

    [ Upstream commit 46a0a2c96f0f47628190f122c2e3d879e590bcbe ]

    Built-in firmware of cptkbd handles scrolling by itself (when middle
    button is pressed) but with issues: it does not support horizontal and
    hi-res scrolling and upon middle button release it sends middle button
    click even if there was a scrolling event. Commit 3cb5ff0220e3 ("HID:
    lenovo: Hide middle-button press until release") workarounds last
    issue but it's impossible to workaround scrolling-related issues
    without firmware modification.

    Likely, Dennis Schneider has reverse engineered the firmware and
    provided an instruction on how to patch it [1]. However,
    aforementioned workaround prevents userspace (libinput) from knowing
    exact moment when middle button has been pressed down and performing
    "On-Button scrolling". This commit detects correctly-behaving patched
    firmware if cursor movement events has been received during middle
    button being pressed and stops applying workaround for this device.

    Link: https://hohlerde.org/rauch/en/elektronik/projekte/tpkbd-fix/ [1]

    Signed-off-by: Mikhail Khvainitski <me@khvoinitsky.org>
    Signed-off-by: Jiri Kosina <jkosina@suse.cz>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/hid/hid-lenovo.c | 68 ++++++++++++++++++++++++++--------------
    1 file changed, 45 insertions(+), 23 deletions(-)

    diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
    index 93b1f935e526e..901c1959efed4 100644
    --- a/drivers/hid/hid-lenovo.c
    +++ b/drivers/hid/hid-lenovo.c
    @@ -50,7 +50,12 @@ struct lenovo_drvdata {
    int select_right;
    int sensitivity;
    int press_speed;
    - u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
    + /* 0: Up
    + * 1: Down (undecided)
    + * 2: Scrolling
    + * 3: Patched firmware, disable workaround
    + */
    + u8 middlebutton_state;
    bool fn_lock;
    };

    @@ -529,31 +534,48 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
    {
    struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);

    - /* "wheel" scroll events */
    - if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
    - usage->code == REL_HWHEEL)) {
    - /* Scroll events disable middle-click event */
    - cptkbd_data->middlebutton_state = 2;
    - return 0;
    - }
    + if (cptkbd_data->middlebutton_state != 3) {
    + /* REL_X and REL_Y events during middle button pressed
    + * are only possible on patched, bug-free firmware
    + * so set middlebutton_state to 3
    + * to never apply workaround anymore
    + */
    + if (cptkbd_data->middlebutton_state == 1 &&
    + usage->type == EV_REL &&
    + (usage->code == REL_X || usage->code == REL_Y)) {
    + cptkbd_data->middlebutton_state = 3;
    + /* send middle button press which was hold before */
    + input_event(field->hidinput->input,
    + EV_KEY, BTN_MIDDLE, 1);
    + input_sync(field->hidinput->input);
    + }

    - /* Middle click events */
    - if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
    - if (value == 1) {
    - cptkbd_data->middlebutton_state = 1;
    - } else if (value == 0) {
    - if (cptkbd_data->middlebutton_state == 1) {
    - /* No scrolling inbetween, send middle-click */
    - input_event(field->hidinput->input,
    - EV_KEY, BTN_MIDDLE, 1);
    - input_sync(field->hidinput->input);
    - input_event(field->hidinput->input,
    - EV_KEY, BTN_MIDDLE, 0);
    - input_sync(field->hidinput->input);
    + /* "wheel" scroll events */
    + if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
    + usage->code == REL_HWHEEL)) {
    + /* Scroll events disable middle-click event */
    + cptkbd_data->middlebutton_state = 2;
    + return 0;
    + }
    +
    + /* Middle click events */
    + if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
    + if (value == 1) {
    + cptkbd_data->middlebutton_state = 1;
    + } else if (value == 0) {
    + if (cptkbd_data->middlebutton_state == 1) {
    + /* No scrolling inbetween, send middle-click */
    + input_event(field->hidinput->input,
    + EV_KEY, BTN_MIDDLE, 1);
    + input_sync(field->hidinput->input);
    + input_event(field->hidinput->input,
    + EV_KEY, BTN_MIDDLE, 0);
    + input_sync(field->hidinput->input);
    + }
    + cptkbd_data->middlebutton_state = 0;
    }
    - cptkbd_data->middlebutton_state = 0;
    + return 1;
    }
    - return 1;
    }

    return 0;
    --
    2.42.0
    \
     
     \ /
      Last update: 2023-11-20 13:51    [W:3.653 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site