#!/usr/bin/python # Written by Antonio Galea - 2010/11/18 # Updated for DFU 1.1 by Sean Cross - 2020/03/31 # Distributed under Gnu LGPL 3.0 # see http://www.gnu.org/licenses/lgpl-3.0.txt import sys,struct,zlib,os from optparse import OptionParser DEFAULT_DEVICE="0x1209:0x5bf0" def named(tuple,names): return dict(zip(names.split(),tuple)) def consume(fmt,data,names): n = struct.calcsize(fmt) return named(struct.unpack(fmt,data[:n]),names),data[n:] def cstring(string): return string.split('\0',1)[0] def compute_crc(data): return 0xFFFFFFFF & -zlib.crc32(data) -1 def parse(file,dump_images=False): print ('File: "%s"' % file) data = open(file,'rb').read() crc = compute_crc(data[:-4]) data = data[len(data)-16:] suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') print ('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) if crc != suffix['crc']: print ("CRC ERROR: computed crc32 is 0x%08x" % crc) data = data[16:] if data: print ("PARSE ERROR") def build(file,data,device=DEFAULT_DEVICE): # Parse the VID and PID from the `device` argument v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) # Generate the DFU suffix, consisting of these fields: # Field name | Length | Description # ================+=========+================================ # bcdDevice | 2 | The release number of this firmware (0xffff - don't care) # idProduct | 2 | PID of this device # idVendor | 2 | VID of this device # bcdDFU | 2 | Version of this DFU spec (0x01 0x00) # ucDfuSignature | 3 | The characters 'DFU', printed in reverse order # bLength | 1 | The length of this suffix (16 bytes) # dwCRC | 4 | A CRC32 of the data, including this suffix data += struct.pack('<4H3sB',0xffff,d,v,0x0100,b'UFD',16) crc = compute_crc(data) # Append the CRC32 of the entire block data += struct.pack('