tests_kernel.test_tablet module

class BaseTest

Bases: object

class TestTablet

Bases: TestUhid

create_device()
post(uhdev, pen, test_button)
test_tolerated_broken_pen_states(state_list, scribble)

Those tests are definitely not part of the Windows specification. However, a half broken device might export those transitions. For example, a pen that has the eraser button might wobble between touching and erasing if the tablet doesn’t enforce the Windows state machine.

test_tolerated_invert_pen_states(state_list, scribble)

This is the second half of the Windows Pen Implementation state machine: we now have Invert and Erase bits, so move in/out or proximity with the intend to erase. https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states

test_tolerated_pen_states(state_list, scribble)

This is not adhering to the Windows Pen Implementation state machine but we should expect the kernel to behave properly, mostly for historical reasons.

test_valid_invert_pen_states(state_list, scribble)

This is the second half of the Windows Pen Implementation state machine: we now have Invert and Erase bits, so move in/out or proximity with the intend to erase. https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states

test_valid_pen_states(state_list, scribble)

This is the first half of the Windows Pen Implementation state machine: we don’t have Invert nor Erase bits, so just move in/out-of-range or proximity. https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states

test_valid_primary_button_pen_states(state_list, scribble)

Rework the transition state machine by adding the primary button.

test_valid_secondary_button_pen_states(state_list, scribble)

Rework the transition state machine by adding the secondary button.

test_valid_third_button_pen_states(state_list, scribble)

Rework the transition state machine by adding the secondary button.

validate_transitions(from_state, pen, evdev, events, allow_intermediate_states, button)
class BtnPressed(*values)

Bases: Enum

Represents whether a button is pressed on the stylus

PRIMARY_PRESSED = BTN_STYLUS:331
SECONDARY_PRESSED = BTN_STYLUS2:332
THIRD_PRESSED = BTN_STYLUS3:329
class BtnTouch(*values)

Bases: Enum

Represents whether the BTN_TOUCH event is set to True or False

DOWN = True
UP = False
class GXTP_pen(name, rdesc_str=None, rdesc=None, application='Pen', physical='Stylus', input_info=(BusType.USB, 1, 2), evdev_name_suffix=None)

Bases: PenDigitizer

event(pen, test_button)
class Huion_Kamvas_Pro_19_256c_006b(name, rdesc_str=None, rdesc=None, application='Stylus', physical=None, input_info=(BusType.USB, 9580, 107), evdev_name_suffix=None)

Bases: PenDigitizer

Pen that reports secondary barrel switch through secondary TipSwtich and 3rd button through Invert

call_input_event(report)

Send an input event from this device.

Parameters:

data (list) – a list of 8-bit integers representing the HID report for this input event

event(pen, button)
move_to(pen, state, button, debug=True)
send_intermediate_state(pen, state, test_button)
class Pen(x, y)

Bases: object

assert_expected_input_events(evdev, button)
backup()
restore()
class PenDigitizer(name, rdesc_str=None, rdesc=None, application='Pen', physical='Stylus', input_info=(BusType.USB, 1, 2), evdev_name_suffix=None)

Bases: UHIDTestDevice

event(pen, button)
get_report(req, rnum, rtype)

Callback invoked when a process calls SetReport on this UHID device.

Return (0, [data bytes]) on success or (errno, []) on failure.

The default method always returns (EIO, []) for a failure. Override this in your device if you want GetReport to succeed.

Parameters:
  • req – the request identifier

  • rnum

    ???

  • rtype – one of UHID_FEATURE_REPORT, UHID_INPUT_REPORT, or UHID_OUTPUT_REPORT

move_to(pen, state, button)
set_report(req, rnum, rtype, data)

Callback invoked when a process calls SetReport on this UHID device.

Return 0 on success or an errno on failure.

The default method always returns EIO for a failure. Override this in your device if you want SetReport to succeed.

Parameters:
  • req – the request identifier

  • rnum

    ???

  • rtype – one of UHID_FEATURE_REPORT, UHID_INPUT_REPORT, or UHID_OUTPUT_REPORT

  • data (list) – a byte string with the data

class PenState(*values)

Bases: Enum

Pen states according to Microsoft reference: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states

We extend it with the various buttons when we need to check them.

PEN_IS_ERASING = (BtnTouch.DOWN, ToolType.RUBBER, False)
PEN_IS_ERASING_WITH_BUTTON = (BtnTouch.DOWN, ToolType.RUBBER, True)
PEN_IS_IN_CONTACT = (BtnTouch.DOWN, ToolType.PEN, False)
PEN_IS_IN_CONTACT_WITH_BUTTON = (BtnTouch.DOWN, ToolType.PEN, True)
PEN_IS_IN_RANGE = (BtnTouch.UP, ToolType.PEN, False)
PEN_IS_IN_RANGE_WITH_BUTTON = (BtnTouch.UP, ToolType.PEN, True)
PEN_IS_IN_RANGE_WITH_ERASING_INTENT = (BtnTouch.UP, ToolType.RUBBER, False)
PEN_IS_IN_RANGE_WITH_ERASING_INTENT_WITH_BUTTON = (BtnTouch.UP, ToolType.RUBBER, True)
PEN_IS_OUT_OF_RANGE = (BtnTouch.UP, None, False)
apply(events: list[InputEvent], strict: bool, test_button: BtnPressed) PenState
static broken_transitions() dict[str, Tuple[PenState, ...]]

