diff mbox series

[4/5] HID: wacom: Add preliminary support for high-resolution wheel scrolling

Message ID 20240730155159.3156-4-jason.gerecke@wacom.com
State New
Headers show
Series None | expand

Commit Message

Gerecke, Jason July 30, 2024, 3:51 p.m. UTC
From: Jason Gerecke <jason.gerecke@wacom.com>

Modern userspace (i.e. libinput) will make use of high-resolution
scrolling if supported. Hardware does not currently set a resolution
multiplier needed for effective high-res scrolling, but we can still
write code to support it in the future.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
---
 drivers/hid/wacom_wac.c | 24 ++++++++++++++++++++----
 drivers/hid/wacom_wac.h |  1 +
 2 files changed, 21 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 96b158a94ef9c..e45abc973363a 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2048,10 +2048,12 @@  static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 		features->device_type |= WACOM_DEVICETYPE_PAD;
 		break;
 	case WACOM_HID_WD_TOUCHRING:
-		if (field->flags & HID_MAIN_ITEM_RELATIVE)
-			wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL, 0);
-		else
+		if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+			wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL_HI_RES, 0);
+			set_bit(REL_WHEEL, input->relbit);
+		} else {
 			wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		}
 		features->device_type |= WACOM_DEVICETYPE_PAD;
 		break;
 	case WACOM_HID_WD_TOUCHRINGSTATUS:
@@ -2179,7 +2181,21 @@  static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
 			 * userspace treats positive REL_WHEEL as a
 			 * scroll *up*!
 			 */
-			value = -value;
+			int hires_value = -value * 120 / usage->resolution_multiplier;
+			int *ring_value = &wacom_wac->hid_data.ring_value;
+
+			value = hires_value;
+			*ring_value += hires_value;
+
+			/* Emulate a legacy wheel click for every 120
+			 * units of hi-res travel.
+			 */
+			if (*ring_value >= 120 || *ring_value <= -120) {
+				int clicks = *ring_value / 120;
+
+				input_event(input, usage->type, REL_WHEEL, clicks);
+				*ring_value -= clicks * 120;
+			}
 		}
 		else {
 			value = wacom_offset_rotation(input, usage, value, 1, 4);
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 6ec499841f709..aeba2f3082f03 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -312,6 +312,7 @@  struct hid_data {
 	int width;
 	int height;
 	int id;
+	int ring_value;
 	int cc_report;
 	int cc_index;
 	int cc_value_index;