-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdeploy_usb.py
More file actions
172 lines (142 loc) · 4.9 KB
/
deploy_usb.py
File metadata and controls
172 lines (142 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
"""Deploy MicroPython firmware to a STeaMi board via DAPLink USB mass-storage.
Detects the STeaMi volume by its label across Linux, macOS, and Windows,
copies the firmware .bin to it, and lets DAPLink auto-reset the target.
Usage:
python scripts/deploy_usb.py path/to/firmware.bin
"""
import os
import platform
import shutil
import subprocess
import sys
VOLUME_LABEL = "STeaMi"
def find_steami_linux():
"""Find STeaMi mount point on Linux via findmnt.
Returns the mount path, or ``None`` if the board is not mounted
or ``findmnt`` is not available.
"""
try:
result = subprocess.run(
["findmnt", "-n", "-o", "TARGET", "-S", "LABEL=" + VOLUME_LABEL],
capture_output=True,
text=True,
check=False,
)
except FileNotFoundError:
return None
if result.returncode == 0:
mount = result.stdout.strip().split("\n")[0]
return mount or None
return None
def find_steami_macos():
"""Find STeaMi mount point on macOS.
Returns ``/Volumes/STeaMi`` if the board is mounted, or ``None``.
"""
path = "/Volumes/" + VOLUME_LABEL
if os.path.isdir(path):
return path
return None
def _find_steami_windows_powershell():
"""Find STeaMi drive letter via PowerShell Get-Volume (preferred)."""
ps_cmd = (
"Get-Volume | Where-Object FileSystemLabel -eq '"
+ VOLUME_LABEL
+ "' | Select-Object -First 1 -ExpandProperty DriveLetter"
)
try:
result = subprocess.run(
["powershell", "-NoProfile", "-Command", ps_cmd],
capture_output=True,
text=True,
check=False,
)
except FileNotFoundError:
return None
if result.returncode == 0:
letter = result.stdout.strip()
if letter:
return letter + ":\\"
return None
def _find_steami_windows_wmic():
"""Find STeaMi drive letter via legacy wmic (fallback for older Windows)."""
try:
result = subprocess.run(
[
"wmic",
"logicaldisk",
"where",
"VolumeName='" + VOLUME_LABEL + "'",
"get",
"DeviceID",
"/value",
],
capture_output=True,
text=True,
check=False,
)
except FileNotFoundError:
return None
if result.returncode == 0:
for line in result.stdout.splitlines():
if line.startswith("DeviceID="):
drive = line.split("=", 1)[1].strip()
if drive:
return drive + "\\"
return None
def find_steami_windows():
"""Find STeaMi drive letter on Windows.
Tries PowerShell Get-Volume first (works on all modern Windows),
falls back to wmic for older systems where PowerShell is unavailable.
Returns the drive path (e.g. ``E:\\``), or ``None`` if the board is
not mounted or neither tool is available.
"""
return _find_steami_windows_powershell() or _find_steami_windows_wmic()
def find_steami():
"""Detect the STeaMi USB volume across platforms.
Returns the mount path as a string (e.g. ``/media/user/STeaMi``,
``/Volumes/STeaMi``, or ``E:\\``) when a volume with label ``STeaMi``
is found, or ``None`` if the board is not mounted (or the detection
tool — findmnt, PowerShell, wmic — is not available on the system).
Exits with an error on unsupported operating systems.
"""
system = platform.system()
if system == "Linux":
return find_steami_linux()
if system == "Darwin":
return find_steami_macos()
if system == "Windows":
return find_steami_windows()
print("Error: unsupported OS: " + system, file=sys.stderr)
sys.exit(1)
def main():
if len(sys.argv) != 2:
print("Usage: deploy_usb.py <firmware.bin>", file=sys.stderr)
sys.exit(1)
firmware = sys.argv[1]
if not os.path.isfile(firmware):
print("Error: firmware binary not found: " + firmware, file=sys.stderr)
print("Run 'make firmware' first.", file=sys.stderr)
sys.exit(1)
mount = find_steami()
if not mount or not os.path.isdir(mount):
print(
"Error: STeaMi board not found (no volume with label '"
+ VOLUME_LABEL
+ "').",
file=sys.stderr,
)
print("Check that the board is connected and mounted.", file=sys.stderr)
if platform.system() == "Windows":
print(
"On Windows, this requires PowerShell (Get-Volume) or wmic.",
file=sys.stderr,
)
sys.exit(1)
print("Copying firmware to " + mount + "...")
shutil.copy(firmware, mount)
# Best-effort flush on Unix (no-op on Windows)
if hasattr(os, "sync"):
os.sync()
print("Firmware deployed via USB. Board will reset automatically.")
if __name__ == "__main__":
main()