]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
HID: input: Support devices sending Eraser without Invert
authorIllia Ostapyshyn <ostapyshyn@sra.uni-hannover.de>
Tue, 13 Jun 2023 15:26:00 +0000 (17:26 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Sep 2023 07:42:55 +0000 (09:42 +0200)
[ Upstream commit 276e14e6c3993317257e1787e93b7166fbc30905 ]

Some digitizers (notably XP-Pen Artist 24) do not report the Invert
usage when erasing.  This causes the device to be permanently stuck with
the BTN_TOOL_RUBBER tool after sending Eraser, as Invert is the only
usage that can release the tool.  In this state, Touch and Inrange are
no longer reported to userspace, rendering the pen unusable.

Prior to commit 87562fcd1342 ("HID: input: remove the need for
HID_QUIRK_INVERT"), BTN_TOOL_RUBBER was never set and Eraser events were
simply translated into BTN_TOUCH without causing an inconsistent state.

Introduce HID_QUIRK_NOINVERT for such digitizers and detect them during
hidinput_configure_usage().  This quirk causes the tool to be released
as soon as Eraser is reported as not set.  Set BTN_TOOL_RUBBER in
input->keybit when mapping Eraser.

Fixes: 87562fcd1342 ("HID: input: remove the need for HID_QUIRK_INVERT")
Co-developed-by: Nils Fuhler <nils@nilsfuhler.de>
Signed-off-by: Nils Fuhler <nils@nilsfuhler.de>
Signed-off-by: Illia Ostapyshyn <ostapyshyn@sra.uni-hannover.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/hid/hid-input.c
include/linux/hid.h

index 3acaaca888acda986bcd242e1030825a977761da..77ee5e01e6111b77a09771edc58ca3d0dc59e310 100644 (file)
@@ -961,6 +961,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        return;
 
                case 0x3c: /* Invert */
+                       device->quirks &= ~HID_QUIRK_NOINVERT;
                        map_key_clear(BTN_TOOL_RUBBER);
                        break;
 
@@ -986,9 +987,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x45: /* ERASER */
                        /*
                         * This event is reported when eraser tip touches the surface.
-                        * Actual eraser (BTN_TOOL_RUBBER) is set by Invert usage when
-                        * tool gets in proximity.
+                        * Actual eraser (BTN_TOOL_RUBBER) is set and released either
+                        * by Invert if tool reports proximity or by Eraser directly.
                         */
+                       if (!test_bit(BTN_TOOL_RUBBER, input->keybit)) {
+                               device->quirks |= HID_QUIRK_NOINVERT;
+                               set_bit(BTN_TOOL_RUBBER, input->keybit);
+                       }
                        map_key_clear(BTN_TOUCH);
                        break;
 
@@ -1532,6 +1537,15 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
                else if (report->tool != BTN_TOOL_RUBBER)
                        /* value is off, tool is not rubber, ignore */
                        return;
+               else if (*quirks & HID_QUIRK_NOINVERT &&
+                        !test_bit(BTN_TOUCH, input->key)) {
+                       /*
+                        * There is no invert to release the tool, let hid_input
+                        * send BTN_TOUCH with scancode and release the tool after.
+                        */
+                       hid_report_release_tool(report, input, BTN_TOOL_RUBBER);
+                       return;
+               }
 
                /* let hid-input set BTN_TOUCH */
                break;
index 0a1ccc68e798a88db91bf076626aa31a3a07c9c3..784dd6b6046ebeb3cfc015d1016a325eaf3ca087 100644 (file)
@@ -357,6 +357,7 @@ struct hid_item {
 #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18)
 #define HID_QUIRK_HAVE_SPECIAL_DRIVER          BIT(19)
 #define HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE BIT(20)
+#define HID_QUIRK_NOINVERT                     BIT(21)
 #define HID_QUIRK_FULLSPEED_INTERVAL           BIT(28)
 #define HID_QUIRK_NO_INIT_REPORTS              BIT(29)
 #define HID_QUIRK_NO_IGNORE                    BIT(30)