diff mbox series

[5/5] HID: wacom: Support devices with two touchrings

Message ID 20240730155159.3156-5-jason.gerecke@wacom.com (mailing list archive)
State New
Delegated to: Jiri Kosina
Headers show
Series [1/5] HID: wacom: Defer calculation of resolution until resolution_code is known | expand

Commit Message

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

If a device has more than one touchring, we want to be sure that userspace
is able to distinguish them. Following previous standards, the first
absolute ring will be reported as ABS_WHEEL and the second as ABS_THROTTLE.
Relative rings will use REL_WHEEL_HI_RES / REL_WHEEL for the first and
REL_HWHEEL_HI_RES / REL_HWHEEL for the second.

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

Patch

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index e45abc973363a..74258a78d0408 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2049,10 +2049,21 @@  static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
 		break;
 	case WACOM_HID_WD_TOUCHRING:
 		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);
+			wacom_wac->relring_count++;
+			if (wacom_wac->relring_count == 1) {
+				wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL_HI_RES, 0);
+				set_bit(REL_WHEEL, input->relbit);
+			}
+			else if (wacom_wac->relring_count == 2) {
+				wacom_map_usage(input, usage, field, EV_REL, REL_HWHEEL_HI_RES, 0);
+				set_bit(REL_HWHEEL, input->relbit);
+			}
 		} else {
-			wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+			wacom_wac->absring_count++;
+			if (wacom_wac->absring_count == 1)
+				wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+			else if (wacom_wac->absring_count == 2)
+				wacom_map_usage(input, usage, field, EV_ABS, ABS_THROTTLE, 0);
 		}
 		features->device_type |= WACOM_DEVICETYPE_PAD;
 		break;
@@ -2175,14 +2186,37 @@  static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
 				value = wacom_offset_rotation(input, usage, value, 1, 2);
 		}
 		else if (field->flags & HID_MAIN_ITEM_RELATIVE) {
-			/* We must invert the sign for vertical
-			 * relative scrolling. Clockwise rotation
-			 * produces positive values from HW, but
-			 * userspace treats positive REL_WHEEL as a
-			 * scroll *up*!
-			 */
-			int hires_value = -value * 120 / usage->resolution_multiplier;
-			int *ring_value = &wacom_wac->hid_data.ring_value;
+			int hires_value = value * 120 / usage->resolution_multiplier;
+			int *ring_value;
+			int lowres_code;
+
+			if (usage->code == REL_WHEEL_HI_RES) {
+				/* We must invert the sign for vertical
+				 * relative scrolling. Clockwise
+				 * rotation produces positive values
+				 * from HW, but userspace treats
+				 * positive REL_WHEEL as a scroll *up*!
+				 */
+				hires_value = -hires_value;
+				ring_value = &wacom_wac->hid_data.ring_value;
+				lowres_code = REL_WHEEL;
+			}
+			else if (usage->code == REL_HWHEEL_HI_RES) {
+				/* No need to invert the sign for
+				 * horizontal relative scrolling.
+				 * Clockwise rotation produces positive
+				 * values from HW and userspace treats
+				 * positive REL_HWHEEL as a scroll
+				 * right.
+				 */
+				ring_value = &wacom_wac->hid_data.ring2_value;
+				lowres_code = REL_HWHEEL;
+			}
+			else {
+				hid_err(wacom->hdev, "unrecognized relative wheel with code %d\n",
+					usage->code);
+				break;
+			}
 
 			value = hires_value;
 			*ring_value += hires_value;
@@ -2193,7 +2227,7 @@  static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
 			if (*ring_value >= 120 || *ring_value <= -120) {
 				int clicks = *ring_value / 120;
 
-				input_event(input, usage->type, REL_WHEEL, clicks);
+				input_event(input, usage->type, lowres_code, clicks);
 				*ring_value -= clicks * 120;
 			}
 		}
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index aeba2f3082f03..55e0c7a9fdcb4 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -313,6 +313,7 @@  struct hid_data {
 	int height;
 	int id;
 	int ring_value;
+	int ring2_value;
 	int cc_report;
 	int cc_index;
 	int cc_value_index;
@@ -356,6 +357,8 @@  struct wacom_wac {
 	int num_contacts_left;
 	u8 bt_features;
 	u8 bt_high_speed;
+	u8 absring_count;
+	u8 relring_count;
 	int mode_report;
 	int mode_value;
 	struct hid_data hid_data;