mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling
@ 2026-09-22 17:40 Erik Håkansson
  2026-09-22 17:40 ` [PATCH 1/2] HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master Erik Håkansson
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Erik Håkansson @ 2026-09-22 17:40 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: Filipe Laíns, Bastien Nocera, Rafael Passos,
	Grégoire Stein, Alexey Zagorodnikov, Oleksandr Natalenko,
	Roman Stingler, Lovekesh Solanki,
	Kateřina Medvědová,
	linux-input, linux-kernel, Erik Håkansson

This series aims to fix high-resolution wheel handling for Logitech devices
connected through Bolt receivers as well as respect user settings for
scroll behaviour.

Patch 1 is Rafael Passos’s original implementation:

https://lore.kernel.org/linux-input/20260904034843.1340846-1-rafael@rcpassos.me/

His patch routes Bolt wheel movement through the HID++ child, where the
device’s HiRes Wheel multiplier can be applied. Patch 2 builds on
Rafael’s work by 1. supporting both high-resolution and low-resolution
scroll events, and 2. preserving user-selected high-resolution and
inversion settings.

The follow-up patch was developed with reference to the patches and
reported behavior in Magnetar-OS’s `logitech-bolt-hidpp-dkms` repository:

https://github.com/Magnetar-OS/logitech-bolt-hidpp-dkms/tree/main/patches

So my assumption right now is that the reason for the divergent results
people have had with the two different fix approaches (i.e. either passing
interface 0 and 1 as DJ interfaces, or Rafael's approach), where it works
for some, and only sometimes, etc. is that with user settings coming from
Solaar, we may end up in weird states.
For example, in the original patch, high-resolution events would go through
the generic HID which would treat each tick as a full wheel event, thus 
scaling the scroll way too far. That was solved with Rafael's patch but
that would instead fail to handle low-resolution events if high resolution
was turned off in Solaar while use_hidpp remained enabled, so a low-resolution
delta would be treated as high-resolution, which would result instead in a 
too slow scroll. Possibly, when Oleksandr switched devices, Solaar reapplied
some saved user settings, which conflicted with the driver logic.

With this patch, user settings from Solaar (or elsewhere) for high-resolution
mode and scroll inversion will be respected, 
and scrolling should work both in high-resolution and low-resolution mode.
However, if user-space turns off the use_hidpp setting while high_resolution
remains on, this will route high-resolution scroll events to generic HID.
Thus, when high_resolution is on for a Bolt device, the driver will
force use_hidpp to be on during initialisation or reinitialisation, because
otherwise the scaling issue will return.
Solaar may still, after driver initialisation, reapply a saved use_hidpp
setting of off while high_resolution remains on, or the user may change it
to off, which will cause the issue even with this patch.

In theory, it should be possible to look at incoming setWheelMode responses
or notifications and, just like on initialisation, enforce use_hidpp as long
as high_resolution is set on a Bolt device. However, I don't know how Solaar
will behave then. There's a risk it will trigger a back-and-forth if Solaar
reapplies its saved setting after the kernel corrects it. Also, even if that
doesn't happen, we should respect user choice even for use_hidpp. Perhaps
the Solaar team can be informed about the problem so they can add a warning
text.

Note that I don't have a Bolt mouse to test this with, and my theory is 
mostly inferred, so I would appreciate very much if people with various
Bolt mice could test it out. Also great if you try different settings in 
Solaar, but note that use_hidpp must be on if high_resolution is on, so 
either set it to on in Solaar, or to ignore.

Link: https://lore.kernel.org/linux-input/20260712003051.338194-2-erikhakan@gmail.com/
Link: https://lore.kernel.org/linux-input/20260901-bolt-scroll-fix-v1-1-58bca7ae487f@protonmail.com/
Link: https://lore.kernel.org/linux-input/LYMlyJcyQt29e1KlLnEoLw@natalenko.name/
Link: https://lore.kernel.org/linux-input/20260920094508.39682-1-roman.stingler@gmail.com/
Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
---
Erik Håkansson (1):
      HID: logitech-hidpp: fix Bolt wheel mode handling

Rafael Passos (1):
      HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master

 drivers/hid/hid-logitech-hidpp.c | 147 ++++++++++++++++++++++++++++++++-------
 1 file changed, 123 insertions(+), 24 deletions(-)
---
base-commit: 022eb347ff3a48281e7e69c3addcb11bf24afa53
change-id: 20260921-feature-bolt-fix-5f1f642496df

Best regards,
-- 
Erik Håkansson <erikhakan@gmail.com>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master
  2026-09-22 17:40 [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Erik Håkansson
@ 2026-09-22 17:40 ` Erik Håkansson
  2026-09-22 17:40 ` [PATCH 2/2] HID: logitech-hidpp: fix Bolt wheel mode handling Erik Håkansson
  2026-09-23  6:39 ` [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Oleksandr Natalenko
  2 siblings, 0 replies; 6+ messages in thread
From: Erik Håkansson @ 2026-09-22 17:40 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: Filipe Laíns, Bastien Nocera, Rafael Passos,
	Grégoire Stein, Alexey Zagorodnikov, Oleksandr Natalenko,
	Roman Stingler, Lovekesh Solanki,
	Kateřina Medvědová,
	linux-input, linux-kernel, Erik Håkansson

From: Rafael Passos <rafael@rcpassos.me>

The new added support for Logitech HID++ caused this mouse to
scroll too far for each tic when using the USB dongle (Bolt).
Previously, this mouse was handled as hid_generic over the Bold
connection, and logitech-hidpp when over Bluetooth.

Cause:
Over the Bolt receiver, the mouse reports  are forwarded over the generic
interface 1, instead of the new HID++ child device. The generic hid does
now know about the hi-res scrolling used by the HID++.
In my tests, I discovered this mouse has a multiplier factor of 15. This
multiplier is only handled by the logitech-hidpp driver. When piped to
hid_generic, the "hi-res" value was piped to a "low-res" field, making
the scroll unbearable.

The fix routes the wheel using the HID++, so the ticks are scaled by the
multiplier and correctly reported as a hi-res event.

I also had to move the hidpp_is_bolt_child function up, to use it in the
hidpp_connect_event function, where the gate for
hidpp_initialize_hires_scroll function lives.

Tested with:
- Logitech MX Master 3S (mouse) via Bolt receiver and Bluetooth.

Fixes: 022eb347ff3a ("HID: logitech: add Bolt receiver support for Logitech HID++ devices")
Signed-off-by: Rafael Passos <rafael@rcpassos.me>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Tested-by: Alexey Zagorodnikov <xglooom@gmail.com>
---
 drivers/hid/hid-logitech-hidpp.c | 47 +++++++++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 4e00ac91493f..166980be57b7 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -3891,6 +3891,19 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,
 	return 1;
 }
 
