forked from Elara6331/infinitime
		
	Fix issue where DFU responses are missed causing DFU to time out intermittently
This commit is contained in:
		
							
								
								
									
										61
									
								
								dfu.go
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								dfu.go
									
									
									
									
									
								
							| @@ -6,7 +6,6 @@ import ( | |||||||
| 	"encoding/binary" | 	"encoding/binary" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"io" |  | ||||||
| 	"io/fs" | 	"io/fs" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| @@ -191,6 +190,23 @@ func (dfu *DFU) sendProgress() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // bufferPropsCh resends all messages on in to a new channel that is buffered with 5 elements | ||||||
|  | func bufferPropsCh(in chan *bluez.PropertyChanged) chan *bluez.PropertyChanged { | ||||||
|  | 	// Create new buffered channel | ||||||
|  | 	out := make(chan *bluez.PropertyChanged, 5) | ||||||
|  | 	go func() { | ||||||
|  | 		// Close channel when underlying channel closed | ||||||
|  | 		defer close(out) | ||||||
|  | 		// For every property change on in | ||||||
|  | 		for prop := range in { | ||||||
|  | 			// Write to out | ||||||
|  | 			out <- prop | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	// Return new buffered channel | ||||||
|  | 	return out | ||||||
|  | } | ||||||
|  |  | ||||||
| // Start DFU process | // Start DFU process | ||||||
| func (dfu *DFU) Start() error { | func (dfu *DFU) Start() error { | ||||||
| 	if dfu.progress == nil { | 	if dfu.progress == nil { | ||||||
| @@ -209,10 +225,12 @@ func (dfu *DFU) Start() error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Watch for property changes on control point | 	// Watch for property changes on control point | ||||||
| 	dfu.ctrlRespCh, err = dfu.ctrlPointChar.WatchProperties() | 	unbufferedCh, err := dfu.ctrlPointChar.WatchProperties() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	// Buffer properties channel so no changes are missed | ||||||
|  | 	dfu.ctrlRespCh = bufferPropsCh(unbufferedCh) | ||||||
|  |  | ||||||
| 	// Run step one | 	// Run step one | ||||||
| 	err = dfu.stepOne() | 	err = dfu.stepOne() | ||||||
| @@ -279,13 +297,30 @@ func (dfu *DFU) Start() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Reset reverts all values back to default to prepare for | ||||||
|  | // the next DFU. | ||||||
|  | func (dfu *DFU) Reset() { | ||||||
|  | 	dfu.bytesRecvd = 0 | ||||||
|  | 	dfu.bytesSent = 0 | ||||||
|  | 	dfu.fwSize = 0 | ||||||
|  | 	dfu.fwSendDone = false | ||||||
|  | 	dfu.fwImage = nil | ||||||
|  | 	dfu.initPacket = nil | ||||||
|  | 	dfu.ctrlRespCh = nil | ||||||
|  | 	dfu.progress = nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // on waits for the given command to be received on | // on waits for the given command to be received on | ||||||
| // the control point characteristic, then runs the callback. | // the control point characteristic, then runs the callback. | ||||||
| func (dfu *DFU) on(cmd []byte, onCmdCb func(data []byte) error) error { | func (dfu *DFU) on(cmd []byte, onCmdCb func(data []byte) error) error { | ||||||
|  | 	// Use for loop in case of invalid property | ||||||
|  | 	for { | ||||||
| 		select { | 		select { | ||||||
| 		case propChanged := <-dfu.ctrlRespCh: | 		case propChanged := <-dfu.ctrlRespCh: | ||||||
|  | 			// If property was invalid | ||||||
| 			if propChanged.Name != "Value" { | 			if propChanged.Name != "Value" { | ||||||
| 			return ErrDFUInvalidResponse | 				// Keep waiting | ||||||
|  | 				continue | ||||||
| 			} | 			} | ||||||
| 			// Assert propery value as byte slice | 			// Assert propery value as byte slice | ||||||
| 			data := propChanged.Value.([]byte) | 			data := propChanged.Value.([]byte) | ||||||
| @@ -299,6 +334,7 @@ func (dfu *DFU) on(cmd []byte, onCmdCb func(data []byte) error) error { | |||||||
| 			return ErrDFUTimeout | 			return ErrDFUTimeout | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (dfu *DFU) stepOne() error { | func (dfu *DFU) stepOne() error { | ||||||
| 	return dfu.ctrlPointChar.WriteValue(DFUCmdStart, nil) | 	return dfu.ctrlPointChar.WriteValue(DFUCmdStart, nil) | ||||||
| @@ -346,7 +382,13 @@ func (dfu *DFU) stepSeven() error { | |||||||
| 	// While send is not done | 	// While send is not done | ||||||
| 	for !dfu.fwSendDone { | 	for !dfu.fwSendDone { | ||||||
| 		for i := 0; i < DFUPktRecvInterval; i++ { | 		for i := 0; i < DFUPktRecvInterval; i++ { | ||||||
| 			amtLeft := int(dfu.fwSize) - dfu.bytesSent | 			amtLeft := dfu.fwSize - int64(dfu.bytesSent) | ||||||
|  | 			// If no bytes left to send, end transfer | ||||||
|  | 			if amtLeft == 0 { | ||||||
|  | 				dfu.sendProgress() | ||||||
|  | 				dfu.fwSendDone = true | ||||||
|  | 				return nil | ||||||
|  | 			} | ||||||
| 			var segment []byte | 			var segment []byte | ||||||
| 			// If amount left is less than segment size | 			// If amount left is less than segment size | ||||||
| 			if amtLeft < DFUSegmentSize { | 			if amtLeft < DFUSegmentSize { | ||||||
| @@ -357,13 +399,8 @@ func (dfu *DFU) stepSeven() error { | |||||||
| 				segment = make([]byte, DFUSegmentSize) | 				segment = make([]byte, DFUSegmentSize) | ||||||
| 			} | 			} | ||||||
| 			// Write firmware image into slice | 			// Write firmware image into slice | ||||||
| 			n, err := dfu.fwImage.Read(segment) | 			_, err := dfu.fwImage.Read(segment) | ||||||
| 			// If EOF, send is done | 			if err != nil { | ||||||
| 			if err == io.EOF { |  | ||||||
| 				dfu.sendProgress() |  | ||||||
| 				dfu.fwSendDone = true |  | ||||||
| 				return nil |  | ||||||
| 			} else if err != nil { |  | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 			// Write segment to packet characteristic | 			// Write segment to packet characteristic | ||||||
| @@ -372,7 +409,7 @@ func (dfu *DFU) stepSeven() error { | |||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 			// Increment bytes sent by amount read | 			// Increment bytes sent by amount read | ||||||
| 			dfu.bytesSent += n | 			dfu.bytesSent += len(segment) | ||||||
| 		} | 		} | ||||||
| 		// On 0x11, verify packet receipt size | 		// On 0x11, verify packet receipt size | ||||||
| 		err := dfu.on(DFUNotifPktRecvd, func(data []byte) error { | 		err := dfu.on(DFUNotifPktRecvd, func(data []byte) error { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user