diff mbox series

HID: input: fix the incorrectly reported BTN_TOOL_RUBBER/PEN tools

Message ID 20211022232837.18988-1-ping.cheng@wacom.com (mailing list archive)
State New, archived
Delegated to: Jiri Kosina
Headers show
Series HID: input: fix the incorrectly reported BTN_TOOL_RUBBER/PEN tools | expand

Commit Message

Ping Cheng Oct. 22, 2021, 11:28 p.m. UTC
The HID_QUIRK_INVERT caused BTN_TOOL_RUBBER events were reported at the
same time as events for BTN_TOOL_PEN/PENCIL/etc, if HID_QUIRK_INVERT
was set by a stylus' sideswitch. The reality is that a pen can only be
a stylus (writing/drawing) or an eraser, but not both at the same time.
This patch makes that logic correct.

CC: stable@vger.kernel.org # 2.4+
Signed-off-by: Ping Cheng <ping.cheng@wacom.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
Tested-by: Tatsunosuke Tobita <junkpainting@gmail.com>
---
 drivers/hid/hid-input.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

Comments

Ping Cheng Oct. 27, 2021, 7:06 p.m. UTC | #1
Hi @Dmitry Torokhov and @Benjamin Tissoires,

Do you have any comments about this patch? The issue and the logic
behind the fix has been explained in the commit comment and in the
code. Jiri is probably waiting for an acknowledgment from one of
you...

Thank you,
Ping

On Fri, Oct 22, 2021 at 4:29 PM Ping Cheng <pinglinux@gmail.com> wrote:
>
> The HID_QUIRK_INVERT caused BTN_TOOL_RUBBER events were reported at the
> same time as events for BTN_TOOL_PEN/PENCIL/etc, if HID_QUIRK_INVERT
> was set by a stylus' sideswitch. The reality is that a pen can only be
> a stylus (writing/drawing) or an eraser, but not both at the same time.
> This patch makes that logic correct.
>
> CC: stable@vger.kernel.org # 2.4+
> Signed-off-by: Ping Cheng <ping.cheng@wacom.com>
> Reviewed-by: Jason Gerecke <killertofu@gmail.com>
> Tested-by: Tatsunosuke Tobita <junkpainting@gmail.com>
> ---
>  drivers/hid/hid-input.c | 24 ++++++++++++++++++++----
>  1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index 4b5ebeacd283..85741a2d828d 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -1344,12 +1344,28 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
>         }
>
>         if (usage->hid == HID_DG_INRANGE) {
> +               /* when HID_QUIRK_INVERT is set by a stylus sideswitch, HID_DG_INRANGE could be
> +                * for stylus or eraser. Make sure events are only posted to the current valid tool:
> +                * BTN_TOOL_RUBBER vs BTN_TOOL_PEN/BTN_TOOL_PENCIL/BTN_TOOL_BRUSH/etc since a pen
> +                * can not be used as a stylus (to draw/write) and an erasaer at the same time
> +                */
> +               static unsigned int last_code = 0;
> +               unsigned int code = (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code;
>                 if (value) {
> -                       input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
> -                       return;
> +                       if (code != last_code) {
> +                               /* send the last tool out before allow the new one in */
> +                               if (last_code)
> +                                       input_event(input, usage->type, last_code, 0);
> +                               input_event(input, usage->type, code, 1);
> +                       }
> +                       last_code = code;
> +               } else {
> +                       /* only send the last valid tool out */
> +                       if (last_code)
> +                               input_event(input, usage->type, last_code, 0);
> +                       /* reset tool for next cycle */
> +                       last_code = 0;
>                 }
> -               input_event(input, usage->type, usage->code, 0);
> -               input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
>                 return;
>         }
>
> --
> 2.25.1
>
Ping Cheng Oct. 30, 2021, 2:54 a.m. UTC | #2
Ok, I know why no one follow-up with my patch. Life wasn't as simple
as I wished for :).

The patch missed one important fact: repeated events don't go into
userland. They are filtered! We need to initiate another input_dev to
hold all the past events for the coming tool, whether it is PEN or
RUBBER. So, it is more like a simplified multi-pen case, right? What's
your suggestions? Do we claim two tools for this particular use case?

On Wed, Oct 27, 2021 at 12:06 PM Ping Cheng <pinglinux@gmail.com> wrote:
>
> Hi @Dmitry Torokhov and @Benjamin Tissoires,
>
> Do you have any comments about this patch? The issue and the logic
> behind the fix has been explained in the commit comment and in the
> code. Jiri is probably waiting for an acknowledgment from one of
> you...
>
> Thank you,
> Ping
>
> On Fri, Oct 22, 2021 at 4:29 PM Ping Cheng <pinglinux@gmail.com> wrote:
> >
> > The HID_QUIRK_INVERT caused BTN_TOOL_RUBBER events were reported at the
> > same time as events for BTN_TOOL_PEN/PENCIL/etc, if HID_QUIRK_INVERT
> > was set by a stylus' sideswitch. The reality is that a pen can only be
> > a stylus (writing/drawing) or an eraser, but not both at the same time.
> > This patch makes that logic correct.
> >
> > CC: stable@vger.kernel.org # 2.4+
> > Signed-off-by: Ping Cheng <ping.cheng@wacom.com>
> > Reviewed-by: Jason Gerecke <killertofu@gmail.com>
> > Tested-by: Tatsunosuke Tobita <junkpainting@gmail.com>
> > ---
> >  drivers/hid/hid-input.c | 24 ++++++++++++++++++++----
> >  1 file changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> > index 4b5ebeacd283..85741a2d828d 100644
> > --- a/drivers/hid/hid-input.c
> > +++ b/drivers/hid/hid-input.c
> > @@ -1344,12 +1344,28 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
> >         }
> >
> >         if (usage->hid == HID_DG_INRANGE) {
> > +               /* when HID_QUIRK_INVERT is set by a stylus sideswitch, HID_DG_INRANGE could be
> > +                * for stylus or eraser. Make sure events are only posted to the current valid tool:
> > +                * BTN_TOOL_RUBBER vs BTN_TOOL_PEN/BTN_TOOL_PENCIL/BTN_TOOL_BRUSH/etc since a pen
> > +                * can not be used as a stylus (to draw/write) and an erasaer at the same time
> > +                */
> > +               static unsigned int last_code = 0;
> > +               unsigned int code = (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code;
> >                 if (value) {
> > -                       input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
> > -                       return;
> > +                       if (code != last_code) {
> > +                               /* send the last tool out before allow the new one in */
> > +                               if (last_code)
> > +                                       input_event(input, usage->type, last_code, 0);
> > +                               input_event(input, usage->type, code, 1);
> > +                       }
> > +                       last_code = code;
> > +               } else {
> > +                       /* only send the last valid tool out */
> > +                       if (last_code)
> > +                               input_event(input, usage->type, last_code, 0);
> > +                       /* reset tool for next cycle */
> > +                       last_code = 0;
> >                 }
> > -               input_event(input, usage->type, usage->code, 0);
> > -               input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
> >                 return;
> >         }
> >
> > --
> > 2.25.1
> >
diff mbox series

Patch

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 4b5ebeacd283..85741a2d828d 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1344,12 +1344,28 @@  void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
 	}
 
 	if (usage->hid == HID_DG_INRANGE) {
+		/* when HID_QUIRK_INVERT is set by a stylus sideswitch, HID_DG_INRANGE could be
+		 * for stylus or eraser. Make sure events are only posted to the current valid tool:
+		 * BTN_TOOL_RUBBER vs BTN_TOOL_PEN/BTN_TOOL_PENCIL/BTN_TOOL_BRUSH/etc since a pen
+		 * can not be used as a stylus (to draw/write) and an erasaer at the same time
+		 */
+		static unsigned int last_code = 0;
+		unsigned int code = (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code;
 		if (value) {
-			input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
-			return;
+			if (code != last_code) {
+				/* send the last tool out before allow the new one in */
+				if (last_code)
+					input_event(input, usage->type, last_code, 0);
+				input_event(input, usage->type, code, 1);
+			}
+			last_code = code;
+		} else {
+			/* only send the last valid tool out */
+			if (last_code)
+				input_event(input, usage->type, last_code, 0);
+			/* reset tool for next cycle */
+			last_code = 0;
 		}
-		input_event(input, usage->type, usage->code, 0);
-		input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
 		return;
 	}