add logging capability

This commit is contained in:
xenia 2021-05-20 00:14:53 -04:00
parent c760bf2fb3
commit fb64863bbe
2 changed files with 39 additions and 15 deletions

View File

@ -49,6 +49,12 @@ CTRL-A is the escape character. CTRL-A + Q quits megacom. CTRL-A + CTRL-A sends
there will be more keyboard shortcuts later, hopefully there will be more keyboard shortcuts later, hopefully
### non-tty mode
megacom can be run even if stdin is not a tty. in this mode, keyboard shortcuts (CTRL-A) are
disabled and input is passed through verbatim. this can be useful to pipe input and output out of a
UART device with programs that are not tty-aware
### baud ### baud
any standard baud rate (as an integer) which is supported by pyserial can be used. usually you want any standard baud rate (as an integer) which is supported by pyserial can be used. usually you want

View File

@ -2,6 +2,8 @@ import argparse
import asyncio import asyncio
import contextlib import contextlib
import errno import errno
import fcntl
import os
import re import re
import signal import signal
import sys import sys
@ -31,29 +33,39 @@ MODE_LOOKUP = {
class TtyRaw: class TtyRaw:
__slots__ = ["isatty", "fd", "settings"] __slots__ = ["isatty", "infd", "outfd", "settings"]
isatty: bool isatty: bool
fd: int infd: int
outfd: int
settings: List[Any] settings: List[Any]
def __init__(self) -> None: def __init__(self) -> None:
self.isatty = False self.isatty = False
self.fd = 0 self.infd = 0
self.outfd = 0
self.settings = [] self.settings = []
def __enter__(self) -> None: def __enter__(self) -> 'TtyRaw':
if sys.stdin.isatty(): if sys.stdin.isatty():
self.isatty = True self.isatty = True
self.fd = sys.stdin.fileno() self.infd = sys.stdin.fileno()
self.settings = termios.tcgetattr(self.fd) self.outfd = sys.stdout.fileno()
tty.setraw(self.fd) self.settings = termios.tcgetattr(self.infd)
return None tty.setraw(self.infd)
return self
def __exit__(self, exc_type: Optional[Type[BaseException]], def __exit__(self, exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException], exc_value: Optional[BaseException],
exc_traceback: Optional[TracebackType]) -> Literal[False]: exc_traceback: Optional[TracebackType]) -> Literal[False]:
if self.isatty: if self.isatty:
termios.tcsetattr(self.fd, termios.TCSADRAIN, self.settings) termios.tcsetattr(self.infd, termios.TCSADRAIN, self.settings)
# unset nonblocking modes
flags = fcntl.fcntl(self.infd, fcntl.F_GETFL)
flags = flags & (~os.O_NONBLOCK)
fcntl.fcntl(self.infd, fcntl.F_SETFL, flags)
flags = fcntl.fcntl(self.outfd, fcntl.F_GETFL)
flags = flags & (~os.O_NONBLOCK)
fcntl.fcntl(self.outfd, fcntl.F_SETFL, flags)
return False return False
@ -74,15 +86,21 @@ ESC_CHAR = b"\x01"
class KeycodeHandler: class KeycodeHandler:
__slots__ = ["exit_flag", "esc"] __slots__ = ["exit_flag", "esc", "isatty"]
exit_flag: asyncio.Event exit_flag: asyncio.Event
esc: bool esc: bool
isatty: bool
def __init__(self) -> None: def __init__(self, isatty: bool) -> None:
self.exit_flag = asyncio.Event() self.exit_flag = asyncio.Event()
self.esc = False self.esc = False
self.isatty = isatty
def process(self, byte: bytes) -> bytes: def process(self, byte: bytes) -> bytes:
# only translate or eat input if stdin is actually a tty
if not self.isatty:
return byte
if self.esc: if self.esc:
self.esc = False self.esc = False
if byte == b"q": if byte == b"q":
@ -104,7 +122,7 @@ class KeycodeHandler:
return byte return byte
async def megacom(tty: str, baud: int, mode: str, logfile: Optional[str]) -> None: async def megacom(ttyraw: TtyRaw, tty: str, baud: int, mode: str, logfile: Optional[str]) -> None:
(stdin, stdout) = await setup_async() (stdin, stdout) = await setup_async()
m = MODE_RE.match(mode) m = MODE_RE.match(mode)
@ -124,7 +142,7 @@ async def megacom(tty: str, baud: int, mode: str, logfile: Optional[str]) -> Non
sys.exit(1) sys.exit(1)
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
keycodes = KeycodeHandler() keycodes = KeycodeHandler(ttyraw.isatty)
loop.add_signal_handler(signal.SIGINT, lambda: keycodes.exit_flag.set()) loop.add_signal_handler(signal.SIGINT, lambda: keycodes.exit_flag.set())
@ -268,6 +286,6 @@ def main() -> None:
parser.add_argument("-l", "--logfile", type=str, default="", help="file to log to") parser.add_argument("-l", "--logfile", type=str, default="", help="file to log to")
args = parser.parse_args() args = parser.parse_args()
with TtyRaw(): with TtyRaw() as ttyraw:
asyncio.run(megacom(args.tty, args.baud, args.mode, asyncio.run(megacom(ttyraw, args.tty, args.baud, args.mode,
args.logfile if args.logfile != "" else None)) args.logfile if args.logfile != "" else None))