diff options
| author | Jiri Kosina <jkosina@suse.com> | 2026-06-16 21:52:56 +0200 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.com> | 2026-06-16 21:52:56 +0200 |
| commit | 5a59f62cc05648e9264d6ec4e46036a6d8dea378 (patch) | |
| tree | 8053e357cc0f43cc45a6ecd1b447217e17657145 /drivers/hid | |
| parent | df1d6781b254e0940082d4e544e9815121850bea (diff) | |
| parent | f0866517be9345d8245d32b722574b8aecccb348 (diff) | |
| download | lwn-5a59f62cc05648e9264d6ec4e46036a6d8dea378.tar.gz lwn-5a59f62cc05648e9264d6ec4e46036a6d8dea378.zip | |
Merge branch 'for-7.2/logitech' into for-linus
- fix for high resolution scrolling for Logitech HID++ 2.0 devices (Lauri Saurus)
Diffstat (limited to 'drivers/hid')
| -rw-r--r-- | drivers/hid/hid-logitech-hidpp.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index d8e86b6ccf37..90b0184df777 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -164,7 +164,6 @@ struct hidpp_battery { /** * struct hidpp_scroll_counter - Utility class for processing high-resolution * scroll events. - * @dev: the input device for which events should be reported. * @wheel_multiplier: the scalar multiplier to be applied to each wheel event * @remainder: counts the number of high-resolution units moved since the last * low-resolution event (REL_WHEEL or REL_HWHEEL) was sent. Should @@ -207,6 +206,9 @@ struct hidpp_device { u8 wireless_feature_index; + int hires_wheel_multiplier; + u8 hires_wheel_feature_index; + bool connected_once; }; @@ -3710,6 +3712,7 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) multiplier = 1; } + hidpp->hires_wheel_multiplier = multiplier; hidpp->vertical_wheel_counter.wheel_multiplier = multiplier; hid_dbg(hidpp->hid_dev, "wheel multiplier = %d\n", multiplier); return 0; @@ -3720,6 +3723,7 @@ static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp) int ret; unsigned long capabilities; + hidpp->hires_wheel_feature_index = 0xff; capabilities = hidpp->capabilities; if (hidpp->protocol_major >= 2) { @@ -3729,6 +3733,7 @@ static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp) &feature_index); if (!ret) { hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL; + hidpp->hires_wheel_feature_index = feature_index; hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scroll wheel\n"); return 0; } @@ -3751,6 +3756,31 @@ static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp) return 0; } +static int hidpp20_hires_wheel_raw_event(struct hidpp_device *hidpp, + u8 *data, int size) +{ + if (hidpp->hires_wheel_feature_index == 0xff) + return 0; + + if (size < 5) + return 0; + + if (data[0] != REPORT_ID_HIDPP_LONG || + data[2] != hidpp->hires_wheel_feature_index) + return 0; + + 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) + ? hidpp->hires_wheel_multiplier : 1; + hidpp->vertical_wheel_counter.wheel_multiplier = new_multiplier; + return 1; + } + + return 0; +} + /* -------------------------------------------------------------------------- */ /* Generic HID++ devices */ /* -------------------------------------------------------------------------- */ @@ -3947,6 +3977,12 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, return ret; } + if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) { + ret = hidpp20_hires_wheel_raw_event(hidpp, data, size); + if (ret != 0) + return ret; + } + return 0; } |
