public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Mikhail Khvainitski <me@khvoinitsky.org>,
	Jiri Kosina <jkosina@suse.cz>, Sasha Levin <sashal@kernel.org>,
	jikos@kernel.org, benjamin.tissoires@redhat.com,
	linux-input@vger.kernel.org
Subject: [PATCH AUTOSEL 5.10 08/16] HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround
Date: Tue,  7 Nov 2023 10:52:27 -0500	[thread overview]
Message-ID: <20231107155249.3768098-8-sashal@kernel.org> (raw)
In-Reply-To: <20231107155249.3768098-1-sashal@kernel.org>

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 0ff03fed97709..71f7b0d539df5 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;
 };
 
@@ -478,31 +483,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


  parent reply	other threads:[~2023-11-07 16:01 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-07 15:52 [PATCH AUTOSEL 5.10 01/16] ASoC: soc-card: Add storage for PCI SSID Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 02/16] crypto: pcrypt - Fix hungtask for PADATA_RESET Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 03/16] RDMA/hfi1: Use FIELD_GET() to extract Link Width Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 04/16] fs/jfs: Add check for negative db_l2nbperpage Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 05/16] fs/jfs: Add validity check for db_maxag and db_agpref Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 06/16] jfs: fix array-index-out-of-bounds in dbFindLeaf Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 07/16] jfs: fix array-index-out-of-bounds in diAlloc Sasha Levin
2023-11-07 15:52 ` Sasha Levin [this message]
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 09/16] ARM: 9320/1: fix stack depot IRQ stack filter Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 10/16] ALSA: hda: Fix possible null-ptr-deref when assigning a stream Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 11/16] PCI: tegra194: Use FIELD_GET()/FIELD_PREP() with Link Width fields Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 12/16] atm: iphase: Do PCI error checks on own line Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 13/16] scsi: libfc: Fix potential NULL pointer dereference in fc_lport_ptp_setup() Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 14/16] misc: pci_endpoint_test: Add Device ID for R-Car S4-8 PCIe controller Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 15/16] HID: Add quirk for Dell Pro Wireless Keyboard and Mouse KM5221W Sasha Levin
2023-11-07 15:52 ` [PATCH AUTOSEL 5.10 16/16] exfat: support handle zero-size directory Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231107155249.3768098-8-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=benjamin.tissoires@redhat.com \
    --cc=jikos@kernel.org \
    --cc=jkosina@suse.cz \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=me@khvoinitsky.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox