summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.com>2026-06-16 21:52:56 +0200
committerJiri Kosina <jkosina@suse.com>2026-06-16 21:52:56 +0200
commit5a59f62cc05648e9264d6ec4e46036a6d8dea378 (patch)
tree8053e357cc0f43cc45a6ecd1b447217e17657145 /drivers/hid
parentdf1d6781b254e0940082d4e544e9815121850bea (diff)
parentf0866517be9345d8245d32b722574b8aecccb348 (diff)
downloadlwn-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.c38
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;
}