plugin hid

This commit is contained in:
Devaev Maxim 2019-09-11 06:28:04 +03:00
parent 447904e468
commit e17889ba42
12 changed files with 138 additions and 33 deletions

View File

@ -15,8 +15,10 @@ kvmd:
auth: !include auth.yaml auth: !include auth.yaml
hid: hid:
reset_pin: 4 type: tty
device: /dev/kvmd-hid params:
reset_pin: 4
device: /dev/kvmd-hid
atx: atx:
power_led_pin: 24 power_led_pin: 24

View File

@ -15,8 +15,10 @@ kvmd:
auth: !include auth.yaml auth: !include auth.yaml
hid: hid:
reset_pin: 4 type: tty
device: /dev/kvmd-hid params:
reset_pin: 4
device: /dev/kvmd-hid
atx: atx:
power_led_pin: 24 power_led_pin: 24

View File

@ -15,8 +15,10 @@ kvmd:
auth: !include auth.yaml auth: !include auth.yaml
hid: hid:
reset_pin: 4 type: tty
device: /dev/kvmd-hid params:
reset_pin: 4
device: /dev/kvmd-hid
atx: atx:
power_led_pin: 24 power_led_pin: 24

View File

@ -15,8 +15,10 @@ kvmd:
auth: !include auth.yaml auth: !include auth.yaml
hid: hid:
reset_pin: 4 type: tty
device: /dev/kvmd-hid params:
reset_pin: 4
device: /dev/kvmd-hid
atx: atx:
power_led_pin: 24 power_led_pin: 24

View File

@ -37,6 +37,7 @@ import pygments.formatters
from ..plugins import UnknownPluginError from ..plugins import UnknownPluginError
from ..plugins.auth import get_auth_service_class from ..plugins.auth import get_auth_service_class
from ..plugins.hid import get_hid_class
from ..yamlconf import ConfigError from ..yamlconf import ConfigError
from ..yamlconf import make_config from ..yamlconf import make_config
@ -64,7 +65,6 @@ from ..validators.net import valid_port
from ..validators.kvm import valid_stream_quality from ..validators.kvm import valid_stream_quality
from ..validators.kvm import valid_stream_fps from ..validators.kvm import valid_stream_fps
from ..validators.hw import valid_tty_speed
from ..validators.hw import valid_gpio_pin from ..validators.hw import valid_gpio_pin
from ..validators.hw import valid_gpio_pin_optional from ..validators.hw import valid_gpio_pin_optional
@ -115,6 +115,9 @@ def _init_config(config_path: str, sections: List[str], override_options: List[s
scheme["kvmd"]["auth"]["internal"] = get_auth_service_class(config.kvmd.auth.internal_type).get_plugin_options() scheme["kvmd"]["auth"]["internal"] = get_auth_service_class(config.kvmd.auth.internal_type).get_plugin_options()
if config.kvmd.auth.external_type: if config.kvmd.auth.external_type:
scheme["kvmd"]["auth"]["external"] = get_auth_service_class(config.kvmd.auth.external_type).get_plugin_options() scheme["kvmd"]["auth"]["external"] = get_auth_service_class(config.kvmd.auth.external_type).get_plugin_options()
scheme["kvmd"]["hid"]["params"] = get_hid_class(config.kvmd.hid.type).get_plugin_options()
config = make_config(raw_config, scheme) config = make_config(raw_config, scheme)
return config return config
@ -174,18 +177,8 @@ def _get_config_scheme(sections: List[str]) -> Dict:
}, },
"hid": { "hid": {
"reset_pin": Option(-1, type=valid_gpio_pin), "type": Option("tty"),
"reset_delay": Option(0.1, type=valid_float_f01), # "params": {},
"device": Option("", type=valid_abs_path, unpack_as="device_path"),
"speed": Option(115200, type=valid_tty_speed),
"read_timeout": Option(2.0, type=valid_float_f01),
"read_retries": Option(10, type=valid_int_f1),
"common_retries": Option(100, type=valid_int_f1),
"retries_delay": Option(0.1, type=valid_float_f01),
"noop": Option(False, type=valid_bool),
"state_poll": Option(0.1, type=valid_float_f01),
}, },
"atx": { "atx": {

View File

@ -48,7 +48,9 @@ def main(argv: Optional[List[str]]=None) -> None:
logger.info("Cleaning up ...") logger.info("Cleaning up ...")
with gpio.bcm(): with gpio.bcm():
for (name, pin, enabled) in [ for (name, pin, enabled) in [
("hid_reset_pin", config.hid.reset_pin, True), *([
("hid_reset_pin", config.hid.params.reset_pin, True),
] if config.hid.type == "tty" else []),
("atx_power_switch_pin", config.atx.power_switch_pin, config.atx.enabled), ("atx_power_switch_pin", config.atx.power_switch_pin, config.atx.enabled),
("atx_reset_switch_pin", config.atx.reset_switch_pin, config.atx.enabled), ("atx_reset_switch_pin", config.atx.reset_switch_pin, config.atx.enabled),
("msd_target_pin", config.msd.target_pin, config.msd.enabled), ("msd_target_pin", config.msd.target_pin, config.msd.enabled),

View File

@ -27,12 +27,13 @@ from ...logging import get_logger
from ... import gpio from ... import gpio
from ...plugins.hid import get_hid_class
from .. import init from .. import init
from .auth import AuthManager from .auth import AuthManager
from .info import InfoManager from .info import InfoManager
from .logreader import LogReader from .logreader import LogReader
from .hid import Hid
from .atx import Atx from .atx import Atx
from .msd import MassStorageDevice from .msd import MassStorageDevice
from .streamer import Streamer from .streamer import Streamer
@ -61,7 +62,7 @@ def main(argv: Optional[List[str]]=None) -> None:
info_manager=InfoManager(**config.info._unpack()), info_manager=InfoManager(**config.info._unpack()),
log_reader=LogReader(), log_reader=LogReader(),
hid=Hid(**config.hid._unpack()), hid=get_hid_class(config.hid.type)(**config.hid.params._unpack()),
atx=Atx(**config.atx._unpack()), atx=Atx(**config.atx._unpack()),
msd=MassStorageDevice(**config.msd._unpack()), msd=MassStorageDevice(**config.msd._unpack()),
streamer=Streamer(**config.streamer._unpack()), streamer=Streamer(**config.streamer._unpack()),

View File

@ -44,6 +44,8 @@ from ...logging import get_logger
from ...aioregion import RegionIsBusyError from ...aioregion import RegionIsBusyError
from ...plugins.hid import BaseHid
from ...validators import ValidatorError from ...validators import ValidatorError
from ...validators.basic import valid_bool from ...validators.basic import valid_bool
@ -70,7 +72,6 @@ from ... import __version__
from .auth import AuthManager from .auth import AuthManager
from .info import InfoManager from .info import InfoManager
from .logreader import LogReader from .logreader import LogReader
from .hid import Hid
from .atx import AtxOperationError from .atx import AtxOperationError
from .atx import Atx from .atx import Atx
from .msd import MsdOperationError from .msd import MsdOperationError
@ -230,7 +231,7 @@ class Server: # pylint: disable=too-many-instance-attributes
info_manager: InfoManager, info_manager: InfoManager,
log_reader: LogReader, log_reader: LogReader,
hid: Hid, hid: BaseHid,
atx: Atx, atx: Atx,
msd: MassStorageDevice, msd: MassStorageDevice,
streamer: Streamer, streamer: Streamer,

View File

@ -0,0 +1,67 @@
# ========================================================================== #
# #
# KVMD - The main Pi-KVM daemon. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
# ========================================================================== #
from typing import Dict
from typing import AsyncGenerator
from typing import Type
from .. import BasePlugin
from .. import get_plugin_class
# =====
class BaseHid(BasePlugin):
def start(self) -> None:
pass
def get_state(self) -> Dict:
raise NotImplementedError
async def poll_state(self) -> AsyncGenerator[Dict, None]:
yield {}
raise NotImplementedError
async def reset(self) -> None:
raise NotImplementedError
async def send_key_event(self, key: str, state: bool) -> None:
raise NotImplementedError
async def send_mouse_move_event(self, to_x: int, to_y: int) -> None:
raise NotImplementedError
async def send_mouse_button_event(self, button: str, state: bool) -> None:
raise NotImplementedError
async def send_mouse_wheel_event(self, delta_y: int) -> None:
raise NotImplementedError
async def clear_events(self) -> None:
raise NotImplementedError
async def cleanup(self) -> None:
pass
# =====
def get_hid_class(name: str) -> Type[BaseHid]:
return get_plugin_class("hid", name) # type: ignore

View File

@ -44,6 +44,19 @@ from ... import aiotools
from ... import gpio from ... import gpio
from ... import keymap from ... import keymap
from ...yamlconf import Option
from ...validators.basic import valid_bool
from ...validators.basic import valid_int_f1
from ...validators.basic import valid_float_f01
from ...validators.os import valid_abs_path
from ...validators.hw import valid_tty_speed
from ...validators.hw import valid_gpio_pin
from . import BaseHid
# ===== # =====
class _BaseEvent: class _BaseEvent:
@ -112,8 +125,8 @@ class _MouseWheelEvent(_IntEvent):
# ===== # =====
class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attributes class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-instance-attributes
def __init__( # pylint: disable=too-many-arguments def __init__( # pylint: disable=too-many-arguments,super-init-not-called
self, self,
reset_pin: int, reset_pin: int,
reset_delay: float, reset_delay: float,
@ -129,7 +142,7 @@ class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attribu
state_poll: float, state_poll: float,
) -> None: ) -> None:
super().__init__(daemon=True) multiprocessing.Process.__init__(self, daemon=True)
self.__reset_pin = gpio.set_output(reset_pin) self.__reset_pin = gpio.set_output(reset_pin)
self.__reset_delay = reset_delay self.__reset_delay = reset_delay
@ -153,9 +166,26 @@ class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attribu
self.__online_shared = multiprocessing.Value("i", 1) self.__online_shared = multiprocessing.Value("i", 1)
self.__stop_event = multiprocessing.Event() self.__stop_event = multiprocessing.Event()
@classmethod
def get_plugin_options(cls) -> Dict[str, Option]:
return {
"reset_pin": Option(-1, type=valid_gpio_pin),
"reset_delay": Option(0.1, type=valid_float_f01),
"device": Option("", type=valid_abs_path, unpack_as="device_path"),
"speed": Option(115200, type=valid_tty_speed),
"read_timeout": Option(2.0, type=valid_float_f01),
"read_retries": Option(10, type=valid_int_f1),
"common_retries": Option(100, type=valid_int_f1),
"retries_delay": Option(0.1, type=valid_float_f01),
"noop": Option(False, type=valid_bool),
"state_poll": Option(0.1, type=valid_float_f01),
}
def start(self) -> None: def start(self) -> None:
get_logger().info("Starting HID daemon ...") get_logger().info("Starting HID daemon ...")
super().start() multiprocessing.Process.start(self)
def get_state(self) -> Dict: def get_state(self) -> Dict:
return {"online": bool(self.__online_shared.value)} return {"online": bool(self.__online_shared.value)}

View File

@ -81,6 +81,7 @@ def main() -> None:
"kvmd.yamlconf", "kvmd.yamlconf",
"kvmd.plugins", "kvmd.plugins",
"kvmd.plugins.auth", "kvmd.plugins.auth",
"kvmd.plugins.hid",
"kvmd.apps", "kvmd.apps",
"kvmd.apps.kvmd", "kvmd.apps.kvmd",
"kvmd.apps.htpasswd", "kvmd.apps.htpasswd",

View File

@ -7,9 +7,11 @@ kvmd:
auth: !include auth.yaml auth: !include auth.yaml
hid: hid:
reset_pin: 4 type: tty
device: /dev/ttyS10 params:
noop: true reset_pin: 4
device: /dev/ttyS10
noop: true
atx: atx:
power_led_pin: 24 power_led_pin: 24