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@xxxxxxxxxxxxxxx # 2.4+ Signed-off-by: Ping Cheng <ping.cheng@xxxxxxxxx> Reviewed-by: Jason Gerecke <killertofu@xxxxxxxxx> Tested-by: Tatsunosuke Tobita <junkpainting@xxxxxxxxx> --- 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