blob: b7c21e617d8342c997eee9487f3cab177e71babc [file] [log] [blame]
#!/usr/bin/python3
import argparse
import sys
import socket
# https://github.com/ntfreak/openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt
class Tap:
def __init__(self, port):
self.port = port
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect(("localhost", port))
def execute(self, commands):
sent = self.socket.send(commands)
assert len(commands) == sent
read_count = 0
for command in commands:
if command == ord('R'):
read_count += 1
result = b""
while len(result) < read_count:
result += self.socket.recv(read_count - len(result))
assert len(result) == read_count
return result
class Chain:
def __init__(self, debug=False):
self.debug = debug
self.taps = []
def append(self, tap):
self.taps.append(tap)
def execute(self, commands):
values = []
for i, tap in enumerate(self.taps):
tmp_commands = []
for command in commands:
if i > 0 and ord('0') <= command <= ord('7'):
# Replace TDI with the value from the previous TAP.
v = values.pop(0)
command &= 0xfe
if v == ord('1'):
command |= 1
if i < len(self.taps) - 1:
if command != ord('R'):
tmp_commands.append(command)
if ord('0') <= command <= ord('7'):
# Read TDO before every scan.
tmp_commands.append(ord('R'))
else:
tmp_commands.append(command)
assert len(values) == 0
values = list(tap.execute(bytes(tmp_commands)))
if self.debug:
sys.stdout.write(" %d %r -> %r\n" % (i, bytes(tmp_commands),
bytes(values)))
return bytes(values)
def main():
parser = argparse.ArgumentParser(
description='Combine multiple remote_bitbang processes into a '
'single scan-chain.')
parser.add_argument("listen_port", type=int,
help="port to listen on")
parser.add_argument("tap_port", nargs="+", type=int,
help="port of a remote_bitbang TAP to connect to")
parser.add_argument("--debug", action='store_true',
help="Print out debug messages.")
args = parser.parse_args()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", args.listen_port))
server.listen(1)
chain = Chain(args.debug)
for port in args.tap_port:
chain.append(Tap(port))
sys.stdout.write("Listening on port %d.\n" % server.getsockname()[1])
sys.stdout.flush()
while True:
(client, _) = server.accept()
while True:
try:
commands = client.recv(4096)
except (ConnectionResetError, OSError):
sys.stdout.write("Client disconnected due to exception.\n")
break
if len(commands) == 0:
sys.stdout.write("Client disconnected.\n")
break
if args.debug:
sys.stdout.write("%r\n" % commands)
result = chain.execute(commands)
if args.debug:
sys.stdout.write(" -> %r\n" % result)
client.send(result)
client.close()
sys.stdout.flush()
if __name__ == '__main__':
sys.exit(main())