Those tests are definitely not part of the Windows specification. However, a half broken device might export those transitions. For example, a pen that has the eraser button might wobble between touching and erasing if the tablet doesn’t enforce the Windows state machine.

classmethod from_evdev(evdev, test_button) PenState
historically_tolerated_transitions() Tuple[PenState, ...]

Following the state machine in the URL above, with a couple of addition for skipping the in-range state, due to historical reasons.

Note that those transitions are from the evdev point of view, not HID

static legal_transitions() dict[str, Tuple[PenState, ...]]

This is the first half of the Windows Pen Implementation state machine: we don’t have Invert nor Erase bits, so just move in/out-of-range or proximity. https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states

static legal_transitions_with_button() dict[str, Tuple[PenState, ...]]

We revisit the Windows Pen Implementation state machine: we now have a button.

static legal_transitions_with_invert() dict[str, Tuple[PenState, ...]]

This is the second half of the Windows Pen Implementation state machine: we now have Invert and Erase bits, so move in/out or proximity with the intend to erase. https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states

static tolerated_transitions() dict[str, Tuple[PenState, ...]]

This is not adhering to the Windows Pen Implementation state machine but we should expect the kernel to behave properly, mostly for historical reasons.

static tolerated_transitions_with_invert() dict[str, Tuple[PenState, ...]]

This is the second half of the Windows Pen Implementation state machine: we now have Invert and Erase bits, so move in/out or proximity with the intend to erase. https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states

valid_transitions() Tuple[PenState, ...]

Following the state machine in the URL above.

Note that those transitions are from the evdev point of view, not HID

class TestElan_04f3_2A49

Bases: TestTablet

create_device()
class TestGXTP_27c6_0113

Bases: TestTablet

create_device()
class TestGoodix_27c6_0e00

Bases: TestTablet

create_device()
class TestHuion_Kamvas_Pro_19_256c_006b

Bases: TestTablet

create_device()
hid_bpfs: list[HidBpf] = [HidBpf(object_name='Huion__Kamvas-Pro-19.bpf.o', has_rdesc_fixup=True)]
class TestNexio_1870_0100

Bases: TestTablet

create_device()
class TestNexio_1870_010d

Bases: TestTablet

create_device()
class TestNexio_1870_0119

Bases: TestTablet

create_device()
class TestXPPen_Artist24_28bd_093a

Bases: TestTablet

create_device()
hid_bpfs: list[HidBpf] = [HidBpf(object_name='XPPen__Artist24.bpf.o', has_rdesc_fixup=True)]
class TestXPPen_ArtistPro16Gen2_28bd_095b

Bases: TestTablet

create_device()
hid_bpfs: list[HidBpf] = [HidBpf(object_name='XPPen__ArtistPro16Gen2.bpf.o', has_rdesc_fixup=True)]
class Testatmel_03eb_840b

Bases: TestTablet

create_device()
class Testn_trig_1b96_0c01

Bases: TestTablet

create_device()
class Testn_trig_1b96_0c03

Bases: TestTablet

create_device()
class Testn_trig_1b96_0f00

Bases: TestTablet

create_device()
class Testn_trig_1b96_0f04

Bases: TestTablet

create_device()
class Testn_trig_1b96_1000

Bases: TestTablet

create_device()
class ToolType(*values)

Bases: Enum

PEN = BTN_TOOL_PEN:320
RUBBER = BTN_TOOL_RUBBER:321
class USIPen(name, rdesc_str=None, rdesc=None, application='Pen', physical='Stylus', input_info=(BusType.USB, 1, 2), evdev_name_suffix=None)

Bases: PenDigitizer

class XPPen_Artist24_28bd_093a(name, rdesc_str=None, rdesc=None, application='Pen', physical='Stylus', input_info=(BusType.USB, 10429, 2362), evdev_name_suffix=None)

Bases: PenDigitizer

Pen that reports secondary barrel switch through eraser

event(pen, button)
move_to(pen, state, button, debug=True)
send_intermediate_state(pen, state, button)
class XPPen_ArtistPro16Gen2_28bd_095b(name, rdesc_str=None, rdesc=None, application='Pen', physical='Stylus', input_info=(BusType.USB, 10429, 2395), evdev_name_suffix=None)

Bases: PenDigitizer

Pen with two buttons and a rubber end, but which reports the second button as an eraser

event(pen, test_button)
move_to(pen, state, button)