mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
selftests/hid: sync the python tests to hid-tools 0.8
Instead of backporting one by one each commits, let's pull them in bulk and refer to the hid-tools project for a detailed history. The short summary is: - make use of dataclass when possible, to avoid tuples - wacom: remove unused uhdev parameter - various small fixes not worth mentioning Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Link: https://patch.msgid.link/20250709-wip-fix-ci-v1-2-b7df4c271cf8@kernel.org Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
This commit is contained in:
parent
c85a8cb9b8
commit
642f9b2d60
|
|
@ -5,6 +5,7 @@
|
|||
# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
|
||||
# Copyright (c) 2017 Red Hat, Inc.
|
||||
|
||||
import dataclasses
|
||||
import libevdev
|
||||
import os
|
||||
import pytest
|
||||
|
|
@ -145,6 +146,18 @@ class UHIDTestDevice(BaseDevice):
|
|||
self.name = name
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class HidBpf:
|
||||
object_name: str
|
||||
has_rdesc_fixup: bool
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class KernelModule:
|
||||
driver_name: str
|
||||
module_name: str
|
||||
|
||||
|
||||
class BaseTestCase:
|
||||
class TestUhid(object):
|
||||
syn_event = libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT) # type: ignore
|
||||
|
|
@ -155,20 +168,20 @@ class BaseTestCase:
|
|||
|
||||
# List of kernel modules to load before starting the test
|
||||
# if any module is not available (not compiled), the test will skip.
|
||||
# Each element is a tuple '(kernel driver name, kernel module)',
|
||||
# for example ("playstation", "hid-playstation")
|
||||
kernel_modules: List[Tuple[str, str]] = []
|
||||
# Each element is a KernelModule object, for example
|
||||
# KernelModule("playstation", "hid-playstation")
|
||||
kernel_modules: List[KernelModule] = []
|
||||
|
||||
# List of in kernel HID-BPF object files to load
|
||||
# before starting the test
|
||||
# Any existing pre-loaded HID-BPF module will be removed
|
||||
# before the ones in this list will be manually loaded.
|
||||
# Each Element is a tuple '(hid_bpf_object, rdesc_fixup_present)',
|
||||
# for example '("xppen-ArtistPro16Gen2.bpf.o", True)'
|
||||
# If 'rdesc_fixup_present' is True, the test needs to wait
|
||||
# Each Element is a HidBpf object, for example
|
||||
# 'HidBpf("xppen-ArtistPro16Gen2.bpf.o", True)'
|
||||
# If 'has_rdesc_fixup' is True, the test needs to wait
|
||||
# for one unbind and rebind before it can be sure the kernel is
|
||||
# ready
|
||||
hid_bpfs: List[Tuple[str, bool]] = []
|
||||
hid_bpfs: List[HidBpf] = []
|
||||
|
||||
def assertInputEventsIn(self, expected_events, effective_events):
|
||||
effective_events = effective_events.copy()
|
||||
|
|
@ -232,25 +245,26 @@ class BaseTestCase:
|
|||
|
||||
@pytest.fixture()
|
||||
def load_kernel_module(self):
|
||||
for kernel_driver, kernel_module in self.kernel_modules:
|
||||
self._load_kernel_module(kernel_driver, kernel_module)
|
||||
for k in self.kernel_modules:
|
||||
self._load_kernel_module(k.driver_name, k.module_name)
|
||||
yield
|
||||
|
||||
def load_hid_bpfs(self):
|
||||
# this function will only work when run in the kernel tree
|
||||
script_dir = Path(os.path.dirname(os.path.realpath(__file__)))
|
||||
root_dir = (script_dir / "../../../../..").resolve()
|
||||
bpf_dir = root_dir / "drivers/hid/bpf/progs"
|
||||
|
||||
if not bpf_dir.exists():
|
||||
pytest.skip("looks like we are not in the kernel tree, skipping")
|
||||
|
||||
udev_hid_bpf = shutil.which("udev-hid-bpf")
|
||||
if not udev_hid_bpf:
|
||||
pytest.skip("udev-hid-bpf not found in $PATH, skipping")
|
||||
|
||||
wait = False
|
||||
for _, rdesc_fixup in self.hid_bpfs:
|
||||
if rdesc_fixup:
|
||||
wait = True
|
||||
wait = any(b.has_rdesc_fixup for b in self.hid_bpfs)
|
||||
|
||||
for hid_bpf, _ in self.hid_bpfs:
|
||||
for hid_bpf in self.hid_bpfs:
|
||||
# We need to start `udev-hid-bpf` in the background
|
||||
# and dispatch uhid events in case the kernel needs
|
||||
# to fetch features on the device
|
||||
|
|
@ -260,13 +274,13 @@ class BaseTestCase:
|
|||
"--verbose",
|
||||
"add",
|
||||
str(self.uhdev.sys_path),
|
||||
str(bpf_dir / hid_bpf),
|
||||
str(bpf_dir / hid_bpf.object_name),
|
||||
],
|
||||
)
|
||||
while process.poll() is None:
|
||||
self.uhdev.dispatch(1)
|
||||
|
||||
if process.poll() != 0:
|
||||
if process.returncode != 0:
|
||||
pytest.fail(
|
||||
f"Couldn't insert hid-bpf program '{hid_bpf}', marking the test as failed"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import dataclasses
|
||||
import fcntl
|
||||
import functools
|
||||
import libevdev
|
||||
|
|
@ -104,6 +105,12 @@ class PowerSupply(object):
|
|||
return self._type.str_value
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class HidReadiness:
|
||||
is_ready: bool = False
|
||||
count: int = 0
|
||||
|
||||
|
||||
class HIDIsReady(object):
|
||||
"""
|
||||
Companion class that binds to a kernel mechanism
|
||||
|
|
@ -115,18 +122,18 @@ class HIDIsReady(object):
|
|||
def __init__(self: "HIDIsReady", uhid: UHIDDevice) -> None:
|
||||
self.uhid = uhid
|
||||
|
||||
def is_ready(self: "HIDIsReady") -> bool:
|
||||
def is_ready(self: "HIDIsReady") -> HidReadiness:
|
||||
"""
|
||||
Overwrite in subclasses: should return True or False whether
|
||||
the attached uhid device is ready or not.
|
||||
"""
|
||||
return False
|
||||
return HidReadiness()
|
||||
|
||||
|
||||
class UdevHIDIsReady(HIDIsReady):
|
||||
_pyudev_context: ClassVar[Optional[pyudev.Context]] = None
|
||||
_pyudev_monitor: ClassVar[Optional[pyudev.Monitor]] = None
|
||||
_uhid_devices: ClassVar[Dict[int, Tuple[bool, int]]] = {}
|
||||
_uhid_devices: ClassVar[Dict[int, HidReadiness]] = {}
|
||||
|
||||
def __init__(self: "UdevHIDIsReady", uhid: UHIDDevice) -> None:
|
||||
super().__init__(uhid)
|
||||
|
|
@ -157,18 +164,19 @@ class UdevHIDIsReady(HIDIsReady):
|
|||
|
||||
id = int(event.sys_path.strip().split(".")[-1], 16)
|
||||
|
||||
device_ready, count = cls._uhid_devices.get(id, (False, 0))
|
||||
readiness = cls._uhid_devices.setdefault(id, HidReadiness())
|
||||
|
||||
ready = event.action == "bind"
|
||||
if not device_ready and ready:
|
||||
count += 1
|
||||
cls._uhid_devices[id] = (ready, count)
|
||||
if not readiness.is_ready and ready:
|
||||
readiness.count += 1
|
||||
|
||||
def is_ready(self: "UdevHIDIsReady") -> Tuple[bool, int]:
|
||||
readiness.is_ready = ready
|
||||
|
||||
def is_ready(self: "UdevHIDIsReady") -> HidReadiness:
|
||||
try:
|
||||
return self._uhid_devices[self.uhid.hid_id]
|
||||
except KeyError:
|
||||
return (False, 0)
|
||||
return HidReadiness()
|
||||
|
||||
|
||||
class EvdevMatch(object):
|
||||
|
|
@ -322,11 +330,11 @@ class BaseDevice(UHIDDevice):
|
|||
|
||||
@property
|
||||
def kernel_is_ready(self: "BaseDevice") -> bool:
|
||||
return self._kernel_is_ready.is_ready()[0] and self.started
|
||||
return self._kernel_is_ready.is_ready().is_ready and self.started
|
||||
|
||||
@property
|
||||
def kernel_ready_count(self: "BaseDevice") -> int:
|
||||
return self._kernel_is_ready.is_ready()[1]
|
||||
return self._kernel_is_ready.is_ready().count
|
||||
|
||||
@property
|
||||
def input_nodes(self: "BaseDevice") -> List[EvdevDevice]:
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@
|
|||
|
||||
from .test_keyboard import ArrayKeyboard, TestArrayKeyboard
|
||||
from hidtools.util import BusType
|
||||
from . import base
|
||||
|
||||
import libevdev
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger("hidtools.test.apple-keyboard")
|
||||
|
||||
KERNEL_MODULE = ("apple", "hid-apple")
|
||||
KERNEL_MODULE = base.KernelModule("apple", "hid-apple")
|
||||
|
||||
|
||||
class KbdData(object):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import pytest
|
|||
|
||||
from .base_gamepad import BaseGamepad, JoystickGamepad, AxisMapping
|
||||
from hidtools.util import BusType
|
||||
from .base import HidBpf
|
||||
|
||||
import logging
|
||||
|
||||
|
|
@ -654,7 +655,7 @@ class TestAsusGamepad(BaseTest.TestGamepad):
|
|||
|
||||
|
||||
class TestRaptorMach2Joystick(BaseTest.TestGamepad):
|
||||
hid_bpfs = [("FR-TEC__Raptor-Mach-2.bpf.o", True)]
|
||||
hid_bpfs = [HidBpf("FR-TEC__Raptor-Mach-2.bpf.o", True)]
|
||||
|
||||
def create_device(self):
|
||||
return RaptorMach2Joystick(
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ from hidtools.util import BusType
|
|||
|
||||
import libevdev
|
||||
import logging
|
||||
from . import base
|
||||
|
||||
logger = logging.getLogger("hidtools.test.ite-keyboard")
|
||||
|
||||
KERNEL_MODULE = ("itetech", "hid_ite")
|
||||
KERNEL_MODULE = base.KernelModule("itetech", "hid_ite")
|
||||
|
||||
|
||||
class KbdData(object):
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import time
|
|||
|
||||
logger = logging.getLogger("hidtools.test.multitouch")
|
||||
|
||||
KERNEL_MODULE = ("hid-multitouch", "hid_multitouch")
|
||||
KERNEL_MODULE = base.KernelModule("hid-multitouch", "hid_multitouch")
|
||||
|
||||
|
||||
def BIT(x):
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#
|
||||
|
||||
from .base import application_matches
|
||||
from .base import KernelModule
|
||||
from .test_gamepad import BaseTest
|
||||
from hidtools.device.sony_gamepad import (
|
||||
PS3Controller,
|
||||
|
|
@ -24,9 +25,9 @@ import pytest
|
|||
|
||||
logger = logging.getLogger("hidtools.test.sony")
|
||||
|
||||
PS3_MODULE = ("sony", "hid_sony")
|
||||
PS4_MODULE = ("playstation", "hid_playstation")
|
||||
PS5_MODULE = ("playstation", "hid_playstation")
|
||||
PS3_MODULE = KernelModule("sony", "hid_sony")
|
||||
PS4_MODULE = KernelModule("playstation", "hid_playstation")
|
||||
PS5_MODULE = KernelModule("playstation", "hid_playstation")
|
||||
|
||||
|
||||
class SonyBaseTest:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from . import base
|
|||
import copy
|
||||
from enum import Enum
|
||||
from hidtools.util import BusType
|
||||
from .base import HidBpf
|
||||
import libevdev
|
||||
import logging
|
||||
import pytest
|
||||
|
|
@ -1472,7 +1473,7 @@ class TestGoodix_27c6_0e00(BaseTest.TestTablet):
|
|||
|
||||
|
||||
class TestXPPen_ArtistPro16Gen2_28bd_095b(BaseTest.TestTablet):
|
||||
hid_bpfs = [("XPPen__ArtistPro16Gen2.bpf.o", True)]
|
||||
hid_bpfs = [HidBpf("XPPen__ArtistPro16Gen2.bpf.o", True)]
|
||||
|
||||
def create_device(self):
|
||||
dev = XPPen_ArtistPro16Gen2_28bd_095b(
|
||||
|
|
@ -1484,7 +1485,7 @@ class TestXPPen_ArtistPro16Gen2_28bd_095b(BaseTest.TestTablet):
|
|||
|
||||
|
||||
class TestXPPen_Artist24_28bd_093a(BaseTest.TestTablet):
|
||||
hid_bpfs = [("XPPen__Artist24.bpf.o", True)]
|
||||
hid_bpfs = [HidBpf("XPPen__Artist24.bpf.o", True)]
|
||||
|
||||
def create_device(self):
|
||||
return XPPen_Artist24_28bd_093a(
|
||||
|
|
@ -1495,7 +1496,7 @@ class TestXPPen_Artist24_28bd_093a(BaseTest.TestTablet):
|
|||
|
||||
|
||||
class TestHuion_Kamvas_Pro_19_256c_006b(BaseTest.TestTablet):
|
||||
hid_bpfs = [("Huion__Kamvas-Pro-19.bpf.o", True)]
|
||||
hid_bpfs = [HidBpf("Huion__Kamvas-Pro-19.bpf.o", True)]
|
||||
|
||||
def create_device(self):
|
||||
return Huion_Kamvas_Pro_19_256c_006b(
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ import logging
|
|||
|
||||
logger = logging.getLogger("hidtools.test.wacom")
|
||||
|
||||
KERNEL_MODULE = ("wacom", "wacom")
|
||||
KERNEL_MODULE = base.KernelModule("wacom", "wacom")
|
||||
|
||||
|
||||
class ProximityState(Enum):
|
||||
|
|
@ -894,7 +894,7 @@ class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest
|
|||
"""
|
||||
return [self.make_contact(id, t) for id in range(0, n)]
|
||||
|
||||
def assert_contact(self, uhdev, evdev, contact_ids, t=0):
|
||||
def assert_contact(self, evdev, contact_ids, t=0):
|
||||
"""
|
||||
Assert properties of a contact generated by make_contact.
|
||||
"""
|
||||
|
|
@ -916,12 +916,12 @@ class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest
|
|||
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_X] == x
|
||||
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_Y] == y
|
||||
|
||||
def assert_contacts(self, uhdev, evdev, data, t=0):
|
||||
def assert_contacts(self, evdev, data, t=0):
|
||||
"""
|
||||
Assert properties of a list of contacts generated by make_contacts.
|
||||
"""
|
||||
for contact_ids in data:
|
||||
self.assert_contact(uhdev, evdev, contact_ids, t)
|
||||
self.assert_contact(evdev, contact_ids, t)
|
||||
|
||||
def test_contact_id_0(self):
|
||||
"""
|
||||
|
|
@ -998,7 +998,6 @@ class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest
|
|||
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
|
||||
|
||||
self.assert_contacts(
|
||||
uhdev,
|
||||
evdev,
|
||||
[
|
||||
self.ContactIds(contact_id=0, tracking_id=-1, slot_num=None),
|
||||
|
|
@ -1032,7 +1031,7 @@ class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest
|
|||
self.debug_reports(r, uhdev, events)
|
||||
|
||||
ids = [x[0] for x in state]
|
||||
self.assert_contacts(uhdev, evdev, ids, t)
|
||||
self.assert_contacts(evdev, ids, t)
|
||||
|
||||
t += 1
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user