selftests/hid: add support for HID-BPF pre-loading before starting a test

few required changes:
- we need to count how many times a udev 'bind' event happens
- we need to tell `udev-hid-bpf` to not automatically attach the
  provided HID-BPF objects
- we need to manually attach the ones from the kernel tree, and wait
  for the second udev 'bind' event to happen

Link: https://lore.kernel.org/r/20240410-bpf_sources-v1-11-a8bf16033ef8@kernel.org
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
This commit is contained in:
Benjamin Tissoires
2024-04-10 19:19:31 +02:00
parent a7def2e51c
commit e906463087
2 changed files with 93 additions and 15 deletions

View File

@@ -35,7 +35,7 @@ from hidtools.uhid import UHIDDevice
from hidtools.util import BusType
from pathlib import Path
from typing import Any, ClassVar, Dict, List, Optional, Type, Union
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Type, Union
logger = logging.getLogger("hidtools.device.base_device")
@@ -126,7 +126,7 @@ class HIDIsReady(object):
class UdevHIDIsReady(HIDIsReady):
_pyudev_context: ClassVar[Optional[pyudev.Context]] = None
_pyudev_monitor: ClassVar[Optional[pyudev.Monitor]] = None
_uhid_devices: ClassVar[Dict[int, bool]] = {}
_uhid_devices: ClassVar[Dict[int, Tuple[bool, int]]] = {}
def __init__(self: "UdevHIDIsReady", uhid: UHIDDevice) -> None:
super().__init__(uhid)
@@ -150,20 +150,25 @@ class UdevHIDIsReady(HIDIsReady):
return
event: pyudev.Device
for event in iter(functools.partial(cls._pyudev_monitor.poll, 0.02), None):
if event.action not in ["bind", "remove"]:
if event.action not in ["bind", "remove", "unbind"]:
return
logger.debug(f"udev event: {event.action} -> {event}")
id = int(event.sys_path.strip().split(".")[-1], 16)
cls._uhid_devices[id] = event.action == "bind"
device_ready, count = cls._uhid_devices.get(id, (False, 0))
def is_ready(self: "UdevHIDIsReady") -> bool:
ready = event.action == "bind"
if not device_ready and ready:
count += 1
cls._uhid_devices[id] = (ready, count)
def is_ready(self: "UdevHIDIsReady") -> Tuple[bool, int]:
try:
return self._uhid_devices[self.uhid.hid_id]
except KeyError:
return False
return (False, 0)
class EvdevMatch(object):
@@ -317,7 +322,11 @@ class BaseDevice(UHIDDevice):
@property
def kernel_is_ready(self: "BaseDevice") -> bool:
return self._kernel_is_ready.is_ready() and self.started
return self._kernel_is_ready.is_ready()[0] and self.started
@property
def kernel_ready_count(self: "BaseDevice") -> int:
return self._kernel_is_ready.is_ready()[1]
@property
def input_nodes(self: "BaseDevice") -> List[EvdevDevice]: