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
hid:
reset_pin: 4
device: /dev/kvmd-hid
type: tty
params:
reset_pin: 4
device: /dev/kvmd-hid
atx:
power_led_pin: 24

View File

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

View File

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

View File

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

View File

@ -37,6 +37,7 @@ import pygments.formatters
from ..plugins import UnknownPluginError
from ..plugins.auth import get_auth_service_class
from ..plugins.hid import get_hid_class
from ..yamlconf import ConfigError
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_fps
from ..validators.hw import valid_tty_speed
from ..validators.hw import valid_gpio_pin
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()
if config.kvmd.auth.external_type:
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)
return config
@ -174,18 +177,8 @@ def _get_config_scheme(sections: List[str]) -> Dict:
},
"hid": {
"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),
"type": Option("tty"),
# "params": {},
},
"atx": {

View File

@ -48,7 +48,9 @@ def main(argv: Optional[List[str]]=None) -> None:
logger.info("Cleaning up ...")
with gpio.bcm():
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_reset_switch_pin", config.atx.reset_switch_pin, config.atx.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 ...plugins.hid import get_hid_class
from .. import init
from .auth import AuthManager
from .info import InfoManager
from .logreader import LogReader
from .hid import Hid
from .atx import Atx
from .msd import MassStorageDevice
from .streamer import Streamer
@ -61,7 +62,7 @@ def main(argv: Optional[List[str]]=None) -> None:
info_manager=InfoManager(**config.info._unpack()),
log_reader=LogReader(),
hid=Hid(**config.hid._unpack()),
hid=get_hid_class(config.hid.type)(**config.hid.params._unpack()),
atx=Atx(**config.atx._unpack()),
msd=MassStorageDevice(**config.msd._unpack()),
streamer=Streamer(**config.streamer._unpack()),

View File

@ -44,6 +44,8 @@ from ...logging import get_logger
from ...aioregion import RegionIsBusyError
from ...plugins.hid import BaseHid
from ...validators import ValidatorError
from ...validators.basic import valid_bool
@ -70,7 +72,6 @@ from ... import __version__
from .auth import AuthManager
from .info import InfoManager
from .logreader import LogReader
from .hid import Hid
from .atx import AtxOperationError
from .atx import Atx
from .msd import MsdOperationError
@ -230,7 +231,7 @@ class Server: # pylint: disable=too-many-instance-attributes
info_manager: InfoManager,
log_reader: LogReader,
hid: Hid,
hid: BaseHid,
atx: Atx,
msd: MassStorageDevice,
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 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:
@ -112,8 +125,8 @@ class _MouseWheelEvent(_IntEvent):
# =====
class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attributes
def __init__( # pylint: disable=too-many-arguments
class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-instance-attributes
def __init__( # pylint: disable=too-many-arguments,super-init-not-called
self,
reset_pin: int,
reset_delay: float,
@ -129,7 +142,7 @@ class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attribu
state_poll: float,
) -> None:
super().__init__(daemon=True)
multiprocessing.Process.__init__(self, daemon=True)
self.__reset_pin = gpio.set_output(reset_pin)
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.__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:
get_logger().info("Starting HID daemon ...")
super().start()
multiprocessing.Process.start(self)
def get_state(self) -> Dict:
return {"online": bool(self.__online_shared.value)}

View File

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

View File

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