tests/tablet: add GXTP reporting quirk tests
In Re: my 4/4 from March, now that !115 (merged) landed
Fails on clean mainline (well, 5.15.0-2 off Debian, applies cleanly to both):
$ sudo pytest-3 -k tablet
============================= test session starts ==============================
platform linux -- Python 3.9.9, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
rootdir: /home/nabijaczleweli/data/2021-02-10-linux-hid-stylus-on-touchscreen-device/hid-tools
collected 2430 items / 2397 deselected / 33 selected
tests/test_tablet.py ..............................FFF [100%]
=================================== FAILURES ===================================
________________ TestGXTP_27c6_0113.test_contact_idiosyncratic _________________
self = <tests.test_tablet.TestGXTP_27c6_0113 object at 0x7f3a35243fd0>
def test_contact_idiosyncratic(self):
"""Pen touches, but loses inrange in the process
Actual reporting from the device: hid=TIPSWITCH,INRANGE (code=TOUCH,TOOL_PEN):
{ 0, 1 } <- hover
{ 1, 1 } <- touch-down
{ 1, 0 } <- still touch, if you scribble on the screen you're in this state
{ 0, 1 } <- liftoff
{ 0, 0 } <- leaves
"""
uhdev = self.uhdev
evdev = uhdev.get_evdev()
p = Pen(50, 60)
events = self.post(uhdev, p)
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events
assert evdev.value[libevdev.EV_ABS.ABS_X] == 50
assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60
p.tipswitch = True
events = self.post(uhdev, p)
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
p.inrange = False
events = self.post(uhdev, p)
> assert not events
E assert not [InputEvent(EV_KEY, BTN_TOOL_PEN, 0), InputEvent(EV_SYN, SYN_REPORT, 0)]
tests/test_tablet.py:351: AssertionError
----------------------------- Captured stdout call -----------------------------
sending 1 report:
08 20 00 32 00 3c 00 0f 00 00 00 00 00
====> ReportID: 8 / Tip Switch: 0 | Barrel Switch: 0 | Invert: 0 | Eraser: 0 | # | In Range: 1 | # | Contact Id: 0 | X: 50 | Y: 60 | Tip Pressure: 15 | X Tilt: 0 | Y Tilt: 0
events received: [InputEvent(EV_KEY, BTN_TOOL_PEN, 1), InputEvent(EV_ABS, ABS_X, 50), InputEvent(EV_ABS, ABS_Y, 60), InputEvent(EV_ABS, ABS_PRESSURE, 15), InputEvent(EV_SYN, SYN_REPORT, 0)]
sending 1 report:
08 21 00 32 00 3c 00 0f 00 00 00 00 00
====> ReportID: 8 / Tip Switch: 1 | Barrel Switch: 0 | Invert: 0 | Eraser: 0 | # | In Range: 1 | # | Contact Id: 0 | X: 50 | Y: 60 | Tip Pressure: 15 | X Tilt: 0 | Y Tilt: 0
events received: [InputEvent(EV_MSC, MSC_SCAN, 852034), InputEvent(EV_KEY, BTN_TOUCH, 1), InputEvent(EV_SYN, SYN_REPORT, 0)]
sending 1 report:
08 01 00 32 00 3c 00 0f 00 00 00 00 00
====> ReportID: 8 / Tip Switch: 1 | Barrel Switch: 0 | Invert: 0 | Eraser: 0 | # | In Range: 0 | # | Contact Id: 0 | X: 50 | Y: 60 | Tip Pressure: 15 | X Tilt: 0 | Y Tilt: 0
events received: [InputEvent(EV_KEY, BTN_TOOL_PEN, 0), InputEvent(EV_SYN, SYN_REPORT, 0)]
____________ TestGXTP_27c6_0113.test_contact_idiosyncratic_primary _____________
self = <tests.test_tablet.TestGXTP_27c6_0113 object at 0x7f3a34b98df0>
def test_contact_idiosyncratic_primary(self):
"""Primary button (stylus) pressed, reports as pressed even while hovering; it needs to be ANDed with the tip switch.
Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN):
{ 0, 0, 1 } <- hover
{ 0, 1, 1 } <- primary button pressed
{ 1, 1, 1 } <- touch-down
{ 1, 1, 0 } <- still touch, if you scribble on the screen you're in this state
{ 0, 1, 1 } <- liftoff
{ 0, 0, 0 } <- leaves
"""
uhdev = self.uhdev
evdev = uhdev.get_evdev()
p = Pen(50, 60)
events = self.post(uhdev, p)
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events
assert evdev.value[libevdev.EV_ABS.ABS_X] == 50
assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60
assert not evdev.value[libevdev.EV_KEY.BTN_STYLUS]
p.barrelswitch = True
events = self.post(uhdev, p)
> assert not events
E assert not [InputEvent(EV_MSC, MSC_SCAN, 852036), InputEvent(EV_KEY, BTN_STYLUS, 1), InputEvent(EV_SYN, SYN_REPORT, 0)]
tests/test_tablet.py:392: AssertionError
---------------------------- Captured stdout setup -----------------------------
abort /dev/input/event25 [('ACTION', 'add'), ('DEVNAME', '/dev/input/event25'), ('DEVPATH', '/devices/virtual/misc/uhid/0003:0001:0002.0024/input/input2531/event25'), ('ID_INPUT', '1'), ('LIBINPUT_IGNORE_DEVICE', '1'), ('MAJOR', '13'), ('MINOR', '89'), ('SEQNUM', '22299'), ('SUBSYSTEM', 'input'), ('USEC_INITIALIZED', '15101887877')]
----------------------------- Captured stdout call -----------------------------
sending 1 report:
08 20 00 32 00 3c 00 0f 00 00 00 00 00
====> ReportID: 8 / Tip Switch: 0 | Barrel Switch: 0 | Invert: 0 | Eraser: 0 | # | In Range: 1 | # | Contact Id: 0 | X: 50 | Y: 60 | Tip Pressure: 15 | X Tilt: 0 | Y Tilt: 0
events received: [InputEvent(EV_KEY, BTN_TOOL_PEN, 1), InputEvent(EV_ABS, ABS_X, 50), InputEvent(EV_ABS, ABS_Y, 60), InputEvent(EV_ABS, ABS_PRESSURE, 15), InputEvent(EV_SYN, SYN_REPORT, 0)]
sending 1 report:
08 22 00 32 00 3c 00 0f 00 00 00 00 00
====> ReportID: 8 / Tip Switch: 0 | Barrel Switch: 1 | Invert: 0 | Eraser: 0 | # | In Range: 1 | # | Contact Id: 0 | X: 50 | Y: 60 | Tip Pressure: 15 | X Tilt: 0 | Y Tilt: 0
events received: [InputEvent(EV_MSC, MSC_SCAN, 852036), InputEvent(EV_KEY, BTN_STYLUS, 1), InputEvent(EV_SYN, SYN_REPORT, 0)]
_____________ TestGXTP_27c6_0113.test_contact_idiosyncratic_eraser _____________
self = <tests.test_tablet.TestGXTP_27c6_0113 object at 0x7f3a34b95be0>
def test_contact_idiosyncratic_eraser(self):
"""Like normal touch, but the secondary button (RUBBER) is held, and provided for the entire time.
In the reporting, RUBBER implies PEN; however, RUBBER must exclude PEN,
otherwise the tool in-proximity is RUBBER but PEN when touching.
Actual reporting from the device: hid=INVERT,ERASER,INRANGE (code=RUBBER,TOUCH,PEN):
{ 1, 0, 1 } <- hover
{ 0, 1, 1 } <- touchdown, scribble
{ 1, 0, 1 } <- liftoff
{ 0, 0, 0 } <- leaves
"""
uhdev = self.uhdev
evdev = uhdev.get_evdev()
p = Pen(50, 60)
p.invert = True
events = self.post(uhdev, p)
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_RUBBER, 1) in events
assert evdev.value[libevdev.EV_ABS.ABS_X] == 50
assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60
assert not evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN]
p.invert, p.eraser = p.eraser, p.invert
events = self.post(uhdev, p)
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
assert evdev.value[libevdev.EV_KEY.BTN_TOOL_RUBBER]
> assert not evdev.value[libevdev.EV_KEY.BTN_TOOL_PEN]
E assert not 1
tests/test_tablet.py:449: AssertionError
---------------------------- Captured stdout setup -----------------------------
abort /dev/input/event25 [('ACTION', 'add'), ('DEVNAME', '/dev/input/event25'), ('DEVPATH', '/devices/virtual/misc/uhid/0003:0001:0002.0025/input/input2535/event25'), ('ID_INPUT', '1'), ('LIBINPUT_IGNORE_DEVICE', '1'), ('MAJOR', '13'), ('MINOR', '89'), ('SEQNUM', '22325'), ('SUBSYSTEM', 'input'), ('USEC_INITIALIZED', '15102459667')]
----------------------------- Captured stdout call -----------------------------
sending 1 report:
08 24 00 32 00 3c 00 0f 00 00 00 00 00
====> ReportID: 8 / Tip Switch: 0 | Barrel Switch: 0 | Invert: 1 | Eraser: 0 | # | In Range: 1 | # | Contact Id: 0 | X: 50 | Y: 60 | Tip Pressure: 15 | X Tilt: 0 | Y Tilt: 0
events received: [InputEvent(EV_KEY, BTN_TOOL_RUBBER, 1), InputEvent(EV_ABS, ABS_X, 50), InputEvent(EV_ABS, ABS_Y, 60), InputEvent(EV_ABS, ABS_PRESSURE, 15), InputEvent(EV_SYN, SYN_REPORT, 0)]
sending 1 report:
08 28 00 32 00 3c 00 0f 00 00 00 00 00
====> ReportID: 8 / Tip Switch: 0 | Barrel Switch: 0 | Invert: 0 | Eraser: 1 | # | In Range: 1 | # | Contact Id: 0 | X: 50 | Y: 60 | Tip Pressure: 15 | X Tilt: 0 | Y Tilt: 0
events received: [InputEvent(EV_MSC, MSC_SCAN, 852037), InputEvent(EV_KEY, BTN_TOUCH, 1), InputEvent(EV_KEY, BTN_TOOL_PEN, 1), InputEvent(EV_SYN, SYN_REPORT, 0)]
=========================== short test summary info ============================
FAILED tests/test_tablet.py::TestGXTP_27c6_0113::test_contact_idiosyncratic
FAILED tests/test_tablet.py::TestGXTP_27c6_0113::test_contact_idiosyncratic_primary
FAILED tests/test_tablet.py::TestGXTP_27c6_0113::test_contact_idiosyncratic_eraser
================ 3 failed, 30 passed, 2397 deselected in 19.06s ================
Passes with 4/4:
$ sudo pytest-3 -k tablet
============================= test session starts ==============================
platform linux -- Python 3.9.9, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
rootdir: /home/nabijaczleweli/data/2021-02-10-linux-hid-stylus-on-touchscreen-device/hid-tools
collected 2430 items / 2397 deselected / 33 selected
tests/test_tablet.py ................................. [100%]
===================== 33 passed, 2397 deselected in 19.02s =====================
The full and preprocessed recording dumps can be had from https://lfs.nabijaczleweli.xyz/0011-OneMix3-Win8-tablet-screen-recording
CC: @bentiss
Edited by наб