mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 01:00:29 +08:00
ps/2 keyboard prototype
This commit is contained in:
parent
65bee96fef
commit
54430fed31
@ -8,7 +8,7 @@ kvmd:
|
||||
pinout:
|
||||
clock: 17
|
||||
data: 4
|
||||
delay: 0.0002
|
||||
pulse: 0.0002
|
||||
|
||||
atx:
|
||||
leds:
|
||||
|
||||
@ -5,6 +5,7 @@ from .application import init
|
||||
|
||||
from .atx import Atx
|
||||
from .streamer import Streamer
|
||||
from .ps2 import Ps2Keyboard
|
||||
from .server import Server
|
||||
|
||||
from . import gpio
|
||||
@ -33,9 +34,16 @@ def main() -> None:
|
||||
loop=loop,
|
||||
)
|
||||
|
||||
keyboard = Ps2Keyboard(
|
||||
clock=config["keyboard"]["pinout"]["clock"],
|
||||
data=config["keyboard"]["pinout"]["data"],
|
||||
pulse=config["keyboard"]["pulse"],
|
||||
)
|
||||
|
||||
Server(
|
||||
atx=atx,
|
||||
streamer=streamer,
|
||||
keyboard=keyboard,
|
||||
heartbeat=config["server"]["heartbeat"],
|
||||
atx_leds_poll=config["atx"]["leds"]["poll"],
|
||||
video_shutdown_delay=config["video"]["shutdown_delay"],
|
||||
|
||||
@ -24,8 +24,8 @@ class Atx:
|
||||
self.__power_led = gpio.set_input(power_led)
|
||||
self.__hdd_led = gpio.set_input(hdd_led)
|
||||
|
||||
self.__power_switch = gpio.set_output_zeroed(power_switch)
|
||||
self.__reset_switch = gpio.set_output_zeroed(reset_switch)
|
||||
self.__power_switch = gpio.set_output(power_switch)
|
||||
self.__reset_switch = gpio.set_output(reset_switch)
|
||||
self.__click_delay = click_delay
|
||||
self.__long_click_delay = long_click_delay
|
||||
|
||||
|
||||
@ -21,8 +21,8 @@ def bcm() -> Generator[None, None, None]:
|
||||
_logger.info("GPIO cleaned")
|
||||
|
||||
|
||||
def set_output_zeroed(pin: int) -> int:
|
||||
GPIO.setup(pin, GPIO.OUT)
|
||||
def set_output(pin: int, initial: bool=False) -> int:
|
||||
GPIO.setup(pin, GPIO.OUT, initial=initial)
|
||||
GPIO.output(pin, False)
|
||||
return pin
|
||||
|
||||
|
||||
63
kvmd/kvmd/ps2.py
Normal file
63
kvmd/kvmd/ps2.py
Normal file
@ -0,0 +1,63 @@
|
||||
import multiprocessing
|
||||
import multiprocessing.queues
|
||||
import queue
|
||||
import logging
|
||||
import time
|
||||
|
||||
from . import gpio
|
||||
|
||||
|
||||
# =====
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Ps2Keyboard(multiprocessing.Process):
|
||||
def __init__(self, clock: int, data: int, pulse: float) -> None:
|
||||
super().__init__(daemon=True)
|
||||
|
||||
self.__clock = gpio.set_output(clock, initial=True)
|
||||
self.__data = gpio.set_output(data, initial=True)
|
||||
self.__pulse = pulse
|
||||
|
||||
self.__queue: multiprocessing.queues.Queue = multiprocessing.Queue()
|
||||
self.__event = multiprocessing.Event()
|
||||
|
||||
def start(self) -> None:
|
||||
_logger.info("Starting keyboard daemon ...")
|
||||
super().start()
|
||||
|
||||
def stop(self) -> None:
|
||||
_logger.info("Stopping keyboard daemon ...")
|
||||
self.__event.set()
|
||||
self.join()
|
||||
|
||||
def send_byte(self, code: int) -> None:
|
||||
self.__queue.put(code)
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
while not self.__event.is_set():
|
||||
try:
|
||||
code = self.__queue.get(timeout=0.1)
|
||||
except queue.Empty:
|
||||
pass
|
||||
else:
|
||||
self.__send_byte(code)
|
||||
except Exception:
|
||||
_logger.exception("Unhandled exception")
|
||||
raise
|
||||
|
||||
def __send_byte(self, code: int) -> None:
|
||||
code_bits = list(map(bool, bin(code)[2:].zfill(8)))
|
||||
code_bits.reverse()
|
||||
message = [False] + code_bits + [(not sum(code_bits) % 2), True]
|
||||
for bit in message:
|
||||
self.__send_bit(bit)
|
||||
|
||||
def __send_bit(self, bit: bool) -> None:
|
||||
gpio.write(self.__clock, True)
|
||||
gpio.write(self.__data, bool(bit))
|
||||
time.sleep(self.__pulse)
|
||||
gpio.write(self.__clock, False)
|
||||
time.sleep(self.__pulse)
|
||||
gpio.write(self.__clock, True)
|
||||
@ -13,6 +13,7 @@ import aiohttp
|
||||
|
||||
from .atx import Atx
|
||||
from .streamer import Streamer
|
||||
from .ps2 import Ps2Keyboard
|
||||
|
||||
|
||||
# =====
|
||||
@ -36,6 +37,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
self,
|
||||
atx: Atx,
|
||||
streamer: Streamer,
|
||||
keyboard: Ps2Keyboard,
|
||||
heartbeat: float,
|
||||
atx_leds_poll: float,
|
||||
video_shutdown_delay: float,
|
||||
@ -45,6 +47,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
self.__atx = atx
|
||||
self.__streamer = streamer
|
||||
self.__heartbeat = heartbeat
|
||||
self.__keyboard = keyboard
|
||||
self.__video_shutdown_delay = video_shutdown_delay
|
||||
self.__atx_leds_poll = atx_leds_poll
|
||||
self.__loop = loop
|
||||
@ -55,6 +58,8 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
self.__system_tasks: List[asyncio.Task] = []
|
||||
|
||||
def run(self, host: str, port: int) -> None:
|
||||
self.__keyboard.start()
|
||||
|
||||
app = aiohttp.web.Application(loop=self.__loop)
|
||||
app.router.add_get("/", self.__root_handler)
|
||||
app.router.add_get("/ws", self.__ws_handler)
|
||||
@ -62,6 +67,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
app.on_cleanup.append(self.__on_cleanup)
|
||||
|
||||
self.__system_tasks.extend([
|
||||
self.__loop.create_task(self.__monitor_keyboard()),
|
||||
self.__loop.create_task(self.__stream_controller()),
|
||||
self.__loop.create_task(self.__poll_dead_sockets()),
|
||||
self.__loop.create_task(self.__poll_atx_leds()),
|
||||
@ -101,9 +107,17 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
await self.__remove_socket(ws)
|
||||
|
||||
async def __on_cleanup(self, _: aiohttp.web.Application) -> None:
|
||||
if self.__keyboard.is_alive():
|
||||
self.__keyboard.stop()
|
||||
if self.__streamer.is_running():
|
||||
await self.__streamer.stop()
|
||||
|
||||
@_system_task
|
||||
async def __monitor_keyboard(self) -> None:
|
||||
while self.__keyboard.is_alive():
|
||||
await asyncio.sleep(0.1)
|
||||
raise RuntimeError("Keyboard dead")
|
||||
|
||||
@_system_task
|
||||
async def __stream_controller(self) -> None:
|
||||
prev = 0
|
||||
|
||||
@ -22,8 +22,8 @@ class Streamer: # pylint: disable=too-many-instance-attributes
|
||||
loop: asyncio.AbstractEventLoop,
|
||||
) -> None:
|
||||
|
||||
self.__cap_power = gpio.set_output_zeroed(cap_power)
|
||||
self.__vga_power = gpio.set_output_zeroed(vga_power)
|
||||
self.__cap_power = gpio.set_output(cap_power)
|
||||
self.__vga_power = gpio.set_output(vga_power)
|
||||
self.__sync_delay = sync_delay
|
||||
|
||||
self.__cmd = (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user