Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: bpf: add heuristics to the Huion Inspiroy 2S eraser button

When pressing the phsyical eraser button (remapped by us to the
Secondary Barrel Switch) while the tip is down, the device
gives us several false reports with a Tip Switch 0:

press| |release
SBS: [0 0 ... 1 1 1 ... 1 0 0 0 0 0 0 ...]
TS: [1 1 ... 1 0 1 ... 1 1 0 0 0 1 1 ...]

In both press/release the number of Tip Switch 0 reports can be up to 4
and *sometimes* the Tip Switch is released in the same report
as the button press/release event.

Paper over this by forcing the tip down for a few reports if it was down
before the button toggled.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/195
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Benjamin Tissoires and committed by
Jiri Kosina
5e3e8f1b 88b5468f

+27 -2
+27 -2
drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
··· 163 163 164 164 165 165 __u8 last_button_state; 166 + __u8 last_tip_state; 167 + __u8 last_sec_barrel_state; 168 + __u8 force_tip_down_count; 166 169 167 170 static const __u8 fixed_rdesc_pad[] = { 168 171 UsagePage_GenericDesktop ··· 525 522 pad_report->wheel = wheel; 526 523 527 524 return sizeof(struct pad_report); 528 - } 525 + } else if (data[1] & 0x80) { /* Pen reports with InRange 1 */ 526 + __u8 tip_state = data[1] & 0x1; 527 + __u8 sec_barrel_state = data[1] & 0x4; 529 528 530 - /* Pen reports need nothing done */ 529 + if (force_tip_down_count > 0) { 530 + data[1] |= 0x1; 531 + --force_tip_down_count; 532 + if (tip_state) 533 + force_tip_down_count = 0; 534 + } 535 + 536 + /* Tip was down and we just pressed or released the 537 + * secondary barrel switch (the physical eraser 538 + * button). The device will send up to 4 539 + * reports with Tip Switch 0 and sometimes 540 + * this report has Tip Switch 0. 541 + */ 542 + if (last_tip_state && 543 + last_sec_barrel_state != sec_barrel_state) { 544 + force_tip_down_count = 4; 545 + data[1] |= 0x1; 546 + } 547 + last_tip_state = tip_state; 548 + last_sec_barrel_state = sec_barrel_state; 549 + } 531 550 } 532 551 533 552 return 0;