+static bool hidpp_is_bolt_child(struct hid_device *hdev)
+{
+	struct device *parent = hdev->dev.parent;
+	struct hid_device *receiver_hdev;
+
+	if (!parent)
+		return false;
+
+	receiver_hdev = to_hid_device(parent);
+	return receiver_hdev->vendor == USB_VENDOR_ID_LOGITECH &&
+	       receiver_hdev->product == USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER;
+}
+
 /* -------------------------------------------------------------------------- */
 /* High-resolution scroll wheels                                              */
 /* -------------------------------------------------------------------------- */
@@ -3901,7 +3914,9 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
 	u8 multiplier = 1;
 
 	if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) {
-		ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false);
+		bool use_hidpp = hidpp_is_bolt_child(hidpp->hid_dev);
+
+		ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, use_hidpp);
 		if (ret == 0)
 			ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier);
 	} else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL) {
@@ -3989,6 +4004,19 @@ static int hidpp20_hires_wheel_raw_event(struct hidpp_device *hidpp,
 		return 1;
 	}
 
+	/* wheel movement event: 16-bit signed delta in HID++ ticks */
+	if ((data[3] & 0xf0) == 0x00 && size >= 7 && hidpp->input &&
+	    hidpp->vertical_wheel_counter.wheel_multiplier) {
+		s16 delta = get_unaligned_be16(&data[5]);
+
+		if (delta) {
+			hidpp_scroll_counter_handle_scroll(hidpp->input,
+				&hidpp->vertical_wheel_counter, delta);
+			input_sync(hidpp->input);
+		}
+		return 1;
+	}
+
 	return 0;
 }
 
@@ -4379,19 +4407,6 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
 	return ret;
 }
 
