mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-13 17:50:29 +08:00
switch binary
This commit is contained in:
parent
4d89d6b222
commit
3cf543a13e
3
PKGBUILD
3
PKGBUILD
@ -79,6 +79,7 @@ depends=(
|
|||||||
python-mako
|
python-mako
|
||||||
python-luma-oled
|
python-luma-oled
|
||||||
python-pyusb
|
python-pyusb
|
||||||
|
python-pyudev
|
||||||
"libgpiod>=2.1"
|
"libgpiod>=2.1"
|
||||||
freetype2
|
freetype2
|
||||||
"v4l-utils>=1.22.1-1"
|
"v4l-utils>=1.22.1-1"
|
||||||
@ -167,7 +168,7 @@ package_kvmd() {
|
|||||||
install -DTm644 configs/os/tmpfiles.conf "$pkgdir/usr/lib/tmpfiles.d/kvmd.conf"
|
install -DTm644 configs/os/tmpfiles.conf "$pkgdir/usr/lib/tmpfiles.d/kvmd.conf"
|
||||||
|
|
||||||
mkdir -p "$pkgdir/usr/share/kvmd"
|
mkdir -p "$pkgdir/usr/share/kvmd"
|
||||||
cp -r {hid,web,extras,contrib/keymaps} "$pkgdir/usr/share/kvmd"
|
cp -r {switch,hid,web,extras,contrib/keymaps} "$pkgdir/usr/share/kvmd"
|
||||||
find "$pkgdir/usr/share/kvmd/web" -name '*.pug' -exec rm -f '{}' \;
|
find "$pkgdir/usr/share/kvmd/web" -name '*.pug' -exec rm -f '{}' \;
|
||||||
|
|
||||||
local _cfg_default="$pkgdir/usr/share/kvmd/configs.default"
|
local _cfg_default="$pkgdir/usr/share/kvmd/configs.default"
|
||||||
|
|||||||
167
kvmd/apps/swctl/__init__.py
Normal file
167
kvmd/apps/swctl/__init__.py
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# KVMD - The main PiKVM daemon. #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2018-2024 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 argparse
|
||||||
|
import pprint
|
||||||
|
import time
|
||||||
|
|
||||||
|
import pyudev
|
||||||
|
|
||||||
|
from ..kvmd.switch.device import Device
|
||||||
|
from ..kvmd.switch.proto import Edid
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
def _find_serial_device() -> str:
|
||||||
|
ctx = pyudev.Context()
|
||||||
|
for device in ctx.list_devices(subsystem="tty"):
|
||||||
|
if (
|
||||||
|
str(device.properties.get("ID_VENDOR_ID")).upper() == "2E8A"
|
||||||
|
and str(device.properties.get("ID_MODEL_ID")).upper() == "1080"
|
||||||
|
):
|
||||||
|
path = device.properties["DEVNAME"]
|
||||||
|
assert path.startswith("/dev/")
|
||||||
|
return path
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_boot_device() -> str:
|
||||||
|
stop_ts = time.time() + 5
|
||||||
|
ctx = pyudev.Context()
|
||||||
|
while time.time() < stop_ts:
|
||||||
|
for device in ctx.list_devices(subsystem="block", DEVTYPE="partition"):
|
||||||
|
if (
|
||||||
|
str(device.properties.get("ID_VENDOR_ID")).upper() == "2E8A"
|
||||||
|
and str(device.properties.get("ID_MODEL_ID")).upper() == "0003"
|
||||||
|
):
|
||||||
|
path = device.properties["DEVNAME"]
|
||||||
|
assert path.startswith("/dev/")
|
||||||
|
return path
|
||||||
|
time.sleep(0.2)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _create_edid(arg: str) -> Edid:
|
||||||
|
if arg == "@":
|
||||||
|
return Edid.from_data("Empty", None)
|
||||||
|
with open(arg) as file:
|
||||||
|
return Edid.from_data(os.path.basename(arg), file.read())
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
def main() -> None: # pylint: disable=too-many-statements
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("-d", "--device", default="")
|
||||||
|
parser.set_defaults(cmd="")
|
||||||
|
subs = parser.add_subparsers()
|
||||||
|
|
||||||
|
def add_command(name: str) -> argparse.ArgumentParser:
|
||||||
|
cmd = subs.add_parser(name)
|
||||||
|
cmd.set_defaults(cmd=name)
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
add_command("poll")
|
||||||
|
|
||||||
|
add_command("state")
|
||||||
|
|
||||||
|
cmd = add_command("bootloader")
|
||||||
|
cmd.add_argument("unit", type=int)
|
||||||
|
|
||||||
|
cmd = add_command("reboot")
|
||||||
|
cmd.add_argument("unit", type=int)
|
||||||
|
|
||||||
|
cmd = add_command("switch")
|
||||||
|
cmd.add_argument("unit", type=int)
|
||||||
|
cmd.add_argument("port", type=int, choices=list(range(5)))
|
||||||
|
|
||||||
|
cmd = add_command("beacon")
|
||||||
|
cmd.add_argument("unit", type=int)
|
||||||
|
cmd.add_argument("port", type=int, choices=list(range(6)))
|
||||||
|
cmd.add_argument("on", choices=["on", "off"])
|
||||||
|
|
||||||
|
add_command("leds")
|
||||||
|
|
||||||
|
cmd = add_command("click")
|
||||||
|
cmd.add_argument("button", choices=["power", "reset"])
|
||||||
|
cmd.add_argument("unit", type=int)
|
||||||
|
cmd.add_argument("port", type=int, choices=list(range(4)))
|
||||||
|
cmd.add_argument("delay_ms", type=int)
|
||||||
|
|
||||||
|
cmd = add_command("set-edid")
|
||||||
|
cmd.add_argument("unit", type=int)
|
||||||
|
cmd.add_argument("port", type=int, choices=list(range(4)))
|
||||||
|
cmd.add_argument("edid", type=_create_edid)
|
||||||
|
|
||||||
|
opts = parser.parse_args()
|
||||||
|
|
||||||
|
if not opts.device:
|
||||||
|
opts.device = _find_serial_device()
|
||||||
|
|
||||||
|
if opts.cmd == "bootloader" and opts.unit == 0:
|
||||||
|
if opts.device:
|
||||||
|
with Device(opts.device) as device:
|
||||||
|
device.request_reboot(opts.unit, bootloader=True)
|
||||||
|
found = _wait_boot_device()
|
||||||
|
if found:
|
||||||
|
print(found)
|
||||||
|
raise SystemExit()
|
||||||
|
raise SystemExit("Error: No switch found")
|
||||||
|
|
||||||
|
if not opts.device:
|
||||||
|
raise SystemExit("Error: No switch found")
|
||||||
|
|
||||||
|
with Device(opts.device) as device:
|
||||||
|
wait_rid: (int | None) = None
|
||||||
|
match opts.cmd:
|
||||||
|
case "poll":
|
||||||
|
device.request_state()
|
||||||
|
device.request_atx_leds()
|
||||||
|
case "state":
|
||||||
|
wait_rid = device.request_state()
|
||||||
|
case "bootloader" | "reboot":
|
||||||
|
device.request_reboot(opts.unit, (opts.cmd == "bootloader"))
|
||||||
|
raise SystemExit()
|
||||||
|
case "switch":
|
||||||
|
wait_rid = device.request_switch(opts.unit, opts.port)
|
||||||
|
case "leds":
|
||||||
|
wait_rid = device.request_atx_leds()
|
||||||
|
case "click":
|
||||||
|
match opts.button:
|
||||||
|
case "power":
|
||||||
|
wait_rid = device.request_atx_cp(opts.unit, opts.port, opts.delay_ms)
|
||||||
|
case "reset":
|
||||||
|
wait_rid = device.request_atx_cr(opts.unit, opts.port, opts.delay_ms)
|
||||||
|
case "beacon":
|
||||||
|
wait_rid = device.request_beacon(opts.unit, opts.port, (opts.on == "on"))
|
||||||
|
case "set-edid":
|
||||||
|
wait_rid = device.request_set_edid(opts.unit, opts.port, opts.edid)
|
||||||
|
|
||||||
|
error_ts = time.monotonic() + 1
|
||||||
|
while True:
|
||||||
|
for resp in device.read_all():
|
||||||
|
pprint.pprint((int(time.time()), resp))
|
||||||
|
print()
|
||||||
|
if resp.header.rid == wait_rid:
|
||||||
|
raise SystemExit()
|
||||||
|
if wait_rid is not None and time.monotonic() > error_ts:
|
||||||
|
raise SystemExit("No answer from unit")
|
||||||
24
kvmd/apps/swctl/__main__.py
Normal file
24
kvmd/apps/swctl/__main__.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# ========================================================================== #
|
||||||
|
# #
|
||||||
|
# KVMD - The main PiKVM daemon. #
|
||||||
|
# #
|
||||||
|
# Copyright (C) 2018-2024 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 . import main
|
||||||
|
main()
|
||||||
1
setup.py
1
setup.py
@ -94,6 +94,7 @@ def main() -> None:
|
|||||||
"kvmd.apps.otgnet",
|
"kvmd.apps.otgnet",
|
||||||
"kvmd.apps.otgmsd",
|
"kvmd.apps.otgmsd",
|
||||||
"kvmd.apps.otgconf",
|
"kvmd.apps.otgconf",
|
||||||
|
"kvmd.apps.swctl",
|
||||||
"kvmd.apps.htpasswd",
|
"kvmd.apps.htpasswd",
|
||||||
"kvmd.apps.totp",
|
"kvmd.apps.totp",
|
||||||
"kvmd.apps.edidconf",
|
"kvmd.apps.edidconf",
|
||||||
|
|||||||
15
switch/LICENSE
Normal file
15
switch/LICENSE
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
The PiKVM Switch Firmware
|
||||||
|
Copyright (C) 2024-2025
|
||||||
|
|
||||||
|
This software is distributed in binary form and is allowed for run only on original PiKVM Switch hardware.
|
||||||
|
|
||||||
|
Modifications are not allowed.
|
||||||
|
|
||||||
|
One day we will publish the source code, but not today.
|
||||||
|
|
||||||
|
=====
|
||||||
|
Includes other software related under other licenses:
|
||||||
|
- MIT: TinyUSB - Copyright (c) 2018, hathach (tinyusb.org).
|
||||||
|
- MIT: Pico-PIO-USB - Copyright (c) 2021 sekigon-gonnoc.
|
||||||
|
- BSD: Pico-SDK - Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
- BSD: FatFS - Copyright (C) 20xx, ChaN, all right reserved.
|
||||||
8
switch/Makefile
Normal file
8
switch/Makefile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
all:
|
||||||
|
@echo "Run 'make install'"
|
||||||
|
|
||||||
|
upload: install
|
||||||
|
install:
|
||||||
|
mount `python -m kvmd.apps.swctl bootloader 0` mnt
|
||||||
|
cp switch.uf2 mnt
|
||||||
|
umount mnt
|
||||||
1
switch/mnt/README
Normal file
1
switch/mnt/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
This is a mount point for the switch.
|
||||||
BIN
switch/switch.uf2
Normal file
BIN
switch/switch.uf2
Normal file
Binary file not shown.
@ -49,6 +49,7 @@ RUN pacman --noconfirm --ask=4 -Syy \
|
|||||||
python-pyotp \
|
python-pyotp \
|
||||||
python-qrcode \
|
python-qrcode \
|
||||||
python-pyserial \
|
python-pyserial \
|
||||||
|
python-pyudev \
|
||||||
python-setproctitle \
|
python-setproctitle \
|
||||||
python-psutil \
|
python-psutil \
|
||||||
python-netifaces \
|
python-netifaces \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user