2014-06-08 15:16:44 +00:00
/ *
USB DFU uses :
control transfers for communicating
recipient is interface
request type is class
2014-06-09 21:29:36 +00:00
Descriptors seems to be broken in current chrome . usb API implementation ( writing this while using canary 37.0 . 2040.0
General rule to remember is that DFU doesn 't like running specific operations while the device isn' t in idle state
that being said , it seems that certain level of CLRSTATUS is required before running another type of operation for
example switching from DNLOAD to UPLOAD , etc , clearning the state so device is in dfuIDLE is highly recommended .
2014-06-08 15:16:44 +00:00
* /
2014-08-09 18:47:07 +00:00
'use strict' ;
2014-06-08 15:16:44 +00:00
2014-08-14 15:00:32 +00:00
var STM32DFU _protocol = function ( ) {
2014-10-01 13:55:11 +00:00
this . callback ; // ref
2014-06-08 15:16:44 +00:00
this . hex ; // ref
this . verify _hex ;
this . handle = null ; // connection handle
2014-06-08 15:42:02 +00:00
this . request = {
2014-06-08 15:16:44 +00:00
DETACH : 0x00 , // OUT, Requests the device to leave DFU mode and enter the application.
DNLOAD : 0x01 , // OUT, Requests data transfer from Host to the device in order to load them into device internal Flash. Includes also erase commands
UPLOAD : 0x02 , // IN, Requests data transfer from device to Host in order to load content of device internal Flash into a Host file.
GETSTATUS : 0x03 , // IN, Requests device to send status report to the Host (including status resulting from the last request execution and the state the device will enter immediately after this request).
CLRSTATUS : 0x04 , // OUT, Requests device to clear error status and move to next step
GETSTATE : 0x05 , // IN, Requests the device to send only the state it will enter immediately after this request.
ABORT : 0x06 // OUT, Requests device to exit the current state/operation and enter idle state immediately.
} ;
this . status = {
OK : 0x00 , // No error condition is present.
errTARGET : 0x01 , // File is not targeted for use by this device.
errFILE : 0x02 , // File is for this device but fails some vendor-specific verification test
errWRITE : 0x03 , // Device is unable to write memory.
errERASE : 0x04 , // Memory erase function failed.
errCHECK _ERASED : 0x05 , // Memory erase check failed.
errPROG : 0x06 , // Program memory function failed.
errVERIFY : 0x07 , // Programmed memory failed verification.
errADDRESS : 0x08 , // Cannot program memory due to received address that is out of range.
errNOTDONE : 0x09 , // Received DFU_DNLOAD with wLength = 0, but device does not think it has all of the data yet.
errFIRMWARE : 0x0A , // Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations.
errVENDOR : 0x0B , // iString indicates a vendor-specific error.
errUSBR : 0x0C , // Device detected unexpected USB reset signaling.
errPOR : 0x0D , // Device detected unexpected power on reset.
errUNKNOWN : 0x0E , // Something went wrong, but the device does not know what it was.
errSTALLEDPKT : 0x0F // Device stalled an unexpected request.
} ;
this . state = {
appIDLE : 0 , // Device is running its normal application.
appDETACH : 1 , // Device is running its normal application, has received the DFU_DETACH request, and is waiting for a USB reset.
dfuIDLE : 2 , // Device is operating in the DFU mode and is waiting for requests.
dfuDNLOAD _SYNC : 3 , // Device has received a block and is waiting for the host to solicit the status via DFU_GETSTATUS.
dfuDNBUSY : 4 , // Device is programming a control-write block into its nonvolatile memories.
dfuDNLOAD _IDLE : 5 , // Device is processing a download operation. Expecting DFU_DNLOAD requests.
dfuMANIFEST _SYNC : 6 , // Device has received the final block of firmware from the host and is waiting for receipt of DFU_GETSTATUS to begin the Manifestation phase; or device has completed the Manifestation phase and is waiting for receipt of DFU_GETSTATUS.
dfuMANIFEST : 7 , // Device is in the Manifestation phase. (Not all devices will be able to respond to DFU_GETSTATUS when in this state.)
dfuMANIFEST _WAIT _RESET : 8 , // Device has programmed its memories and is waiting for a USB reset or a power on reset. (Devices that must enter this state clear bitManifestationTolerant to 0.)
dfuUPLOAD _IDLE : 9 , // The device is processing an upload operation. Expecting DFU_UPLOAD requests.
dfuERROR : 10 // An error has occurred. Awaiting the DFU_CLRSTATUS request.
} ;
} ;
2014-10-01 13:55:11 +00:00
STM32DFU _protocol . prototype . connect = function ( device , hex , callback ) {
2014-06-08 18:10:07 +00:00
var self = this ;
self . hex = hex ;
2014-10-01 13:55:11 +00:00
self . callback = callback ;
2014-06-08 18:26:28 +00:00
2014-06-08 21:44:06 +00:00
// reset and set some variables before we start
2014-10-01 13:55:11 +00:00
self . upload _time _start = new Date ( ) . getTime ( ) ;
2014-06-08 21:44:06 +00:00
self . verify _hex = [ ] ;
// reset progress bar to initial state
self . progress _bar _e = $ ( '.progress' ) ;
self . progress _bar _e . val ( 0 ) ;
self . progress _bar _e . removeClass ( 'valid invalid' ) ;
2014-08-14 15:00:32 +00:00
chrome . usb . getDevices ( device , function ( result ) {
2014-06-08 18:26:28 +00:00
if ( result . length ) {
console . log ( 'USB DFU detected with ID: ' + result [ 0 ] . device ) ;
self . openDevice ( result [ 0 ] ) ;
} else {
2014-07-22 12:16:09 +00:00
console . log ( 'USB DFU not found' ) ;
GUI . log ( 'USB DFU not found' ) ;
2014-06-08 18:26:28 +00:00
}
} ) ;
2014-06-08 18:10:07 +00:00
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . openDevice = function ( device ) {
2014-06-08 18:26:28 +00:00
var self = this ;
2014-08-14 15:00:32 +00:00
chrome . usb . openDevice ( device , function ( handle ) {
2014-06-08 18:26:28 +00:00
self . handle = handle ;
2014-06-08 19:15:12 +00:00
console . log ( 'Device opened with Handle ID: ' + handle . handle ) ;
2014-06-08 18:26:28 +00:00
self . claimInterface ( 0 ) ;
} ) ;
2014-06-08 15:16:44 +00:00
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . closeDevice = function ( ) {
2014-06-08 19:15:12 +00:00
var self = this ;
chrome . usb . closeDevice ( this . handle , function closed ( ) {
console . log ( 'Device closed with Handle ID: ' + self . handle . handle ) ;
self . handle = null ;
} ) ;
2014-06-08 15:16:44 +00:00
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . claimInterface = function ( interfaceNumber ) {
2014-06-08 19:15:12 +00:00
var self = this ;
2014-06-08 18:26:28 +00:00
chrome . usb . claimInterface ( this . handle , interfaceNumber , function claimed ( ) {
console . log ( 'Claimed interface: ' + interfaceNumber ) ;
2014-06-08 19:15:12 +00:00
self . upload _procedure ( 1 ) ;
2014-06-08 18:26:28 +00:00
} ) ;
2014-06-08 15:16:44 +00:00
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . releaseInterface = function ( interfaceNumber ) {
2014-06-08 19:15:12 +00:00
var self = this ;
chrome . usb . releaseInterface ( this . handle , interfaceNumber , function released ( ) {
console . log ( 'Released interface: ' + interfaceNumber ) ;
self . closeDevice ( ) ;
} ) ;
2014-06-08 15:16:44 +00:00
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . resetDevice = function ( callback ) {
chrome . usb . resetDevice ( this . handle , function ( result ) {
2014-06-08 15:16:44 +00:00
console . log ( 'Reset Device: ' + result ) ;
if ( callback ) callback ( ) ;
} ) ;
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . controlTransfer = function ( direction , request , value , _interface , length , data , callback ) {
2014-06-08 15:42:02 +00:00
if ( direction == 'in' ) {
// data is ignored
chrome . usb . controlTransfer ( this . handle , {
'direction' : 'in' ,
'recipient' : 'interface' ,
'requestType' : 'class' ,
'request' : request ,
'value' : value ,
2014-08-09 18:47:07 +00:00
'index' : _interface ,
2014-06-08 15:42:02 +00:00
'length' : length
2014-08-14 15:00:32 +00:00
} , function ( result ) {
2014-06-08 19:15:12 +00:00
if ( result . resultCode ) console . log ( result . resultCode ) ;
var buf = new Uint8Array ( result . data ) ;
2014-06-09 15:47:41 +00:00
callback ( buf , result . resultCode ) ;
2014-06-08 19:15:12 +00:00
} ) ;
2014-06-08 15:42:02 +00:00
} else {
// length is ignored
if ( data ) {
var arrayBuf = new ArrayBuffer ( data . length ) ;
var arrayBufView = new Uint8Array ( arrayBuf ) ;
arrayBufView . set ( data ) ;
} else {
var arrayBuf = new ArrayBuffer ( 0 ) ;
}
chrome . usb . controlTransfer ( this . handle , {
'direction' : 'out' ,
'recipient' : 'interface' ,
'requestType' : 'class' ,
'request' : request ,
'value' : value ,
2014-08-09 18:47:07 +00:00
'index' : _interface ,
2014-06-08 15:42:02 +00:00
'data' : arrayBuf
2014-08-14 15:00:32 +00:00
} , function ( result ) {
2014-06-08 19:15:12 +00:00
if ( result . resultCode ) console . log ( result . resultCode ) ;
callback ( result ) ;
} ) ;
}
} ;
2014-06-09 21:29:36 +00:00
// routine calling DFU_CLRSTATUS until device is in dfuIDLE state
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . clearStatus = function ( callback ) {
2014-06-09 21:29:36 +00:00
var self = this ;
function check _status ( ) {
2014-08-14 15:00:32 +00:00
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-09 21:29:36 +00:00
if ( data [ 4 ] == self . state . dfuIDLE ) {
2014-06-09 21:49:08 +00:00
callback ( data ) ;
2014-06-09 21:29:36 +00:00
} else {
var delay = data [ 1 ] | ( data [ 2 ] << 8 ) | ( data [ 3 ] << 16 ) ;
setTimeout ( clear _status , delay ) ;
}
} ) ;
}
function clear _status ( ) {
2014-06-09 21:49:08 +00:00
self . controlTransfer ( 'out' , self . request . CLRSTATUS , 0 , 0 , 0 , 0 , check _status ) ;
2014-06-09 21:29:36 +00:00
}
check _status ( ) ;
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . loadAddress = function ( address , callback ) {
2014-06-09 21:29:36 +00:00
var self = this ;
2014-08-14 15:00:32 +00:00
self . controlTransfer ( 'out' , self . request . DNLOAD , 0 , 0 , 0 , [ 0x21 , address , ( address >> 8 ) , ( address >> 16 ) , ( address >> 24 ) ] , function ( ) {
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-09 21:29:36 +00:00
if ( data [ 4 ] == self . state . dfuDNBUSY ) {
var delay = data [ 1 ] | ( data [ 2 ] << 8 ) | ( data [ 3 ] << 16 ) ;
2014-08-14 15:00:32 +00:00
setTimeout ( function ( ) {
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-09 21:29:36 +00:00
if ( data [ 4 ] == self . state . dfuDNLOAD _IDLE ) {
2014-06-09 21:49:08 +00:00
callback ( data ) ;
2014-06-09 21:29:36 +00:00
} else {
console . log ( 'Failed to execure address load' ) ;
self . upload _procedure ( 99 ) ;
}
} ) ;
} , delay ) ;
} else {
console . log ( 'Failed to request address load' ) ;
self . upload _procedure ( 99 ) ;
}
} ) ;
} ) ;
} ;
2014-06-09 11:01:18 +00:00
// first_array = usually hex_to_flash array
// second_array = usually verify_hex array
// result = true/false
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . verify _flash = function ( first _array , second _array ) {
2014-06-09 11:01:18 +00:00
for ( var i = 0 ; i < first _array . length ; i ++ ) {
if ( first _array [ i ] != second _array [ i ] ) {
console . log ( 'Verification failed on byte: ' + i + ' expected: 0x' + first _array [ i ] . toString ( 16 ) + ' received: 0x' + second _array [ i ] . toString ( 16 ) ) ;
return false ;
}
}
console . log ( 'Verification successful, matching: ' + first _array . length + ' bytes' ) ;
return true ;
} ;
2014-08-14 15:00:32 +00:00
STM32DFU _protocol . prototype . upload _procedure = function ( step ) {
2014-06-08 19:15:12 +00:00
var self = this ;
switch ( step ) {
case 1 :
2014-08-14 15:00:32 +00:00
self . clearStatus ( function ( ) {
2014-06-09 21:29:36 +00:00
self . upload _procedure ( 2 ) ;
2014-06-08 19:15:12 +00:00
} ) ;
break ;
case 2 :
2014-06-08 21:44:06 +00:00
// full chip erase
console . log ( 'Executing global chip erase' ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Erasing ...' ) ;
2014-06-08 21:44:06 +00:00
2014-08-14 15:00:32 +00:00
self . controlTransfer ( 'out' , self . request . DNLOAD , 0 , 0 , 0 , [ 0x41 ] , function ( ) {
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-08 19:33:42 +00:00
if ( data [ 4 ] == self . state . dfuDNBUSY ) { // completely normal
2014-06-08 20:06:01 +00:00
var delay = data [ 1 ] | ( data [ 2 ] << 8 ) | ( data [ 3 ] << 16 ) ;
2014-08-14 15:00:32 +00:00
setTimeout ( function ( ) {
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-08 20:06:01 +00:00
if ( data [ 4 ] == self . state . dfuDNLOAD _IDLE ) {
self . upload _procedure ( 4 ) ;
} else {
2014-06-09 21:29:36 +00:00
console . log ( 'Failed to execute global chip erase' ) ;
self . upload _procedure ( 99 ) ;
2014-06-08 20:06:01 +00:00
}
} ) ;
} , delay ) ;
2014-06-08 19:33:42 +00:00
} else {
2014-06-09 21:29:36 +00:00
console . log ( 'Failed to initiate global chip erase' ) ;
self . upload _procedure ( 99 ) ;
2014-06-08 19:33:42 +00:00
}
} ) ;
} ) ;
break ;
case 4 :
2014-06-08 21:44:06 +00:00
// upload
2014-06-09 21:29:36 +00:00
// we dont need to clear the state as we are already using DFU_DNLOAD
2014-06-08 21:44:06 +00:00
console . log ( 'Writing data ...' ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Flashing ...' ) ;
2014-06-08 21:44:06 +00:00
var blocks = self . hex . data . length - 1 ;
var flashing _block = 0 ;
var address = self . hex . data [ flashing _block ] . address ;
var bytes _flashed = 0 ;
var bytes _flashed _total = 0 ; // used for progress bar
var wBlockNum = 2 ; // required by DFU
2014-08-09 18:47:07 +00:00
var write = function ( ) {
2014-06-08 21:44:06 +00:00
if ( bytes _flashed < self . hex . data [ flashing _block ] . bytes ) {
var bytes _to _write = ( ( bytes _flashed + 2048 ) <= self . hex . data [ flashing _block ] . bytes ) ? 2048 : ( self . hex . data [ flashing _block ] . bytes - bytes _flashed ) ;
2014-06-09 21:29:36 +00:00
var data _to _flash = self . hex . data [ flashing _block ] . data . slice ( bytes _flashed , bytes _flashed + bytes _to _write ) ;
2014-06-09 10:46:41 +00:00
address += bytes _to _write ;
2014-06-09 21:29:36 +00:00
bytes _flashed += bytes _to _write ;
2014-06-09 10:46:41 +00:00
bytes _flashed _total += bytes _to _write ;
2014-06-08 21:44:06 +00:00
2014-08-14 15:00:32 +00:00
self . controlTransfer ( 'out' , self . request . DNLOAD , wBlockNum ++ , 0 , 0 , data _to _flash , function ( ) {
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-09 21:29:36 +00:00
if ( data [ 4 ] == self . state . dfuDNBUSY ) {
var delay = data [ 1 ] | ( data [ 2 ] << 8 ) | ( data [ 3 ] << 16 ) ;
2014-08-14 15:00:32 +00:00
setTimeout ( function ( ) {
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-09 21:29:36 +00:00
if ( data [ 4 ] == self . state . dfuDNLOAD _IDLE ) {
// update progress bar
self . progress _bar _e . val ( bytes _flashed _total / ( self . hex . bytes _total * 2 ) * 100 ) ;
// flash another page
write ( ) ;
} else {
console . log ( 'Failed to write ' + bytes _to _write + 'bytes to 0x' + address . toString ( 16 ) ) ;
self . upload _procedure ( 99 ) ;
}
} ) ;
} , delay ) ;
} else {
console . log ( 'Failed to initiate write ' + bytes _to _write + 'bytes to 0x' + address . toString ( 16 ) ) ;
self . upload _procedure ( 99 ) ;
}
2014-06-08 21:44:06 +00:00
} ) ;
2014-06-09 10:46:41 +00:00
} )
2014-06-08 21:44:06 +00:00
} else {
if ( flashing _block < blocks ) {
2014-06-09 21:29:36 +00:00
// move to another block
2014-06-08 21:44:06 +00:00
flashing _block ++ ;
address = self . hex . data [ flashing _block ] . address ;
bytes _flashed = 0 ;
2014-06-09 10:46:41 +00:00
wBlockNum = 2 ;
2014-06-08 21:44:06 +00:00
2014-06-09 21:29:36 +00:00
self . loadAddress ( address , write ) ;
2014-06-08 21:44:06 +00:00
} else {
// all blocks flashed
console . log ( 'Writing: done' ) ;
// proceed to next step
2014-06-09 11:01:18 +00:00
self . upload _procedure ( 5 ) ;
2014-06-08 21:44:06 +00:00
}
}
}
2015-10-03 07:35:38 +00:00
// start
self . loadAddress ( address , write ) ;
2014-06-08 19:33:42 +00:00
break ;
case 5 :
2014-06-08 21:44:06 +00:00
// verify
console . log ( 'Verifying data ...' ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Verifying ...' ) ;
2014-06-08 21:44:06 +00:00
var blocks = self . hex . data . length - 1 ;
var reading _block = 0 ;
var address = self . hex . data [ reading _block ] . address ;
var bytes _verified = 0 ;
var bytes _verified _total = 0 ; // used for progress bar
2014-06-09 10:46:41 +00:00
var wBlockNum = 2 ; // required by DFU
2014-06-08 21:44:06 +00:00
// initialize arrays
for ( var i = 0 ; i <= blocks ; i ++ ) {
self . verify _hex . push ( [ ] ) ;
}
2014-06-09 22:19:42 +00:00
// start
2014-08-14 15:00:32 +00:00
self . clearStatus ( function ( ) {
self . loadAddress ( address , function ( ) {
2014-06-09 22:19:42 +00:00
self . clearStatus ( read ) ;
2014-06-09 11:01:18 +00:00
} ) ;
2014-06-09 22:19:42 +00:00
} ) ;
2014-06-09 11:01:18 +00:00
2014-08-09 18:47:07 +00:00
var read = function ( ) {
2014-06-09 11:01:18 +00:00
if ( bytes _verified < self . hex . data [ reading _block ] . bytes ) {
var bytes _to _read = ( ( bytes _verified + 2048 ) <= self . hex . data [ reading _block ] . bytes ) ? 2048 : ( self . hex . data [ reading _block ] . bytes - bytes _verified ) ;
2014-08-14 15:00:32 +00:00
self . controlTransfer ( 'in' , self . request . UPLOAD , wBlockNum ++ , 0 , bytes _to _read , 0 , function ( data , code ) {
2014-06-09 11:01:18 +00:00
for ( var i = 0 ; i < data . length ; i ++ ) {
self . verify _hex [ reading _block ] . push ( data [ i ] ) ;
}
address += bytes _to _read ;
bytes _verified += bytes _to _read ;
bytes _verified _total += bytes _to _read ;
// update progress bar
self . progress _bar _e . val ( ( self . hex . bytes _total + bytes _verified _total ) / ( self . hex . bytes _total * 2 ) * 100 ) ;
// verify another page
read ( ) ;
} ) ;
2014-06-08 21:44:06 +00:00
} else {
if ( reading _block < blocks ) {
2014-06-13 19:45:36 +00:00
// move to another block
2014-06-08 21:44:06 +00:00
reading _block ++ ;
address = self . hex . data [ reading _block ] . address ;
bytes _verified = 0 ;
2014-06-09 22:19:42 +00:00
wBlockNum = 2 ;
2014-06-08 21:44:06 +00:00
2014-08-14 15:00:32 +00:00
self . clearStatus ( function ( ) {
self . loadAddress ( address , function ( ) {
2014-06-09 22:19:42 +00:00
self . clearStatus ( read ) ;
} ) ;
} ) ;
2014-06-08 21:44:06 +00:00
} else {
// all blocks read, verify
var verify = true ;
for ( var i = 0 ; i <= blocks ; i ++ ) {
verify = self . verify _flash ( self . hex . data [ i ] . data , self . verify _hex [ i ] ) ;
if ( ! verify ) break ;
}
if ( verify ) {
console . log ( 'Programming: SUCCESSFUL' ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Programming: SUCCESSFUL' ) ;
2014-07-16 10:59:12 +00:00
googleAnalytics . sendEvent ( 'Flashing' , 'Programming' , 'success' ) ;
2014-06-08 21:44:06 +00:00
// update progress bar
self . progress _bar _e . addClass ( 'valid' ) ;
// proceed to next step
self . upload _procedure ( 6 ) ;
} else {
console . log ( 'Programming: FAILED' ) ;
2014-08-30 08:30:28 +00:00
$ ( 'span.progressLabel' ) . text ( 'Programming: FAILED' ) ;
2014-07-16 10:59:12 +00:00
googleAnalytics . sendEvent ( 'Flashing' , 'Programming' , 'fail' ) ;
2014-06-08 21:44:06 +00:00
// update progress bar
self . progress _bar _e . addClass ( 'invalid' ) ;
// disconnect
self . upload _procedure ( 99 ) ;
}
}
}
}
break ;
case 6 :
2014-06-09 11:16:58 +00:00
// jump to application code
var address = self . hex . data [ 0 ] . address ;
2014-08-14 15:00:32 +00:00
self . clearStatus ( function ( ) {
2014-06-09 22:09:15 +00:00
self . loadAddress ( address , leave ) ;
} ) ;
2014-06-09 11:16:58 +00:00
2014-08-09 18:47:07 +00:00
var leave = function ( ) {
2014-08-14 15:00:32 +00:00
self . controlTransfer ( 'out' , self . request . DNLOAD , 0 , 0 , 0 , 0 , function ( ) {
self . controlTransfer ( 'in' , self . request . GETSTATUS , 0 , 0 , 6 , 0 , function ( data ) {
2014-06-09 11:16:58 +00:00
self . upload _procedure ( 99 ) ;
} ) ;
} ) ;
}
2014-06-08 19:15:12 +00:00
break ;
case 99 :
// cleanup
self . releaseInterface ( 0 ) ;
2014-10-01 13:55:11 +00:00
var timeSpent = new Date ( ) . getTime ( ) - self . upload _time _start ;
console . log ( 'Script finished after: ' + ( timeSpent / 1000 ) + ' seconds' ) ;
2014-11-15 12:44:12 +00:00
if ( self . callback ) self . callback ( ) ;
2014-06-08 19:15:12 +00:00
break ;
2014-06-08 15:42:02 +00:00
}
2014-06-08 15:16:44 +00:00
} ;
// initialize object
var STM32DFU = new STM32DFU _protocol ( ) ;