#!/usr/bin/env python3 # cdc.py -- minimal host helper to talk to the c2probe CDC line protocol. # Uses termios (no pyserial). Usage: # ./cdc.py hello # ./cdc.py id2 # ./cdc.py "read 2400 16" # Sends one command, prints all reply lines until a known terminator/prompt. import sys, os, termios, tty, time, select DEV = os.environ.get("C2PROBE_DEV", "/dev/cu.usbmodem2101") def open_port(): fd = os.open(DEV, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) attrs = termios.tcgetattr(fd) attrs[2] = termios.CS8 | termios.CLOCAL | termios.CREAD # cflag attrs[3] = 0 # lflag: raw attrs[4] = termios.B115200 # ispeed attrs[5] = termios.B115200 # ospeed # no flow control, no special chars attrs[0] = 0; attrs[1] = 0 termios.tcsetattr(fd, termios.TCSANOW, attrs) return fd def drain(fd, t=0.15): r, _, _ = select.select([fd], [], [], t) if r: try: return os.read(fd, 4096).decode("utf-8", "replace") except BlockingIOError: return "" return "" def cmd(fd, line, timeout=3.0): os.write(fd, (line + "\n").encode()) out = "" end = time.time() + timeout while time.time() < end: r, _, _ = select.select([fd], [], [], 0.1) if r: try: out += os.read(fd, 4096).decode("utf-8", "replace") except BlockingIOError: pass # stop once we have at least one complete line and the port goes quiet if "\n" in out: # give a short quiet window for any trailing lines r2, _, _ = select.select([fd], [], [], 0.08) if not r2: break return out if __name__ == "__main__": line = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "hello" fd = open_port() drain(fd, 0.3) # drop any startup/banner print(cmd(fd, line), end="") os.close(fd)