3 # Contains class definitions for Facedancer, FacedancerCommand, FacedancerApp,
4 # and GoodFETMonitorApp.
9 def __init__(self, serialport, verbose=0):
10 self.serialport = serialport
11 self.verbose = verbose
14 self.monitor_app = GoodFETMonitorApp(self, verbose=self.verbose)
15 self.monitor_app.announce_connected()
18 self.serialport.setRTS(1)
19 self.serialport.setDTR(1)
23 print("Facedancer resetting...")
26 self.serialport.setDTR(0)
31 print("Facedancer reset")
36 b = self.serialport.read(n)
39 print("Facedancer received", len(b), "bytes;",
40 self.serialport.inWaiting(), "bytes remaining")
43 print("Facedancer Rx:", bytes_as_hex(b))
48 """Read a single command."""
54 n = b[2] + (b[3] << 8)
62 raise ValueError('Facedancer expected ' + str(n) \
63 + ' bytes but received only ' + str(len(data)))
65 cmd = FacedancerCommand(app, verb, data)
68 print("Facedancer Rx command:", cmd)
73 """Write raw bytes."""
76 print("Facedancer Tx:", bytes_as_hex(b))
78 self.serialport.write(b)
80 def writecmd(self, c):
81 """Write a single command."""
82 self.write(c.as_bytestring())
85 print("Facedancer Tx command:", c)
88 class FacedancerCommand:
89 def __init__(self, app=None, verb=None, data=None):
95 s = "app 0x%02x, verb 0x%02x, len %d" % (self.app, self.verb,
98 if len(self.data) > 0:
99 s += ", data " + bytes_as_hex(self.data)
103 def long_string(self):
104 s = "app: " + str(self.app) + "\n" \
105 + "verb: " + str(self.verb) + "\n" \
106 + "len: " + str(len(self.data))
108 if len(self.data) > 0:
110 s += "\n" + self.data.decode("utf-8")
111 except UnicodeDecodeError:
112 s += "\n" + bytes_as_hex(self.data)
116 def as_bytestring(self):
130 app_name = "override this"
133 def __init__(self, device, verbose=0):
135 self.verbose = verbose
140 print(self.app_name, "initialized")
142 def init_commands(self):
147 self.device.writecmd(self.enable_app_cmd)
148 self.device.readcmd()
151 print(self.app_name, "enabled")
154 class GoodFETMonitorApp(FacedancerApp):
155 app_name = "GoodFET monitor"
158 def read_byte(self, addr):
159 d = [ addr & 0xff, addr >> 8 ]
160 cmd = FacedancerCommand(0, 2, d)
162 self.device.writecmd(cmd)
163 resp = self.device.readcmd()
167 def get_infostring(self):
168 return bytes([ self.read_byte(0xff0), self.read_byte(0xff1) ])
170 def get_clocking(self):
171 return bytes([ self.read_byte(0x57), self.read_byte(0x56) ])
173 def print_info(self):
174 infostring = self.get_infostring()
175 clocking = self.get_clocking()
177 print("MCU", bytes_as_hex(infostring, delim=""))
178 print("clocked at", bytes_as_hex(clocking, delim=""))
181 cmd = FacedancerCommand(self.app_num, 0x82, b'0x0')
182 self.device.writecmd(cmd)
184 resp = self.device.readcmd()
185 print("build date:", resp.data.decode("utf-8"))
187 print("firmware apps:")
189 resp = self.device.readcmd()
190 if len(resp.data) == 0:
192 print(resp.data.decode("utf-8"))
195 b = bytes(s, encoding="utf-8")
197 cmd = FacedancerCommand(self.app_num, 0x81, b)
198 self.device.writecmd(cmd)
200 resp = self.device.readcmd()
202 return resp.data == b
204 def announce_connected(self):
205 cmd = FacedancerCommand(self.app_num, 0xb1, b'')
206 self.device.writecmd(cmd)
207 resp = self.device.readcmd()