Skip to content

Commit 2fabba1

Browse files
Flasher tool: install Windows drivers to correctly flash the board (#671)
Co-authored-by: Cristian Maglie <c.maglie@arduino.cc>
1 parent 278104f commit 2fabba1

File tree

12 files changed

+179
-19
lines changed

12 files changed

+179
-19
lines changed

.github/workflows/release-flasher.yml

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ jobs:
1616
build:
1717
strategy:
1818
matrix:
19-
os: [linux, darwin, windows]
19+
os: [ubuntu-22.04, macos-13, windows-2022]
2020
arch: [amd64, arm64]
2121
exclude:
22-
- os: windows
22+
- os: windows-2022
2323
arch: arm64
24-
runs-on: ubuntu-22.04
24+
runs-on: ${{ matrix.os }}
2525
outputs:
2626
release: ${{ steps.set-version.outputs.RELEASE_NAME }}
27+
defaults:
28+
run:
29+
shell: bash
2730
steps:
2831
- name: Extract version
2932
run: |
@@ -37,7 +40,7 @@ jobs:
3740
id: set-version
3841
run: |
3942
echo "RELEASE_NAME=${{ env.RELEASE_NAME }}" >> $GITHUB_OUTPUT
40-
if: matrix.os == 'windows'
43+
if: matrix.os == 'windows-2022'
4144

4245
- name: Checkout
4346
uses: actions/checkout@v4
@@ -60,18 +63,9 @@ jobs:
6063
git config --global url."https://${{ env.GITHUB_USERNAME }}:${{ env.GITHUB_TOKEN }}@github.com".insteadOf "https://github.com"
6164
6265
- name: Build Binary
63-
env:
64-
GOARCH: ${{ matrix.arch }}
65-
GOOS: ${{ matrix.os }}
6666
run: |
6767
task arduino-flasher-cli:build
6868
69-
- name: Rename Windows exe
70-
working-directory: ./${{ env.DIST_DIR }}
71-
run: |
72-
mv arduino-flasher-cli arduino-flasher-cli.exe
73-
if: matrix.os == 'windows'
74-
7569
- name: Prepare Build Artifacts
7670
working-directory: ./${{ env.DIST_DIR }}
7771
run: |
@@ -104,7 +98,7 @@ jobs:
10498
- name: Download artifacts
10599
uses: actions/download-artifact@v5
106100
with:
107-
name: ${{ env.PROJECT_NAME }}-windows-amd64
101+
name: ${{ env.PROJECT_NAME }}-windows-2022-amd64
108102

109103
- name: Save Win signing certificate to file
110104
run: echo "${{ secrets.INSTALLER_CERT_WINDOWS_CER }}" | base64 --decode > ${{ env.INSTALLER_CERT_WINDOWS_CER}}
@@ -130,7 +124,7 @@ jobs:
130124
- name: Upload artifacts
131125
uses: actions/upload-artifact@v4
132126
with:
133-
name: ${{ env.PROJECT_NAME }}-windows-amd64
127+
name: ${{ env.PROJECT_NAME }}-windows-2022-amd64
134128
path: |
135129
${{ env.RELEASE_NAME }}.tar.gz
136130
if-no-files-found: error

arduino-flasher-cli/drivers.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package main
2+
3+
import (
4+
"github.com/bcmi-labs/orchestrator/cmd/feedback"
5+
"github.com/bcmi-labs/orchestrator/cmd/i18n"
6+
"github.com/spf13/cobra"
7+
)
8+
9+
func newInstallDriversCmd() *cobra.Command {
10+
cmd := &cobra.Command{
11+
Use: "install-drivers",
12+
Hidden: true,
13+
Run: func(cmd *cobra.Command, args []string) {
14+
if err := installDrivers(); err != nil {
15+
feedback.Fatal(i18n.Tr("error installing drivers: %v", err), feedback.ErrGeneric)
16+
}
17+
},
18+
}
19+
return cmd
20+
}
1020 KB
Binary file not shown.
901 KB
Binary file not shown.
12 KB
Binary file not shown.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
;
2+
; Installs WinUsb
3+
;
4+
5+
[Version]
6+
Signature = "$Windows NT$"
7+
Class = USBDevice
8+
ClassGUID = {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
9+
Provider = %ManufacturerName%
10+
CatalogFile = unoq.cat
11+
DriverVer = 09/17/2025,10.48.00.000
12+
13+
; ========== Manufacturer/Models sections ===========
14+
15+
[Manufacturer]
16+
%ManufacturerName% = Standard,NTamd64
17+
18+
[Standard.NTamd64]
19+
%DeviceName% =USB_Install, USB\VID_05C6&PID_9008
20+
21+
; ========== Class definition ===========
22+
23+
[ClassInstall32]
24+
AddReg = ClassInstall_AddReg
25+
26+
[ClassInstall_AddReg]
27+
HKR,,,,%ClassName%
28+
HKR,,NoInstallClass,,1
29+
HKR,,IconPath,%REG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20"
30+
HKR,,LowerLogoVersion,,5.2
31+
32+
; =================== Installation ===================
33+
34+
[USB_Install]
35+
Include = winusb.inf
36+
Needs = WINUSB.NT
37+
38+
[USB_Install.Services]
39+
Include = winusb.inf
40+
Needs = WINUSB.NT.Services
41+
42+
[USB_Install.HW]
43+
AddReg=Dev_AddReg
44+
45+
[Dev_AddReg]
46+
HKR,,DeviceInterfaceGUIDs,0x10000,"{51de5bfa-d59d-4f3e-9b36-0b4b210dd53f}"
47+
48+
; [DestinationDirs]
49+
; If your INF needs to copy files, you must not use the DefaultDestDir directive here.
50+
; You must explicitly reference all file-list-section names in this section.
51+
52+
; =================== Strings ===================
53+
54+
[Strings]
55+
ManufacturerName="Arduino"
56+
ClassName="Universal Serial Bus devices"
57+
DeviceName="Arduino UNO Q Download mode"
58+
REG_MULTI_SZ = 0x00010000
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//go:build !windows
2+
3+
package main
4+
5+
// installDrivers is a no-op on non-Windows platforms
6+
func installDrivers() error {
7+
return nil
8+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package main
2+
3+
import (
4+
"embed"
5+
"log/slog"
6+
"runtime"
7+
8+
"github.com/arduino/go-paths-helper"
9+
)
10+
11+
//go:embed drivers
12+
var drivers embed.FS
13+
14+
// installDrivers installs the Windows driver using dpinst.exe. This requires
15+
// administrative privileges.
16+
func installDrivers() error {
17+
tmpDir, err := paths.MkTempDir("", "arduino-flasher-windriver-")
18+
if err != nil {
19+
return err
20+
}
21+
defer tmpDir.RemoveAll()
22+
23+
dpinstArch := "drivers/dpinst-x86.exe"
24+
if runtime.GOARCH == "amd64" {
25+
dpinstArch = "drivers/dpinst-amd64.exe"
26+
}
27+
dpinst, err := drivers.ReadFile(dpinstArch)
28+
if err != nil {
29+
return err
30+
}
31+
driverCat, err := drivers.ReadFile("drivers/unoq.cat")
32+
if err != nil {
33+
return err
34+
}
35+
driverInf, err := drivers.ReadFile("drivers/unoq.inf")
36+
if err != nil {
37+
return err
38+
}
39+
dpinstPath := tmpDir.Join("dpinst.exe")
40+
err = dpinstPath.WriteFile(dpinst)
41+
if err != nil {
42+
return err
43+
}
44+
catPath := tmpDir.Join("unoq.cat")
45+
err = catPath.WriteFile(driverCat)
46+
if err != nil {
47+
return err
48+
}
49+
infPath := tmpDir.Join("unoq.inf")
50+
err = infPath.WriteFile(driverInf)
51+
if err != nil {
52+
return err
53+
}
54+
55+
slog.Info("Installing Windows driver")
56+
dpinstProc, err := paths.NewProcessFromPath(nil, dpinstPath, "/SE", "/SW", "/SA")
57+
if err != nil {
58+
return err
59+
}
60+
dpinstProc.SetDir(tmpDir.String())
61+
return dpinstProc.Run()
62+
}

arduino-flasher-cli/flash.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"fmt"
77
"net/url"
88
"os"
9+
"runtime"
910
"strings"
1011

1112
"github.com/arduino/go-paths-helper"
13+
runas "github.com/arduino/go-windows-runas"
1214
"github.com/bcmi-labs/orchestrator/cmd/feedback"
1315
"github.com/bcmi-labs/orchestrator/cmd/i18n"
1416
"github.com/spf13/cobra"
@@ -24,6 +26,7 @@ func newFlashCmd() *cobra.Command {
2426
" " + os.Args[0] + " flash 20250915-173\n",
2527
Args: cobra.ExactArgs(1),
2628
Run: func(cmd *cobra.Command, args []string) {
29+
checkDriversInstalled()
2730
runFlashCommand(cmd.Context(), args, forceYes)
2831
},
2932
}
@@ -33,6 +36,17 @@ func newFlashCmd() *cobra.Command {
3336
return appCmd
3437
}
3538

39+
func checkDriversInstalled() {
40+
if runtime.GOOS != "windows" {
41+
return
42+
}
43+
cmd, _ := os.Executable()
44+
pwd, _ := os.Getwd()
45+
if _, err := runas.RunElevated(cmd, pwd, []string{"install-drivers"}, true); err != nil {
46+
feedback.Fatal(i18n.Tr("error installing drivers: %v", err), feedback.ErrGeneric)
47+
}
48+
}
49+
3650
func runFlashCommand(ctx context.Context, args []string, forceYes bool) {
3751
version := args[0]
3852

arduino-flasher-cli/go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
module arduino-flasher
22

3-
go 1.25
3+
go 1.25.1
44

55
require (
66
github.com/arduino/go-paths-helper v1.14.0
7+
github.com/arduino/go-windows-runas v1.0.1
78
github.com/bcmi-labs/orchestrator v0.3.0
89
github.com/codeclysm/extract/v4 v4.0.0
910
github.com/spf13/cobra v1.9.1
@@ -18,5 +19,5 @@ require (
1819
github.com/sirupsen/logrus v1.9.3 // indirect
1920
github.com/spf13/pflag v1.0.7 // indirect
2021
github.com/ulikunitz/xz v0.5.12 // indirect
21-
golang.org/x/sys v0.35.0 // indirect
22+
golang.org/x/sys v0.36.0 // indirect
2223
)

0 commit comments

Comments
 (0)