Skip to content

Commit e166686

Browse files
committed
feat(grpc): wait for edl device
1 parent bc42dba commit e166686

2 files changed

Lines changed: 72 additions & 17 deletions

File tree

internal/updater/flasher.go

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
package updater
1717

1818
import (
19+
"bytes"
1920
"context"
2021
"encoding/hex"
22+
"errors"
2123
"fmt"
24+
"log/slog"
25+
"os/exec"
2226
"runtime"
2327
"strconv"
2428
"strings"
@@ -112,27 +116,13 @@ type FlashEvent struct {
112116
type FlashCallback func(FlashEvent)
113117

114118
func FlashBoard(ctx context.Context, downloadedImagePath *paths.Path, version string, preserveUser bool, callback FlashCallback) error {
115-
flashDir, err := searchForFlashDir(downloadedImagePath)
119+
qdlPath, cleanup, err := installQdl()
116120
if err != nil {
117121
return err
118122
}
123+
defer cleanup()
119124

120-
qdlDir, err := paths.MkTempDir("", "qdl-")
121-
if err != nil {
122-
return err
123-
}
124-
defer func() { _ = qdlDir.RemoveAll() }()
125-
126-
qdlPath := qdlDir.Join("qdl")
127-
if runtime.GOOS == "windows" {
128-
qdlPath = qdlDir.Join("qdl.exe")
129-
}
130-
131-
err = qdlPath.WriteFile(artifacts.QdlBinary)
132-
if err != nil {
133-
return err
134-
}
135-
err = qdlPath.Chmod(0755)
125+
flashDir, err := searchForFlashDir(downloadedImagePath)
136126
if err != nil {
137127
return err
138128
}
@@ -239,6 +229,27 @@ func searchForFlashDir(extractPath *paths.Path) (*paths.Path, error) {
239229
}
240230
}
241231

232+
func installQdl() (*paths.Path, func(), error) {
233+
qdlDir, err := paths.MkTempDir("", "qdl-")
234+
if err != nil {
235+
return nil, nil, err
236+
}
237+
238+
qdlPath := qdlDir.Join("qdl")
239+
if runtime.GOOS == "windows" {
240+
qdlPath = qdlDir.Join("qdl.exe")
241+
}
242+
243+
if err = qdlPath.WriteFile(artifacts.QdlBinary); err != nil {
244+
return nil, nil, err
245+
}
246+
if err = qdlPath.Chmod(0755); err != nil {
247+
return nil, nil, err
248+
}
249+
250+
return qdlPath, func() { _ = qdlDir.RemoveAll() }, nil
251+
}
252+
242253
// Checks the board GPT table and counts the number of partitions, this tells if the board supports preserving or not user's data.
243254
func checkBoardGPTTable(ctx context.Context, qdlPath, flashDir *paths.Path) error {
244255
dumpBinPath := qdlPath.Parent().Join("dump.bin")
@@ -288,3 +299,43 @@ func checkBoardGPTTable(ctx context.Context, qdlPath, flashDir *paths.Path) erro
288299

289300
return nil
290301
}
302+
303+
// WantForQdlDevice waits for a QDL device to be connected.
304+
// This is like and hack because QDL does not have a specific command to wait for a device,
305+
// so we use the read command with a dummy ELF and XML file to detect when a device is connected.
306+
func WaitForQdlDevice(ctx context.Context) error {
307+
qdlPath, cleanup, err := installQdl()
308+
if err != nil {
309+
return err
310+
}
311+
defer cleanup()
312+
313+
readXMLPath := qdlPath.Parent().Join("read.xml")
314+
if err := readXMLPath.WriteFile(artifacts.ReadXML); err != nil {
315+
return err
316+
}
317+
318+
dummyBin := qdlPath.Parent().Join("dummy.elf")
319+
if err := dummyBin.WriteFile([]byte{}); err != nil {
320+
return err
321+
}
322+
323+
cmd, err := paths.NewProcess(nil, qdlPath.String(), dummyBin.String(), readXMLPath.String(), "--debug")
324+
if err != nil {
325+
return err
326+
}
327+
cmd.SetDir(qdlPath.Parent().String())
328+
if out, err := cmd.RunAndCaptureCombinedOutput(ctx); err != nil {
329+
slog.Debug("wait for qdl device command exit", "out", string(out), "err", err)
330+
var exitErr *exec.ExitError
331+
if errors.As(err, &exitErr) {
332+
const qdlExpectErrorStr = "USB: using out-chunk-size"
333+
if exitErr.ExitCode() == 1 && bytes.Contains(out, []byte(qdlExpectErrorStr)) {
334+
return nil
335+
}
336+
}
337+
return fmt.Errorf("error waiting for QDL device: %w: %s", err, out)
338+
} else {
339+
return fmt.Errorf("no QDL device found: %s", out)
340+
}
341+
}

service/service_flash.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ func (s *flasherServerImpl) Flash(req *flasher.FlashRequest, stream flasher.Flas
6767
}
6868
}
6969

70+
if err := updater.WaitForQdlDevice(ctx); err != nil {
71+
return fmt.Errorf("could not find connected Arduino Uno QDL device: %w", err)
72+
}
73+
7074
rel, err := client.GetReleaseByVersion(ctx, req.GetVersion())
7175
if err != nil {
7276
return fmt.Errorf("could not get release info: %w", err)

0 commit comments

Comments
 (0)