Fix issue where DFU responses are missed causing DFU to time out intermittently
This commit is contained in:
parent
d1a75f1c67
commit
1dde7f9b07
85
dfu.go
85
dfu.go
@ -6,7 +6,6 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"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
|
||||
func (dfu *DFU) Start() error {
|
||||
if dfu.progress == nil {
|
||||
@ -209,10 +225,12 @@ func (dfu *DFU) Start() error {
|
||||
}
|
||||
|
||||
// Watch for property changes on control point
|
||||
dfu.ctrlRespCh, err = dfu.ctrlPointChar.WatchProperties()
|
||||
unbufferedCh, err := dfu.ctrlPointChar.WatchProperties()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Buffer properties channel so no changes are missed
|
||||
dfu.ctrlRespCh = bufferPropsCh(unbufferedCh)
|
||||
|
||||
// Run step one
|
||||
err = dfu.stepOne()
|
||||
@ -279,24 +297,42 @@ func (dfu *DFU) Start() error {
|
||||
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
|
||||
// the control point characteristic, then runs the callback.
|
||||
func (dfu *DFU) on(cmd []byte, onCmdCb func(data []byte) error) error {
|
||||
select {
|
||||
case propChanged := <-dfu.ctrlRespCh:
|
||||
if propChanged.Name != "Value" {
|
||||
// Use for loop in case of invalid property
|
||||
for {
|
||||
select {
|
||||
case propChanged := <-dfu.ctrlRespCh:
|
||||
// If property was invalid
|
||||
if propChanged.Name != "Value" {
|
||||
// Keep waiting
|
||||
continue
|
||||
}
|
||||
// Assert propery value as byte slice
|
||||
data := propChanged.Value.([]byte)
|
||||
// If command has prefix of given command
|
||||
if bytes.HasPrefix(data, cmd) {
|
||||
// Return callback with data after command
|
||||
return onCmdCb(data[len(cmd):])
|
||||
}
|
||||
return ErrDFUInvalidResponse
|
||||
case <-time.After(50 * time.Second):
|
||||
return ErrDFUTimeout
|
||||
}
|
||||
// Assert propery value as byte slice
|
||||
data := propChanged.Value.([]byte)
|
||||
// If command has prefix of given command
|
||||
if bytes.HasPrefix(data, cmd) {
|
||||
// Return callback with data after command
|
||||
return onCmdCb(data[len(cmd):])
|
||||
}
|
||||
return ErrDFUInvalidResponse
|
||||
case <-time.After(50 * time.Second):
|
||||
return ErrDFUTimeout
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,7 +382,13 @@ func (dfu *DFU) stepSeven() error {
|
||||
// While send is not done
|
||||
for !dfu.fwSendDone {
|
||||
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
|
||||
// If amount left is less than segment size
|
||||
if amtLeft < DFUSegmentSize {
|
||||
@ -357,13 +399,8 @@ func (dfu *DFU) stepSeven() error {
|
||||
segment = make([]byte, DFUSegmentSize)
|
||||
}
|
||||
// Write firmware image into slice
|
||||
n, err := dfu.fwImage.Read(segment)
|
||||
// If EOF, send is done
|
||||
if err == io.EOF {
|
||||
dfu.sendProgress()
|
||||
dfu.fwSendDone = true
|
||||
return nil
|
||||
} else if err != nil {
|
||||
_, err := dfu.fwImage.Read(segment)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write segment to packet characteristic
|
||||
@ -372,7 +409,7 @@ func (dfu *DFU) stepSeven() error {
|
||||
return err
|
||||
}
|
||||
// Increment bytes sent by amount read
|
||||
dfu.bytesSent += n
|
||||
dfu.bytesSent += len(segment)
|
||||
}
|
||||
// On 0x11, verify packet receipt size
|
||||
err := dfu.on(DFUNotifPktRecvd, func(data []byte) error {
|
||||
|
Reference in New Issue
Block a user