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

selftests/hid: tablets: convert the primary button tests

We get more descriptive in what we are doing, and also get more
information of what is actually being tested. Instead of having a non
exhaustive button changes that are semi-randomly done, we can describe
all the states we want to test.

Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Jiri Kosina <jkosina@suse.com>
Link: https://lore.kernel.org/r/20231206-wip-selftests-v2-11-c0350c2f5986@kernel.org
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

+65 -95
+65 -95
tools/testing/selftests/hid/tests/test_tablet.py
··· 318 318 } 319 319 320 320 @staticmethod 321 + def legal_transitions_with_primary_button() -> Dict[str, Tuple["PenState", ...]]: 322 + """We revisit the Windows Pen Implementation state machine: 323 + we now have a primary button. 324 + """ 325 + return { 326 + "hover-button": (PenState.PEN_IS_IN_RANGE_WITH_BUTTON,), 327 + "hover-button -> out-of-range": ( 328 + PenState.PEN_IS_IN_RANGE_WITH_BUTTON, 329 + PenState.PEN_IS_OUT_OF_RANGE, 330 + ), 331 + "in-range -> button-press": ( 332 + PenState.PEN_IS_IN_RANGE, 333 + PenState.PEN_IS_IN_RANGE_WITH_BUTTON, 334 + ), 335 + "in-range -> button-press -> button-release": ( 336 + PenState.PEN_IS_IN_RANGE, 337 + PenState.PEN_IS_IN_RANGE_WITH_BUTTON, 338 + PenState.PEN_IS_IN_RANGE, 339 + ), 340 + "in-range -> touch -> button-press -> button-release": ( 341 + PenState.PEN_IS_IN_RANGE, 342 + PenState.PEN_IS_IN_CONTACT, 343 + PenState.PEN_IS_IN_CONTACT_WITH_BUTTON, 344 + PenState.PEN_IS_IN_CONTACT, 345 + ), 346 + "in-range -> touch -> button-press -> release -> button-release": ( 347 + PenState.PEN_IS_IN_RANGE, 348 + PenState.PEN_IS_IN_CONTACT, 349 + PenState.PEN_IS_IN_CONTACT_WITH_BUTTON, 350 + PenState.PEN_IS_IN_RANGE_WITH_BUTTON, 351 + PenState.PEN_IS_IN_RANGE, 352 + ), 353 + "in-range -> button-press -> touch -> release -> button-release": ( 354 + PenState.PEN_IS_IN_RANGE, 355 + PenState.PEN_IS_IN_RANGE_WITH_BUTTON, 356 + PenState.PEN_IS_IN_CONTACT_WITH_BUTTON, 357 + PenState.PEN_IS_IN_RANGE_WITH_BUTTON, 358 + PenState.PEN_IS_IN_RANGE, 359 + ), 360 + "in-range -> button-press -> touch -> button-release -> release": ( 361 + PenState.PEN_IS_IN_RANGE, 362 + PenState.PEN_IS_IN_RANGE_WITH_BUTTON, 363 + PenState.PEN_IS_IN_CONTACT_WITH_BUTTON, 364 + PenState.PEN_IS_IN_CONTACT, 365 + PenState.PEN_IS_IN_RANGE, 366 + ), 367 + } 368 + 369 + @staticmethod 321 370 def tolerated_transitions() -> Dict[str, Tuple["PenState", ...]]: 322 371 """This is not adhering to the Windows Pen Implementation state machine 323 372 but we should expect the kernel to behave properly, mostly for historical ··· 721 672 self._test_states(state_list, scribble) 722 673 723 674 @pytest.mark.skip_if_uhdev( 675 + lambda uhdev: "Barrel Switch" not in uhdev.fields, 676 + "Device not compatible, missing Barrel Switch usage", 677 + ) 678 + @pytest.mark.parametrize("scribble", [True, False], ids=["scribble", "static"]) 679 + @pytest.mark.parametrize( 680 + "state_list", 681 + [ 682 + pytest.param(v, id=k) 683 + for k, v in PenState.legal_transitions_with_primary_button().items() 684 + ], 685 + ) 686 + def test_valid_primary_button_pen_states(self, state_list, scribble): 687 + """Rework the transition state machine by adding the primary button.""" 688 + self._test_states(state_list, scribble) 689 + 690 + @pytest.mark.skip_if_uhdev( 724 691 lambda uhdev: "Invert" not in uhdev.fields, 725 692 "Device not compatible, missing Invert usage", 726 693 ) ··· 792 727 touching and erasing if the tablet doesn't enforce the Windows 793 728 state machine.""" 794 729 self._test_states(state_list, scribble) 795 - 796 - @pytest.mark.skip_if_uhdev( 797 - lambda uhdev: "Barrel Switch" not in uhdev.fields, 798 - "Device not compatible, missing Barrel Switch usage", 799 - ) 800 - def test_primary_button(self): 801 - """Primary button (stylus) pressed, reports as pressed even while hovering. 802 - Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN): 803 - { 0, 0, 1 } <- hover 804 - { 0, 1, 1 } <- primary button pressed 805 - { 0, 1, 1 } <- liftoff 806 - { 0, 0, 0 } <- leaves 807 - """ 808 - 809 - uhdev = self.uhdev 810 - evdev = uhdev.get_evdev() 811 - 812 - p = Pen(50, 60) 813 - p.inrange = True 814 - events = self.post(uhdev, p) 815 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events 816 - assert evdev.value[libevdev.EV_ABS.ABS_X] == 50 817 - assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60 818 - assert not evdev.value[libevdev.EV_KEY.BTN_STYLUS] 819 - 820 - p.barrelswitch = True 821 - events = self.post(uhdev, p) 822 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 1) in events 823 - 824 - p.x += 1 825 - p.y -= 1 826 - events = self.post(uhdev, p) 827 - assert len(events) == 3 # X, Y, SYN 828 - assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 51) in events 829 - assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 59) in events 830 - 831 - p.barrelswitch = False 832 - events = self.post(uhdev, p) 833 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 0) in events 834 - 835 - p.inrange = False 836 - events = self.post(uhdev, p) 837 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 0) in events 838 - 839 - @pytest.mark.skip_if_uhdev( 840 - lambda uhdev: "Barrel Switch" not in uhdev.fields, 841 - "Device not compatible, missing Barrel Switch usage", 842 - ) 843 - def test_contact_primary_button(self): 844 - """Primary button (stylus) pressed, reports as pressed even while hovering. 845 - Actual reporting from the device: hid=TIPSWITCH,BARRELSWITCH,INRANGE (code=TOUCH,STYLUS,PEN): 846 - { 0, 0, 1 } <- hover 847 - { 0, 1, 1 } <- primary button pressed 848 - { 1, 1, 1 } <- touch-down 849 - { 1, 1, 1 } <- still touch, scribble on the screen 850 - { 0, 1, 1 } <- liftoff 851 - { 0, 0, 0 } <- leaves 852 - """ 853 - 854 - uhdev = self.uhdev 855 - evdev = uhdev.get_evdev() 856 - 857 - p = Pen(50, 60) 858 - p.inrange = True 859 - events = self.post(uhdev, p) 860 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 1) in events 861 - assert evdev.value[libevdev.EV_ABS.ABS_X] == 50 862 - assert evdev.value[libevdev.EV_ABS.ABS_Y] == 60 863 - assert not evdev.value[libevdev.EV_KEY.BTN_STYLUS] 864 - 865 - p.barrelswitch = True 866 - events = self.post(uhdev, p) 867 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 1) in events 868 - 869 - p.tipswitch = True 870 - events = self.post(uhdev, p) 871 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events 872 - assert evdev.value[libevdev.EV_KEY.BTN_STYLUS] 873 - 874 - p.x += 1 875 - p.y -= 1 876 - events = self.post(uhdev, p) 877 - assert len(events) == 3 # X, Y, SYN 878 - assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X, 51) in events 879 - assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y, 59) in events 880 - 881 - p.tipswitch = False 882 - events = self.post(uhdev, p) 883 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events 884 - 885 - p.barrelswitch = False 886 - p.inrange = False 887 - events = self.post(uhdev, p) 888 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN, 0) in events 889 - assert libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS, 0) in events 890 730 891 731 892 732 class GXTP_pen(PenDigitizer):