#!/usr/bin/env python3 """gbtype - inject shell input into a running gbhub Game Boy, no OSK needed. The Game Boy's link port *is* its console when nothing SLIP-frames the bytes, so text sent over the hub's control socket lands straight on the shell's stdin - exactly as if typed on the on-screen keyboard, but driven from your host. Start the hub first (in another terminal): sudo tools/gbhub --daemon tools/gbtype 'ls -l' run 'ls -l' on GB0 (a trailing Enter is added) tools/gbtype -g 1 ps target GB1 (the Nth joined Game Boy) tools/gbtype -n abc type 'abc' but no Enter (leave it on the line) tools/gbtype -r just press Enter tools/gbtype -l list the connected Game Boys printf 'ls\\ncat readme\\n' | tools/gbtype pipe a script via stdin Options must come before the command; the first non-option word starts the literal text (so 'gbtype ls -l' needs no quoting, and '-l' there is not --list). No root needed - the hub opens the control socket world-connectable.""" import os, sys, socket CTL = "/tmp/gbhub.ctl" def usage(code=0): (sys.stdout if code == 0 else sys.stderr).write(__doc__ + "\n") sys.exit(code) def send(header, payload=b""): if not os.path.exists(CTL): sys.exit("gbtype: no hub control socket at %s\n" " start it first: sudo tools/gbhub --daemon" % CTL) s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: s.connect(CTL) except OSError as e: sys.exit("gbtype: cannot connect %s (%s)" % (CTL, e)) s.sendall(header + b"\n" + payload) s.shutdown(socket.SHUT_WR) # end-of-payload marker for the hub out = b"" while True: try: d = s.recv(4096) except Exception: break if not d: break out += d s.close() sys.stdout.write(out.decode(errors="replace")) def main(): args = sys.argv[1:] idx = None newline = True i = 0 while i < len(args): a = args[i] if a in ("-h", "--help"): usage(0) elif a in ("-l", "--list"): send(b"list"); return elif a in ("-g", "--gb"): i += 1 if i >= len(args): usage(1) idx = args[i] elif a in ("-n", "--no-enter"): newline = False elif a in ("-r", "--enter"): send(b"type" + (b" " + idx.encode() if idx else b""), b"\n"); return elif a == "--": i += 1; break elif a.startswith("-") and len(a) > 1: sys.stderr.write("gbtype: unknown option %s\n" % a); usage(1) else: break # first positional: rest is literal text i += 1 words = args[i:] if words: payload = " ".join(words).encode() + (b"\n" if newline else b"") else: payload = sys.stdin.buffer.read() # piped script, sent verbatim if newline and payload and not payload.endswith(b"\n"): payload += b"\n" send(b"type" + (b" " + idx.encode() if idx is not None else b""), payload) if __name__ == "__main__": main()