mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 17:20:30 +08:00
otgbind pseudo-gpio plugin
This commit is contained in:
parent
77771bea55
commit
570dd04e29
@ -409,9 +409,10 @@ def _get_config_scheme() -> Dict:
|
|||||||
"udc": Option("", type=valid_stripped_string),
|
"udc": Option("", type=valid_stripped_string),
|
||||||
"init_delay": Option(3.0, type=valid_float_f01),
|
"init_delay": Option(3.0, type=valid_float_f01),
|
||||||
|
|
||||||
|
"user": Option("kvmd", type=valid_user),
|
||||||
|
|
||||||
"devices": {
|
"devices": {
|
||||||
"msd": {
|
"msd": {
|
||||||
"user": Option("kvmd", type=valid_user),
|
|
||||||
"default": {
|
"default": {
|
||||||
"stall": Option(False, type=valid_bool),
|
"stall": Option(False, type=valid_bool),
|
||||||
"cdrom": Option(True, type=valid_bool),
|
"cdrom": Option(True, type=valid_bool),
|
||||||
|
|||||||
@ -81,7 +81,7 @@ def main(argv: Optional[List[str]]=None) -> None:
|
|||||||
info_manager=InfoManager(global_config),
|
info_manager=InfoManager(global_config),
|
||||||
log_reader=LogReader(),
|
log_reader=LogReader(),
|
||||||
wol=WakeOnLan(**config.wol._unpack()),
|
wol=WakeOnLan(**config.wol._unpack()),
|
||||||
user_gpio=UserGpio(config.gpio),
|
user_gpio=UserGpio(config.gpio, global_config.otg.udc),
|
||||||
|
|
||||||
hid=hid,
|
hid=hid,
|
||||||
atx=get_atx_class(config.atx.type)(**config.atx._unpack(ignore=["type"])),
|
atx=get_atx_class(config.atx.type)(**config.atx._unpack(ignore=["type"])),
|
||||||
|
|||||||
@ -231,7 +231,7 @@ class _GpioOutput: # pylint: disable=too-many-instance-attributes
|
|||||||
|
|
||||||
# =====
|
# =====
|
||||||
class UserGpio:
|
class UserGpio:
|
||||||
def __init__(self, config: Section) -> None:
|
def __init__(self, config: Section, udc: str) -> None:
|
||||||
self.__view = config.view
|
self.__view = config.view
|
||||||
|
|
||||||
self.__notifier = aiotools.AioNotifier()
|
self.__notifier = aiotools.AioNotifier()
|
||||||
@ -241,6 +241,7 @@ class UserGpio:
|
|||||||
instance_name=driver,
|
instance_name=driver,
|
||||||
notifier=self.__notifier,
|
notifier=self.__notifier,
|
||||||
**drv_config._unpack(ignore=["instance_name", "notifier", "type"]),
|
**drv_config._unpack(ignore=["instance_name", "notifier", "type"]),
|
||||||
|
**({"udc": udc} if drv_config.type == "otgbind" else {}), # Hack
|
||||||
)
|
)
|
||||||
for (driver, drv_config) in tools.sorted_kvs(config.drivers)
|
for (driver, drv_config) in tools.sorted_kvs(config.drivers)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -210,7 +210,7 @@ def _cmd_start(config: Section) -> None:
|
|||||||
|
|
||||||
if config.kvmd.msd.type == "otg":
|
if config.kvmd.msd.type == "otg":
|
||||||
logger.info("===== Required MSD =====")
|
logger.info("===== Required MSD =====")
|
||||||
_create_msd(gadget_path, config_path, 0, config.otg.devices.msd.user, **config.otg.devices.msd.default._unpack())
|
_create_msd(gadget_path, config_path, 0, config.otg.user, **config.otg.devices.msd.default._unpack())
|
||||||
if config.otg.devices.drives.enabled:
|
if config.otg.devices.drives.enabled:
|
||||||
logger.info("===== Required MSD extra drives: %d =====", config.otg.devices.drives.count)
|
logger.info("===== Required MSD extra drives: %d =====", config.otg.devices.drives.count)
|
||||||
for instance in range(config.otg.devices.drives.count):
|
for instance in range(config.otg.devices.drives.count):
|
||||||
@ -222,6 +222,11 @@ def _cmd_start(config: Section) -> None:
|
|||||||
_write(join(gadget_path, "UDC"), udc)
|
_write(join(gadget_path, "UDC"), udc)
|
||||||
time.sleep(config.otg.init_delay)
|
time.sleep(config.otg.init_delay)
|
||||||
|
|
||||||
|
logger.info("Setting DWC2 bind permissions ...")
|
||||||
|
driver_path = f"{env.SYSFS_PREFIX}/sys/bus/platform/drivers/dwc2"
|
||||||
|
_chown(join(driver_path, "bind"), config.otg.user)
|
||||||
|
_chown(join(driver_path, "unbind"), config.otg.user)
|
||||||
|
|
||||||
logger.info("Ready to work")
|
logger.info("Ready to work")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
119
kvmd/plugins/ugpio/otgbind.py
Normal file
119
kvmd/plugins/ugpio/otgbind.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# 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/>. #
|
||||||
|
# #
|
||||||
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from ...logging import get_logger
|
||||||
|
|
||||||
|
from ...inotify import InotifyMask
|
||||||
|
from ...inotify import Inotify
|
||||||
|
|
||||||
|
from ... import env
|
||||||
|
from ... import aiotools
|
||||||
|
|
||||||
|
from . import BaseUserGpioDriver
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
class Plugin(BaseUserGpioDriver):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
instance_name: str,
|
||||||
|
notifier: aiotools.AioNotifier,
|
||||||
|
|
||||||
|
udc: str, # XXX: Not from options, see /kvmd/apps/kvmd/__init__.py for details
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
super().__init__(instance_name, notifier)
|
||||||
|
|
||||||
|
self.__udc = udc
|
||||||
|
|
||||||
|
def register_input(self, pin: int, debounce: float) -> None:
|
||||||
|
_ = pin
|
||||||
|
_ = debounce
|
||||||
|
|
||||||
|
def register_output(self, pin: int, initial: Optional[bool]) -> None:
|
||||||
|
_ = pin
|
||||||
|
_ = initial
|
||||||
|
|
||||||
|
def prepare(self) -> None:
|
||||||
|
candidates = sorted(os.listdir(f"{env.SYSFS_PREFIX}/sys/class/udc"))
|
||||||
|
if not self.__udc:
|
||||||
|
if len(candidates) == 0:
|
||||||
|
raise RuntimeError("Can't find any UDC")
|
||||||
|
self.__udc = candidates[0]
|
||||||
|
elif self.__udc not in candidates:
|
||||||
|
raise RuntimeError(f"Can't find selected UDC: {self.__udc}")
|
||||||
|
get_logger().info("Using UDC %s", self.__udc)
|
||||||
|
|
||||||
|
async def run(self) -> None:
|
||||||
|
logger = get_logger(0)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
await self._notifier.notify()
|
||||||
|
if os.path.isdir(self.__get_driver_path()):
|
||||||
|
break
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
|
||||||
|
with Inotify() as inotify:
|
||||||
|
inotify.watch(self.__get_driver_path(), InotifyMask.ALL_MODIFY_EVENTS)
|
||||||
|
await self._notifier.notify()
|
||||||
|
while True:
|
||||||
|
need_restart = False
|
||||||
|
need_notify = False
|
||||||
|
for event in (await inotify.get_series(timeout=1)):
|
||||||
|
need_notify = True
|
||||||
|
if event.mask & (InotifyMask.DELETE_SELF | InotifyMask.MOVE_SELF | InotifyMask.UNMOUNT):
|
||||||
|
logger.warning("Got fatal inotify event: %s; reinitializing OTG-bind ...", event)
|
||||||
|
need_restart = True
|
||||||
|
break
|
||||||
|
if need_restart:
|
||||||
|
break
|
||||||
|
if need_notify:
|
||||||
|
await self._notifier.notify()
|
||||||
|
except Exception:
|
||||||
|
logger.exception("Unexpected OTG-bind watcher error")
|
||||||
|
|
||||||
|
def cleanup(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def read(self, pin: int) -> bool:
|
||||||
|
_ = pin
|
||||||
|
return os.path.islink(self.__get_driver_path(self.__udc))
|
||||||
|
|
||||||
|
def write(self, pin: int, state: bool) -> None:
|
||||||
|
_ = pin
|
||||||
|
with open(self.__get_driver_path("bind" if state else "unbind"), "w") as ctl_file:
|
||||||
|
ctl_file.write(f"{self.__udc}\n")
|
||||||
|
|
||||||
|
def __get_driver_path(self, name: str="") -> str:
|
||||||
|
path = f"{env.SYSFS_PREFIX}/sys/bus/platform/drivers/dwc2"
|
||||||
|
return (os.path.join(path, name) if name else path)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"GPIO({self._instance_name})"
|
||||||
|
|
||||||
|
__repr__ = __str__
|
||||||
Loading…
x
Reference in New Issue
Block a user