1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#!/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()
text = out.decode(errors="replace")
if text.startswith("err"): # make failures loud and scriptable
sys.stderr.write(text)
sys.exit(1)
sys.stdout.write(text)
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()
|