]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
HID: wacom: Support touchrings with relative motion
authorJason Gerecke <jason.gerecke@wacom.com>
Tue, 30 Jul 2024 15:51:57 +0000 (08:51 -0700)
committerJiri Kosina <jkosina@suse.com>
Fri, 2 Aug 2024 11:02:46 +0000 (13:02 +0200)
If a touchring is configured to send relative events (e.g. +1 or -1 every
time some bit of rotational distance is covered), we should similarly
send relative events up to userspace. Previous non-HID tablets used
REL_WHEEL to send this kind of information, so we opt to use this same
axis since userspace (xf86-input-wacom and libinput) already expects
this kind of behavior from the Wacom kernel driver.

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
drivers/hid/wacom_wac.c

index b753b2f111fb6e688d0ba670e2cea207416a14bd..798c26ddaeba7d8f255a75f9740360fb13425e43 100644 (file)
@@ -1909,6 +1909,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
                }
                input_abs_set_res(input, code, resolution);
                break;
+       case EV_REL:
        case EV_KEY:
        case EV_MSC:
        case EV_SW:
@@ -2045,7 +2046,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
                features->device_type |= WACOM_DEVICETYPE_PAD;
                break;
        case WACOM_HID_WD_TOUCHRING:
-               wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+               if (field->flags & HID_MAIN_ITEM_RELATIVE)
+                       wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL, 0);
+               else
+                       wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
                features->device_type |= WACOM_DEVICETYPE_PAD;
                break;
        case WACOM_HID_WD_TOUCHRINGSTATUS:
@@ -2110,7 +2114,10 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
                return;
 
        if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) {
-               if (usage->hid != WACOM_HID_WD_TOUCHRING)
+               bool is_abs_touchring = usage->hid == WACOM_HID_WD_TOUCHRING &&
+                                       !(field->flags & HID_MAIN_ITEM_RELATIVE);
+
+               if (!is_abs_touchring)
                        wacom_wac->hid_data.inrange_state |= value;
        }
 
@@ -2163,6 +2170,15 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
                                 hdev->product == 0x3AA)
                                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*!
+                        */
+                       value = -value;
+               }
                else {
                        value = wacom_offset_rotation(input, usage, value, 1, 4);
                }