-static bool hidpp_is_bolt_child(struct hid_device *hdev)
-{
-	struct device *parent = hdev->dev.parent;
-	struct hid_device *receiver_hdev;
-
-	if (!parent)
-		return false;
-
-	receiver_hdev = to_hid_device(parent);
-	return receiver_hdev->vendor == USB_VENDOR_ID_LOGITECH &&
-	       receiver_hdev->product == USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER;
-}
-
 static int hidpp_bolt_init(struct hidpp_device *hidpp)
 {
 	struct hid_device *hdev = hidpp->hid_dev;
@@ -4553,7 +4568,9 @@ static void hidpp_connect_event(struct work_struct *work)
 	}
 
 	hidpp_initialize_battery(hidpp);
-	if (!hid_is_usb(hidpp->hid_dev))
+
+	if (!hid_is_usb(hidpp->hid_dev) ||
+	    hidpp_is_bolt_child(hidpp->hid_dev))
 		hidpp_initialize_hires_scroll(hidpp);
 
 	/* forward current battery state */

-- 
2.55.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/2] HID: logitech-hidpp: fix Bolt wheel mode handling
  2026-09-22 17:40 [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Erik Håkansson
  2026-09-22 17:40 ` [PATCH 1/2] HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master Erik Håkansson
@ 2026-09-22 17:40 ` Erik Håkansson
  2026-09-23  6:39 ` [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Oleksandr Natalenko
  2 siblings, 0 replies; 6+ messages in thread
From: Erik Håkansson @ 2026-09-22 17:40 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: Filipe Laíns, Bastien Nocera, Rafael Passos,
	Grégoire Stein, Alexey Zagorodnikov, Oleksandr Natalenko,
	Roman Stingler, Lovekesh Solanki,
	Kateřina Medvědová,
	linux-input, linux-kernel, Erik Håkansson

Preserve the device's user-selected resolution and inversion settings
while enabling HID++ wheel notifications for Bolt devices. Track diverted
wheel events and apply the device multiplier to both high- and
low-resolution events.

Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
---
 drivers/hid/hid-logitech-hidpp.c | 112 +++++++++++++++++++++++++++++++++------
 1 file changed, 97 insertions(+), 15 deletions(-)

diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 166980be57b7..55e9ac5e5ab7 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -213,6 +213,7 @@ struct hidpp_device {
 
 	int hires_wheel_multiplier;
 	u8 hires_wheel_feature_index;
+	bool hires_wheel_diverted; /* whether wheel events use HID++ notifications */
 
 	bool connected_once;
 };
@@ -2043,8 +2044,14 @@ static int hidpp_hrs_set_highres_scrolling_mode(struct hidpp_device *hidpp,
 
 #define HIDPP_PAGE_HIRES_WHEEL		0x2121
 
+#define EVENT_HIRES_WHEEL_MOVEMENT		0x00
 #define CMD_HIRES_WHEEL_GET_WHEEL_CAPABILITY	0x00
+#define CMD_HIRES_WHEEL_GET_WHEEL_MODE		0x10
 #define CMD_HIRES_WHEEL_SET_WHEEL_MODE		0x20
+#define HIRES_WHEEL_MODE_USE_HIDPP		BIT(0)
+#define HIRES_WHEEL_MODE_HIGH_RESOLUTION	BIT(1)
+#define HIRES_WHEEL_MODE_INVERT			BIT(2)
+#define HIRES_WHEEL_EVENT_HIGH_RESOLUTION	BIT(4)
 
 static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp,
 	u8 *multiplier)
@@ -2072,6 +2079,26 @@ static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp,
 	return ret;
 }
 
+static int hidpp_hrw_get_wheel_mode(struct hidpp_device *hidpp, u8 *mode)
+{
+	u8 feature_index;
+	struct hidpp_report response;
+
+	int ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
+					 &feature_index);
+	if (ret)
+		return ret;
+
+	ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+					  CMD_HIRES_WHEEL_GET_WHEEL_MODE,
+					  NULL, 0, &response);
+	if (ret)
+		return ret;
+
+	*mode = response.fap.params[0];
+	return 0;
+}
+
 static int hidpp_hrw_set_wheel_mode(struct hidpp_device *hidpp, bool invert,
 	bool high_resolution, bool use_hidpp)
 {
@@ -2085,9 +2112,9 @@ static int hidpp_hrw_set_wheel_mode(struct hidpp_device *hidpp, bool invert,
 	if (ret)
 		return ret;
 
-	params[0] = (invert          ? BIT(2) : 0) |
-		    (high_resolution ? BIT(1) : 0) |
-		    (use_hidpp       ? BIT(0) : 0);
+	params[0] = (invert          ? HIRES_WHEEL_MODE_INVERT : 0) |
+		    (high_resolution ? HIRES_WHEEL_MODE_HIGH_RESOLUTION : 0) |
+		    (use_hidpp       ? HIRES_WHEEL_MODE_USE_HIDPP : 0);
 
 	return hidpp_send_fap_command_sync(hidpp, feature_index,
 					   CMD_HIRES_WHEEL_SET_WHEEL_MODE,
@@ -3912,16 +3939,43 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
 {
 	int ret;
 	u8 multiplier = 1;
+	bool high_resolution = true;
+	const bool is_bolt = hidpp_is_bolt_child(hidpp->hid_dev);
+
+	if (is_bolt)
+		hidpp->hires_wheel_diverted = false;
 
 	if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) {
-		bool use_hidpp = hidpp_is_bolt_child(hidpp->hid_dev);
+		u8 mode;
+
+		/* Preserve the persistent mode, except for Bolt event routing. */
+		ret = hidpp_hrw_get_wheel_mode(hidpp, &mode);
+		if (ret == 0) {
+			bool invert = mode & HIRES_WHEEL_MODE_INVERT;
+			bool use_hidpp = mode & HIRES_WHEEL_MODE_USE_HIDPP;
+
+			high_resolution = mode & HIRES_WHEEL_MODE_HIGH_RESOLUTION;
+
+			/* Preserve user-set resolution and inversion; enable HID++ for Bolt. */
+			if (is_bolt && high_resolution && !use_hidpp) {
+				ret = hidpp_hrw_set_wheel_mode(hidpp, invert,
+							       high_resolution, true);
+				if (ret == 0)
+					use_hidpp = true;
+			}
 
-		ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, use_hidpp);
-		if (ret == 0)
-			ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier);
+			if (ret == 0)
+				ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier);
+			if (ret == 0)
+				hidpp->hires_wheel_diverted = use_hidpp;
+		}
 	} else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL) {
-		ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true,
+		/* Bolt reports for this feature also bypass hid-logitech-hidpp. */
+		high_resolution = !is_bolt;
+		ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, !is_bolt,
 							   &multiplier);
+		if (!ret && is_bolt)
+			multiplier = 1;
 	} else /* if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL) */ {
 		ret = hidpp10_enable_scrolling_acceleration(hidpp);
 		multiplier = 8;
@@ -3938,8 +3992,12 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
 		multiplier = 1;
 	}
 
+	/* Keep the device-reported multiplier for HID++ event conversion. */
 	hidpp->hires_wheel_multiplier = multiplier;
-	hidpp->vertical_wheel_counter.wheel_multiplier = multiplier;
+	/* Apply the multiplier only while high-resolution mode or HID++ diversion is active. */
+	hidpp->vertical_wheel_counter.wheel_multiplier =
+	(high_resolution || hidpp->hires_wheel_diverted) ?
+		multiplier : 1;
 	hid_dbg(hidpp->hid_dev, "wheel multiplier = %d\n", multiplier);
 	return 0;
 }
@@ -3997,17 +4055,41 @@ static int hidpp20_hires_wheel_raw_event(struct hidpp_device *hidpp,
 
 	if ((data[3] & 0xf0) == CMD_HIRES_WHEEL_SET_WHEEL_MODE) {
 		u8 mode = data[4];
-		bool hires = (mode & 0x02) != 0;
-		int new_multiplier = (hires && hidpp->hires_wheel_multiplier > 0)
+		bool hires = mode & HIRES_WHEEL_MODE_HIGH_RESOLUTION;
+		bool use_hidpp = mode & HIRES_WHEEL_MODE_USE_HIDPP;
+		int new_multiplier = ((hires || use_hidpp) &&
+				      hidpp->hires_wheel_multiplier > 0)
 			? hidpp->hires_wheel_multiplier : 1;
+
+		hidpp->hires_wheel_diverted = use_hidpp;
 		hidpp->vertical_wheel_counter.wheel_multiplier = new_multiplier;
 		return 1;
 	}
 
-	/* wheel movement event: 16-bit signed delta in HID++ ticks */
-	if ((data[3] & 0xf0) == 0x00 && size >= 7 && hidpp->input &&
-	    hidpp->vertical_wheel_counter.wheel_multiplier) {
-		s16 delta = get_unaligned_be16(&data[5]);
+	/*
+	 * HID++ 0x2121 wheelMovement event:
+	 *   data[3]    = event/function index in the upper nibble (0x0),
+	 *                client ID in the lower nibble
+	 *   data[4]    = event flags; bit 4 indicates high-resolution units
+	 *   data[5:6]  = signed 16-bit big-endian vertical wheel delta
+	 *
+	 * The outer HID++ path normally validates long reports as 20 bytes, but
+	 * keep the size check below before reading data[5:6] from the buffer.
+	 * Low-resolution deltas are converted using the device's multiplier
+	 * before being passed to the scroll counter.
+	 */
+	if (data[3] == EVENT_HIRES_WHEEL_MOVEMENT && hidpp->hires_wheel_diverted) {
+		int delta;
+
+		if (size < 7 || !hidpp->input ||
+		    !hidpp->vertical_wheel_counter.wheel_multiplier ||
+		    !hidpp->hires_wheel_multiplier)
+			return 1;
+
+		delta = (s16)get_unaligned_be16(&data[5]);
+		if (!(data[4] & HIRES_WHEEL_EVENT_HIGH_RESOLUTION))
+			/* low-resolution delta: convert to hi-res units */
+			delta *= hidpp->hires_wheel_multiplier;
 
 		if (delta) {
 			hidpp_scroll_counter_handle_scroll(hidpp->input,

-- 
2.55.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling
  2026-09-22 17:40 [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Erik Håkansson
  2026-09-22 17:40 ` [PATCH 1/2] HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master Erik Håkansson
  2026-09-22 17:40 ` [PATCH 2/2] HID: logitech-hidpp: fix Bolt wheel mode handling Erik Håkansson
@ 2026-09-23  6:39 ` Oleksandr Natalenko
  2026-09-23  7:54   ` Benjamin Tissoires
  2 siblings, 1 reply; 6+ messages in thread
From: Oleksandr Natalenko @ 2026-09-23  6:39 UTC (permalink / raw)
  To: Erik Håkansson
  Cc: Jiri Kosina, Benjamin Tissoires, Filipe Laíns,
	Bastien Nocera, Rafael Passos, Grégoire Stein,
	Alexey Zagorodnikov, Roman Stingler, Lovekesh Solanki,
	Kateřina Medvědová,
	linux-input, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4902 bytes --]

Hello.

On úterý 22. září 2026 19:40:26, středoevropský letní čas Erik Håkansson wrote:
> This series aims to fix high-resolution wheel handling for Logitech devices
> connected through Bolt receivers as well as respect user settings for
> scroll behaviour.
> 
> Patch 1 is Rafael Passos’s original implementation:
> 
> https://lore.kernel.org/linux-input/20260904034843.1340846-1-rafael@rcpassos.me/
> 
> His patch routes Bolt wheel movement through the HID++ child, where the
> device’s HiRes Wheel multiplier can be applied. Patch 2 builds on
> Rafael’s work by 1. supporting both high-resolution and low-resolution
> scroll events, and 2. preserving user-selected high-resolution and
> inversion settings.
> 
> The follow-up patch was developed with reference to the patches and
> reported behavior in Magnetar-OS’s `logitech-bolt-hidpp-dkms` repository:
> 
> https://github.com/Magnetar-OS/logitech-bolt-hidpp-dkms/tree/main/patches
> 
> So my assumption right now is that the reason for the divergent results
> people have had with the two different fix approaches (i.e. either passing
> interface 0 and 1 as DJ interfaces, or Rafael's approach), where it works
> for some, and only sometimes, etc. is that with user settings coming from
> Solaar, we may end up in weird states.
> For example, in the original patch, high-resolution events would go through
> the generic HID which would treat each tick as a full wheel event, thus 
> scaling the scroll way too far. That was solved with Rafael's patch but
> that would instead fail to handle low-resolution events if high resolution
> was turned off in Solaar while use_hidpp remained enabled, so a low-resolution
> delta would be treated as high-resolution, which would result instead in a 
> too slow scroll. Possibly, when Oleksandr switched devices, Solaar reapplied
> some saved user settings, which conflicted with the driver logic.
> 
> With this patch, user settings from Solaar (or elsewhere) for high-resolution
> mode and scroll inversion will be respected, 
> and scrolling should work both in high-resolution and low-resolution mode.
> However, if user-space turns off the use_hidpp setting while high_resolution
> remains on, this will route high-resolution scroll events to generic HID.
> Thus, when high_resolution is on for a Bolt device, the driver will
> force use_hidpp to be on during initialisation or reinitialisation, because
> otherwise the scaling issue will return.
> Solaar may still, after driver initialisation, reapply a saved use_hidpp
> setting of off while high_resolution remains on, or the user may change it
> to off, which will cause the issue even with this patch.
> 
> In theory, it should be possible to look at incoming setWheelMode responses
> or notifications and, just like on initialisation, enforce use_hidpp as long
> as high_resolution is set on a Bolt device. However, I don't know how Solaar
> will behave then. There's a risk it will trigger a back-and-forth if Solaar
> reapplies its saved setting after the kernel corrects it. Also, even if that
> doesn't happen, we should respect user choice even for use_hidpp. Perhaps
> the Solaar team can be informed about the problem so they can add a warning
> text.
> 
> Note that I don't have a Bolt mouse to test this with, and my theory is 
> mostly inferred, so I would appreciate very much if people with various
> Bolt mice could test it out. Also great if you try different settings in 
> Solaar, but note that use_hidpp must be on if high_resolution is on, so 
> either set it to on in Solaar, or to ignore.
> 
> Link: https://lore.kernel.org/linux-input/20260712003051.338194-2-erikhakan@gmail.com/
> Link: https://lore.kernel.org/linux-input/20260901-bolt-scroll-fix-v1-1-58bca7ae487f@protonmail.com/
> Link: https://lore.kernel.org/linux-input/LYMlyJcyQt29e1KlLnEoLw@natalenko.name/
> Link: https://lore.kernel.org/linux-input/20260920094508.39682-1-roman.stingler@gmail.com/
> Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
> ---
> Erik Håkansson (1):
>       HID: logitech-hidpp: fix Bolt wheel mode handling
> 
> Rafael Passos (1):
>       HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master
> 
>  drivers/hid/hid-logitech-hidpp.c | 147 ++++++++++++++++++++++++++++++++-------
>  1 file changed, 123 insertions(+), 24 deletions(-)
> ---
> base-commit: 022eb347ff3a48281e7e69c3addcb11bf24afa53
> change-id: 20260921-feature-bolt-fix-5f1f642496df
> 
> Best regards,

Not sure if I'm testing this right, but with v7.3-rc4 and these two patches scrolling works OK as long as I keep "Scroll Wheel Resolution" in Solaar off. Unlike with unpatched kernel, scrolling doesn't go crazy if I switch between devices. But if I switch "Scroll Wheel Resolution" on, scrolling jumps crazy again.

-- 
Oleksandr Natalenko, MSE

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling
  2026-09-23  6:39 ` [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Oleksandr Natalenko
@ 2026-09-23  7:54   ` Benjamin Tissoires
  2026-09-23 16:09     ` erikhakan
  0 siblings, 1 reply; 6+ messages in thread
From: Benjamin Tissoires @ 2026-09-23  7:54 UTC (permalink / raw)
  To: Oleksandr Natalenko
  Cc: Erik Håkansson, Jiri Kosina, Filipe Laíns,
	Bastien Nocera, Rafael Passos, Grégoire Stein,
	Alexey Zagorodnikov, Roman Stingler, Lovekesh Solanki,
	Kateřina Medvědová,
	linux-input, linux-kernel

On Sep 23 2026, Oleksandr Natalenko wrote:
> Hello.
> 
> On úterý 22. září 2026 19:40:26, středoevropský letní čas Erik Håkansson wrote:
> > This series aims to fix high-resolution wheel handling for Logitech devices
> > connected through Bolt receivers as well as respect user settings for
> > scroll behaviour.
> > 
> > Patch 1 is Rafael Passos’s original implementation:
> > 
> > https://lore.kernel.org/linux-input/20260904034843.1340846-1-rafael@rcpassos.me/
> > 
> > His patch routes Bolt wheel movement through the HID++ child, where the
> > device’s HiRes Wheel multiplier can be applied. Patch 2 builds on
> > Rafael’s work by 1. supporting both high-resolution and low-resolution
> > scroll events, and 2. preserving user-selected high-resolution and
> > inversion settings.
> > 
> > The follow-up patch was developed with reference to the patches and
> > reported behavior in Magnetar-OS’s `logitech-bolt-hidpp-dkms` repository:
> > 
> > https://github.com/Magnetar-OS/logitech-bolt-hidpp-dkms/tree/main/patches
> > 
> > So my assumption right now is that the reason for the divergent results
> > people have had with the two different fix approaches (i.e. either passing
> > interface 0 and 1 as DJ interfaces, or Rafael's approach), where it works
> > for some, and only sometimes, etc. is that with user settings coming from
> > Solaar, we may end up in weird states.
> > For example, in the original patch, high-resolution events would go through
> > the generic HID which would treat each tick as a full wheel event, thus 
> > scaling the scroll way too far. That was solved with Rafael's patch but
> > that would instead fail to handle low-resolution events if high resolution
> > was turned off in Solaar while use_hidpp remained enabled, so a low-resolution
> > delta would be treated as high-resolution, which would result instead in a 
> > too slow scroll. Possibly, when Oleksandr switched devices, Solaar reapplied
> > some saved user settings, which conflicted with the driver logic.
> > 
> > With this patch, user settings from Solaar (or elsewhere) for high-resolution
> > mode and scroll inversion will be respected, 
> > and scrolling should work both in high-resolution and low-resolution mode.
> > However, if user-space turns off the use_hidpp setting while high_resolution
> > remains on, this will route high-resolution scroll events to generic HID.
> > Thus, when high_resolution is on for a Bolt device, the driver will
> > force use_hidpp to be on during initialisation or reinitialisation, because
> > otherwise the scaling issue will return.
> > Solaar may still, after driver initialisation, reapply a saved use_hidpp
> > setting of off while high_resolution remains on, or the user may change it
> > to off, which will cause the issue even with this patch.
> > 
> > In theory, it should be possible to look at incoming setWheelMode responses
> > or notifications and, just like on initialisation, enforce use_hidpp as long
> > as high_resolution is set on a Bolt device. However, I don't know how Solaar
> > will behave then. There's a risk it will trigger a back-and-forth if Solaar
> > reapplies its saved setting after the kernel corrects it. Also, even if that
> > doesn't happen, we should respect user choice even for use_hidpp. Perhaps
> > the Solaar team can be informed about the problem so they can add a warning
> > text.
> > 
> > Note that I don't have a Bolt mouse to test this with, and my theory is 
> > mostly inferred, so I would appreciate very much if people with various
> > Bolt mice could test it out. Also great if you try different settings in 
> > Solaar, but note that use_hidpp must be on if high_resolution is on, so 
> > either set it to on in Solaar, or to ignore.
> > 
> > Link: https://lore.kernel.org/linux-input/20260712003051.338194-2-erikhakan@gmail.com/
> > Link: https://lore.kernel.org/linux-input/20260901-bolt-scroll-fix-v1-1-58bca7ae487f@protonmail.com/
> > Link: https://lore.kernel.org/linux-input/LYMlyJcyQt29e1KlLnEoLw@natalenko.name/
> > Link: https://lore.kernel.org/linux-input/20260920094508.39682-1-roman.stingler@gmail.com/
> > Signed-off-by: Erik Håkansson <erikhakan@gmail.com>
> > ---
> > Erik Håkansson (1):
> >       HID: logitech-hidpp: fix Bolt wheel mode handling
> > 
> > Rafael Passos (1):
> >       HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master
> > 
> >  drivers/hid/hid-logitech-hidpp.c | 147 ++++++++++++++++++++++++++++++++-------
> >  1 file changed, 123 insertions(+), 24 deletions(-)
> > ---
> > base-commit: 022eb347ff3a48281e7e69c3addcb11bf24afa53
> > change-id: 20260921-feature-bolt-fix-5f1f642496df
> > 
> > Best regards,
> 
> Not sure if I'm testing this right, but with v7.3-rc4 and these two patches scrolling works OK as long as I keep "Scroll Wheel Resolution" in Solaar off. Unlike with unpatched kernel, scrolling doesn't go crazy if I switch between devices. But if I switch "Scroll Wheel Resolution" on, scrolling jumps crazy again.

Hopefully we've got all of the involved people here.

Honestly, this whole situation has been running for too long: Bolt can't
be handled as a DJ receiver, and all the quirks I'm seeing here are
making things even worse, with the "as long as I keep [some user
settings] off".

Bolt in kernel was adding in 7.3, so I'm going to revert it now, and
we'll have to have a fully working plan for an eventual inclusion in a
future kernel version.

Cheers,
Benjamin

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling
  2026-09-23  7:54   ` Benjamin Tissoires
@ 2026-09-23 16:09     ` erikhakan
  0 siblings, 0 replies; 6+ messages in thread
From: erikhakan @ 2026-09-23 16:09 UTC (permalink / raw)
  To: Benjamin Tissoires, Oleksandr Natalenko, Jiri Kosina,
	Filipe Laíns, Bastien Nocera, Rafael Passos,
	Grégoire Stein, Alexey Zagorodnikov, Roman Stingler,
	Lovekesh Solanki, Kateřina Medvědová,
	linux-input, linux-kernel

Hi!

> On Sep 23 2026, Oleksandr Natalenko wrote:
> > Hello.
> >
> > Not sure if I'm testing this right, but with v7.3-rc4 and these two patches scrolling works OK as long as I keep "Scroll Wheel Resolution" in Solaar off. Unlike with unpatched kernel, scrolling doesn't go crazy if I switch between devices. But if I switch "Scroll Wheel Resolution" on, scrolling jumps crazy again.

Okay, the expectation would be that scrolling would remain working
with "Scroll Wheel Resolution" (==high_resolution) either ON or OFF,
but when it's ON, it would also need "Scroll Wheel Diversion"
(==use_hidpp) to be ON (or ignored, but ignore may retain a previous
user setting, so a reconnect after setting that would be good.).

When you tested, do you remember what the setting for Scroll Wheel 
Diversion was? With it set to off, the scroll events will not go 
through the hid++ driver, so if high resolution is turned on, the 
events will be misinterpreted by the generic HID driver that expects
low resolution events.

> Hopefully we've got all of the involved people here.
> 
> Honestly, this whole situation has been running for too long: Bolt can't
> be handled as a DJ receiver, and all the quirks I'm seeing here are
> making things even worse, with the "as long as I keep [some user
> settings] off".
> 
> Bolt in kernel was adding in 7.3, so I'm going to revert it now, and
> we'll have to have a fully working plan for an eventual inclusion in a
> future kernel version.
> 
> Cheers,
> Benjamin

I totally agree that this is the right call, despite this being my first
kernel patch and I was a bit excited to see it roll out :) But of course
I don't want my first contribution to be problematic, so I agree with
reverting it.
For what it's worth, I checked with my G502 Lightspeed mouse, and it too
has incompatibilities between kernel and userspace, but in a rather
oppsite fashion: When "Scroll Wheel Diversion" (=use_hidpp) is turned
ON for it, scrolling stops working altogether, and looking at the code
I think that might actually be true for any device that supports HID++
function 0x2121, i.e. the more modern high resolution scroll.
So, having an incompatibility between the kernel driver and some Solaar
settings would not be new to the Bolt driver, it would just be a
different incompatibility.

But anyway, let's see if Oleksandr can confirm if the issue remains even
with use_hidpp ON. If not, then I think we're hopefully done with at
least the scroll scaling issue, especially if more people can test as
well. But of course there's still the other issue of not being able to
distinguish between devices.

Cheers!
Erik

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-23 16:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-22 17:40 [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Erik Håkansson
2026-09-22 17:40 ` [PATCH 1/2] HID: logitech-hidpp: fix hi-res scroll for Bolt-connected MX Master Erik Håkansson
2026-09-22 17:40 ` [PATCH 2/2] HID: logitech-hidpp: fix Bolt wheel mode handling Erik Håkansson
2026-09-23  6:39 ` [PATCH 0/2] HID: logitech-hidpp: fix Bolt hi-res wheel handling Oleksandr Natalenko
2026-09-23  7:54   ` Benjamin Tissoires
2026-09-23 16:09     ` erikhakan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®