Re: [REGRESSION 7.3-rc1] HID: logitech-hidpp: hi-res scroll mode forcibly re-enabled on every reconnect for Bolt devices, overriding userspace

From: Lovekesh Solanki

Date: Tue Sep 22 2026 - 11:42:02 EST


On Sun, Sep 20, 2026 at 10:50:53PM +0200, Roman Stingler wrote:
> diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
> index 1504de32b1c8..ffc7cef49b59 100644
> --- a/drivers/hid/hid-logitech-hidpp.c
> +++ b/drivers/hid/hid-logitech-hidpp.c
> @@ -2044,6 +2044,7 @@ static int hidpp_hrs_set_highres_scrolling_mode(struct hidpp_device *hidpp,
> #define HIDPP_PAGE_HIRES_WHEEL 0x2121
>
> #define CMD_HIRES_WHEEL_GET_WHEEL_CAPABILITY 0x00
> +#define CMD_HIRES_WHEEL_GET_WHEEL_MODE 0x10
> #define CMD_HIRES_WHEEL_SET_WHEEL_MODE 0x20
>
> static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp,
> @@ -2072,12 +2073,10 @@ static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp,
> return ret;
> }
>
> -static int hidpp_hrw_set_wheel_mode(struct hidpp_device *hidpp, bool invert,
> - bool high_resolution, bool use_hidpp)
> +static int hidpp_hrw_get_wheel_mode(struct hidpp_device *hidpp, u8 *mode)
> {
> u8 feature_index;
> int ret;
> - u8 params[1];
> struct hidpp_report response;
>
> ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
> @@ -2085,13 +2084,14 @@ 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);
> + ret = hidpp_send_fap_command_sync(hidpp, feature_index,
> + CMD_HIRES_WHEEL_GET_WHEEL_MODE,
> + NULL, 0, &response);
> + if (ret)
> + return ret;
>
> - return hidpp_send_fap_command_sync(hidpp, feature_index,
> - CMD_HIRES_WHEEL_SET_WHEEL_MODE,
> - params, sizeof(params), &response);
> + *mode = response.fap.params[0];
> + return 0;
> }
>
> /* -------------------------------------------------------------------------- */
> @@ -3910,8 +3910,16 @@ 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);
> - if (ret == 0)
> + u8 mode;
> +
> + /*
> + * The wheel mode is persistent state in the device, so read it
> + * rather than overwriting it, and scale to match. A device
> + * left in hi-res still gets the multiplier it needs; one the
> + * user configured for low resolution is left alone.
> + */
> + ret = hidpp_hrw_get_wheel_mode(hidpp, &mode);
> + if (ret == 0 && (mode & BIT(1)))
> ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier);
> } else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL) {
> ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true,
>
> Tested on top of 7.3-rc3, installed via DKMS so it is the module loaded at
> boot. Results against the same device:
>
> stock your patch this
> suspend/resume no yes yes
> solaar write sticks no yes yes
> module reload no no yes
> cold boot no no yes

I didn't think of this, your patch seems like a better solution.
I think you should format and send it.


Regards,
Lovekesh