1
- from cStringIO import StringIO
2
1
from struct import pack , unpack , calcsize
3
2
from zlib import crc32
4
3
from time import sleep
@@ -488,13 +487,24 @@ def download(self, firmware, blocknum=None):
488
487
sleep (timeout / 1000 )
489
488
return blocknum
490
489
491
- def upload (self , blocknum , length ):
490
+ def upload (self , length , blocknum = None ):
491
+ blocknum = self .getNextBlockNumber (blocknum )
492
492
if self .__has_stm_extensions and blocknum < 2 :
493
493
raise ValueError ('upload must not be called with blocknum < 2 '
494
494
'on devices supporting STM extensions' )
495
- result = self ._controlRead (DFU_UPLOAD , blocknum , length )
496
- self .checkStatus ()
497
- return result
495
+ try :
496
+ result = self ._controlRead (DFU_UPLOAD , blocknum , length )
497
+ self .checkStatus ()
498
+ except Exception :
499
+ exc_info = sys .exc_info ()
500
+ try :
501
+ self .abort ()
502
+ except Exception :
503
+ raise DoubleException (
504
+ '' .join (traceback .format_exception (* exc_info )),
505
+ traceback .format_exc ())
506
+ raise exc_info [0 ], exc_info [1 ], exc_info [2 ]
507
+ return result , blocknum
498
508
499
509
def getStatus (self ):
500
510
status , timeout , timeout_upper , state , status_descriptor = unpack (
@@ -582,6 +592,9 @@ def _parseFieldList(data, field_list):
582
592
if not data :
583
593
break
584
594
return result
595
+ def _generateFieldList (data_dict , field_list ):
596
+ return pack ('' .join (x [1 ] for x in field_list ),
597
+ * [data_dict [x [0 ]] for x in field_list ])
585
598
586
599
class DFU (object ):
587
600
def __init__ (self , handle ):
@@ -672,12 +685,8 @@ def _download(self, data):
672
685
blocknum = download (data [:transfer_size ], blocknum )
673
686
data = data [transfer_size :]
674
687
675
- def upload (self ):
676
- data = StringIO ()
677
- self .uploadStream (data )
678
- return data .getvalue ()
679
-
680
- def uploadStream (self , stream ):
688
+ def upload (self , vendor_specific = True , product_specific = True ,
689
+ version = 0xffff , stm_format = False ):
681
690
iface = self .__dfu_interface
682
691
if not iface .canUpload ():
683
692
raise DFUUnsupportedError ('Cannot upload' )
@@ -688,54 +697,48 @@ def uploadStream(self, stream):
688
697
state = iface .getState ()
689
698
if state != DFU_STATE_DFU_IDLE :
690
699
raise DFUBadSate (state )
691
- write = stream . write
700
+ result = ''
692
701
iface_upload = iface .upload
693
702
transfer_size = iface .getTransferSize ()
694
703
checkStatus = iface .checkStatus
695
704
abort = iface .abort
696
- if iface .hasSTExtensions ():
697
- def upload ():
698
- # TODO: create a valid DfuSe file.
699
- getNextBlockNumber = iface .getNextSTBlockNumber
700
- setAddress = iface .STM_setAddress
701
- for chunk in iface .STM_getDeviceMappingList ():
702
- setAddress (chunk ['address' ])
703
- import pdb ; pdb .set_trace ()
704
- blocknum = None
705
- for sector in chunk ['sectors' ]:
706
- if not sector ['mode' ] & DFU_ST_SECTOR_MODE_R :
707
- continue
708
- remain = sector ['count' ] * sector ['size' ]
709
- while remain :
710
- blocknum = getNextBlockNumber (blocknum )
711
- data = iface_upload (blocknum , min (transfer_size ,
712
- remain ))
713
- checkStatus ()
714
- write (data )
715
- remain -= len (data )
716
- assert remain >= 0 , remain
717
- abort ()
718
- else :
719
- def upload ():
720
- getNextBlockNumber = iface .getNextStandardBlockNumber
705
+ if stm_format and iface .hasSTMExtensions ():
706
+ # Untested/unfinished code ahead, raise.
707
+ raise NotImplementedError
708
+ # TODO: create a valid DfuSe file.
709
+ setAddress = iface .STM_setAddress
710
+ for chunk in iface .STM_getDeviceMappingList ():
711
+ setAddress (chunk ['address' ])
721
712
blocknum = None
722
- while True :
723
- blocknum = getNextBlockNumber (blocknum )
724
- data = iface_upload (blocknum , transfer_size )
725
- checkStatus ()
726
- write (data )
727
- if len (data ) < transfer_size :
728
- break
729
- abort ()
730
- try :
731
- upload ()
732
- except :
733
- exc_info = sys .exc_info ()
734
- try :
735
- abort ()
736
- except :
737
- raise DoubleException (
738
- '' .join (traceback .format_exception (* exc_info )),
739
- traceback .format_exc ())
740
- raise exc_info [0 ], exc_info [1 ], exc_info [2 ]
713
+ for sector in chunk ['sectors' ]:
714
+ if not sector ['mode' ] & DFU_ST_SECTOR_MODE_R :
715
+ continue
716
+ remain = sector ['count' ] * sector ['size' ]
717
+ while len (result ) < remain :
718
+ data , blocknum = iface_upload (min (transfer_size ,
719
+ remain ), blocknum )
720
+ checkStatus ()
721
+ result += data
722
+ assert remain == len (result ), (remain , len (result ))
723
+ abort ()
724
+ else :
725
+ blocknum = None
726
+ while True :
727
+ data , blocknum = iface_upload (transfer_size , blocknum )
728
+ result += data
729
+ if len (data ) < transfer_size :
730
+ break
731
+ abort ()
732
+ # Add defuse tail
733
+ device = self .__handle .getDevice ()
734
+ tail = _generateFieldList ({
735
+ 'dfu_version' : 0x110 ,
736
+ 'vendor' : vendor_specific and device .getVendorID () or 0xffff ,
737
+ 'product' : product_specific and device .getProductID () or 0xffff ,
738
+ 'device' : version ,
739
+ }, DFU_SUFFIX_FIELD_LIST )
740
+ data += '' .join (reversed (tail )) + 'UFD' + \
741
+ chr (len (tail ) + DFU_SUFFIX_BASE_LENGTH )
742
+ data += pack ('<I' , crc32 (data ))
743
+ return data
741
744
0 commit comments