| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- #!/usr/bin/env python3
- import dfudfuse
- import usb.core
- import usb.util
- import argparse
- import sys
- import parse
- class Firmware:
- def __init__(self, vid, pid, cfg, intf, alternate):
- self.mmaps = list()
- self.usbdev = usb.core.find(idVendor = vid, idProduct = pid)
- if self.usbdev is not None:
- self.dfu = dfuse.DfuDevice(self.usbdev)
- mmap_str = usb.util.get_string(self.usbdev, self.dfu.cfg[(0,0)].iInterface)
- mmap = parse.parse('{name}/{address:x}/{regions}',mmap_str)
- self.address = mmap['address']
- for m in mmap['regions'].split(','):
- map = dict(zip(['sectors','sec_size','unit','flag'], parse.parse('{:d}*{:d}{:1}{:1}', m)))
- self.mmaps.append(map)
- for _,alt in self.dfu.alternates():
- if alt.configuration == cfg and alt.bInterfaceNumber == intf and alt.bAlternateSetting == alternate:
- self.dfu.set_alternate(alt)
- status = self.dfu.get_status()
- if status[1] == dfuse.DfuState.DFU_ERROR:
- # print("Error cleared: %r" % (status,))
- self.dfu.clear_status() # Clear left-over errors
- return
- raise ValueError('No DfuSe compatible device found, check device information options (see --help)')
- def erase(self, address):
- print ("Erasing. Please wait this might be long ...")
- """
- dfu.erase(args.erase)
- status = dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
- if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
- raise RuntimeError("An error occured. Device Status: %r" % status)
- """
- for i in range(0, 1280):
- print("Erasing page %r" % i)
- self.dfu.erase(address + i * size)
- status = self.dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
- if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
- raise RuntimeError("An error occured. Device Status: %r" % status)
- print ("Done !")
- def leave_dfu(args):
- dfu = find_device(args)
- dfu.leave()
- status = dfu.get_status()
- # if status[0] > 0:
- # raise RuntimeError("An error occured. Status: %r" % status)
- def flash(dfufile):
- if (dfufile.devInfo['vid'] != dfu.dev.idVendor or dfufile.devInfo['pid'] != self.dfu.dev.idProduct):
- raise ValueError("Vendor/Product id mismatch: [%.4x:%.4x] (file) [%.4x:%.4x] (device). Trying running with --force" % ( \
- dfufile.devInfo['vid'], \
- dfufile.devInfo['vid'], \
- self.dfu.dev.idVendor, \
- self.dfu.dev.idProduct))
- targets = [t for t in dfufile.targets if t['alternate'] == self.dfu.intf.bAlternateSetting]
- if len(targets) == 0:
- raise ValueError("No file target matches the device. Check the --alt setting")
- print ("Flashing. Please wait this might be long ...")
- for t in targets:
- print(self.dfu.alternates()[0][0])
- return
- print ("Found target %r" % t['name'])
- for idx, image in enumerate(t['elements']):
- print("Flashing image %d at 0x%.8X" % (idx, image['address']))
- print("Flashing ...")
- transfer_size = 1024
- self.dfu.set_address(image['address'])
- status = self.dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
- if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
- raise RuntimeError("An error occured. Device Status: %r" % status)
-
- data = image['data']
- blocks = [data[i:i + transfer_size] for i in range(0, len(data), transfer_size)]
- for blocknum, block in enumerate(blocks):
- print("Flashing block %r" % blocknum)
- self.dfu.write(blocknum, block)
- status = self.dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
- if status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
- raise RuntimeError("An error occured. Device Status: %r" % status)
- print("Done")
- return
- status = self.dfu.wait_while_state(dfuse.DfuState.DFU_DOWNLOAD_BUSY)
- if status[1] != dfuse.DfuState.DFU_IDLE and status[1] != dfuse.DfuState.DFU_DOWNLOAD_IDLE:
- raise RuntimeError("An error occured. Status: %r" % status)
- print ("Done !")
|