diff options
Diffstat (limited to 'kvmd/plugins/hid/otg')
-rw-r--r-- | kvmd/plugins/hid/otg/__init__.py | 52 | ||||
-rw-r--r-- | kvmd/plugins/hid/otg/device.py | 26 | ||||
-rw-r--r-- | kvmd/plugins/hid/otg/keyboard.py | 12 |
3 files changed, 41 insertions, 49 deletions
diff --git a/kvmd/plugins/hid/otg/__init__.py b/kvmd/plugins/hid/otg/__init__.py index 84c2803e..0684a674 100644 --- a/kvmd/plugins/hid/otg/__init__.py +++ b/kvmd/plugins/hid/otg/__init__.py @@ -20,17 +20,12 @@ # ========================================================================== # -import asyncio -import concurrent.futures -import multiprocessing -import multiprocessing.queues -import queue -import functools - from typing import Dict from typing import AsyncGenerator from typing import Any +from .... import aiomulti + from ....yamlconf import Option from ....validators.basic import valid_bool @@ -54,10 +49,10 @@ class Plugin(BaseHid): noop: bool, ) -> None: - self.__changes_queue: multiprocessing.queues.Queue = multiprocessing.Queue() + self.__state_notifier = aiomulti.AioProcessNotifier() - self.__keyboard_proc = KeyboardProcess(noop=noop, changes_queue=self.__changes_queue, **keyboard) - self.__mouse_proc = MouseProcess(noop=noop, changes_queue=self.__changes_queue, **mouse) + self.__keyboard_proc = KeyboardProcess(noop=noop, state_notifier=self.__state_notifier, **keyboard) + self.__mouse_proc = MouseProcess(noop=noop, state_notifier=self.__state_notifier, **mouse) @classmethod def get_plugin_options(cls) -> Dict: @@ -81,31 +76,30 @@ class Plugin(BaseHid): self.__keyboard_proc.start() self.__mouse_proc.start() - def get_state(self) -> Dict: - keyboard_state = self.__keyboard_proc.get_state() - mouse_state = self.__mouse_proc.get_state() + async def get_state(self) -> Dict: + keyboard_state = await self.__keyboard_proc.get_state() + mouse_state = await self.__mouse_proc.get_state() return { "online": (keyboard_state["online"] and mouse_state["online"]), - "keyboard": {"features": {"leds": True}, **keyboard_state}, + "keyboard": { + "online": keyboard_state["online"], + "leds": { + "caps": keyboard_state["caps"], + "scroll": keyboard_state["scroll"], + "num": keyboard_state["num"], + }, + }, "mouse": mouse_state, } async def poll_state(self) -> AsyncGenerator[Dict, None]: - loop = asyncio.get_running_loop() - wait_for_changes = functools.partial(self.__changes_queue.get, timeout=1) - with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor: - prev_state: Dict = {} - while True: - state = self.get_state() - if state != prev_state: - yield state - prev_state = state - while True: - try: - await loop.run_in_executor(executor, wait_for_changes) - break - except queue.Empty: - pass + prev_state: Dict = {} + while True: + state = await self.get_state() + if state != prev_state: + yield state + prev_state = state + await self.__state_notifier.wait() async def reset(self) -> None: self.__keyboard_proc.send_reset_event() diff --git a/kvmd/plugins/hid/otg/device.py b/kvmd/plugins/hid/otg/device.py index 0fbb63cb..37cb7b07 100644 --- a/kvmd/plugins/hid/otg/device.py +++ b/kvmd/plugins/hid/otg/device.py @@ -30,12 +30,13 @@ import errno import time from typing import Dict -from typing import Any import setproctitle from ....logging import get_logger +from .... import aiomulti + # ===== class BaseEvent: @@ -48,7 +49,7 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in name: str, read_size: int, initial_state: Dict, - changes_queue: multiprocessing.queues.Queue, + state_notifier: aiomulti.AioProcessNotifier, device_path: str, select_timeout: float, @@ -61,7 +62,6 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in self.__name = name self.__read_size = read_size - self.__changes_queue = changes_queue self.__device_path = device_path self.__select_timeout = select_timeout @@ -71,7 +71,7 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in self.__fd = -1 self.__events_queue: multiprocessing.queues.Queue = multiprocessing.Queue() - self.__state_shared = multiprocessing.Manager().dict(online=True, **initial_state) # type: ignore + self.__state_flags = aiomulti.AioSharedFlags({"online": True, **initial_state}, state_notifier) self.__stop_event = multiprocessing.Event() def run(self) -> None: @@ -100,8 +100,8 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in self.__close_device() - def get_state(self) -> Dict: - return dict(self.__state_shared) + async def get_state(self) -> Dict: + return (await self.__state_flags.get()) # ===== @@ -111,6 +111,9 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in def _process_read_report(self, report: bytes) -> None: pass + def _update_state(self, **kwargs: bool) -> None: + self.__state_flags.update(**kwargs) + # ===== def _stop(self) -> None: @@ -134,11 +137,6 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in if close: self.__close_device() - def _update_state(self, key: str, value: Any) -> None: - if self.__state_shared[key] != value: - self.__state_shared[key] = value - self.__changes_queue.put(None) - # ===== def __write_report(self, report: bytes) -> bool: @@ -153,7 +151,7 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in try: written = os.write(self.__fd, report) if written == len(report): - self._update_state("online", True) + self.__state_flags.update(online=True) return True else: logger.error("HID-%s write() error: written (%s) != report length (%d)", @@ -223,7 +221,7 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in if self.__fd >= 0: try: if select.select([], [self.__fd], [], self.__select_timeout)[1]: - self._update_state("online", True) + self.__state_flags.update(online=True) return True else: logger.debug("HID-%s is busy/unplugged (write select)", self.__name) @@ -231,7 +229,7 @@ class BaseDeviceProcess(multiprocessing.Process): # pylint: disable=too-many-in logger.error("Can't select() for write HID-%s: %s: %s", self.__name, type(err).__name__, err) self.__close_device() - self._update_state("online", False) + self.__state_flags.update(online=False) return False def __close_device(self) -> None: diff --git a/kvmd/plugins/hid/otg/keyboard.py b/kvmd/plugins/hid/otg/keyboard.py index 6c9ddfed..fb964d8a 100644 --- a/kvmd/plugins/hid/otg/keyboard.py +++ b/kvmd/plugins/hid/otg/keyboard.py @@ -68,7 +68,7 @@ class KeyboardProcess(BaseDeviceProcess): super().__init__( name="keyboard", read_size=1, - initial_state={"leds": {"caps": False, "scroll": False, "num": False}}, + initial_state={"caps": False, "scroll": False, "num": False}, **kwargs, ) @@ -98,11 +98,11 @@ class KeyboardProcess(BaseDeviceProcess): def _process_read_report(self, report: bytes) -> None: # https://wiki.osdev.org/USB_Human_Interface_Devices#LED_lamps assert len(report) == 1, report - self._update_state("leds", { - "caps": bool(report[0] & 2), - "scroll": bool(report[0] & 4), - "num": bool(report[0] & 1), - }) + self._update_state( + caps=bool(report[0] & 2), + scroll=bool(report[0] & 4), + num=bool(report[0] & 1), + ) # ===== |