Message ID | 20230613152559.108594-1-ostapyshyn@sra.uni-hannover.de |
---|---|
State | Accepted |
Commit | 276e14e6c3993317257e1787e93b7166fbc30905 |
Headers | show |
Series | [RESEND] HID: input: Support devices sending Eraser without Invert | expand |
On Tue, 13 Jun 2023, Illia Ostapyshyn wrote: > 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> Applied, thanks. > --- > We were wondering about the reason to keep quirk bits reserved for > backward compatibility. Is it because of dynamic quirks at module load > time? Yes, that is indeed the case. Thanks,
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a1d2690a1a0d..c443f78287df 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -988,6 +988,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; @@ -1013,9 +1014,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; @@ -1579,6 +1584,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; diff --git a/include/linux/hid.h b/include/linux/hid.h index 4e4c4fe36911..7cbc10073a1f 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -360,6 +360,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)