librescoot-ums (ums-service)¶
Description¶
Manages USB gadget mode switching on the MDB between network (g_ether) and USB Mass Storage (g_mass_storage) modes. In UMS mode, exposes a 1 GB FAT32 virtual drive at /data/usb.drive to the host PC. On switching back to normal mode, processes files placed on the drive: syncs settings and WireGuard configs, installs Mender updates, runs scripts, and transfers maps to the DBC.
Command-Line Options¶
REDIS_ADDR=localhost:6379 Redis server address (environment variable)
REDIS_PASSWORD= Redis password (environment variable)
UMS_MAP_TIMEOUT=10m Per-file timeout for map transfers (environment variable)
UMS_SCRIPT_TIMEOUT=2m Per-file timeout for script transfers (environment variable)
UMS_MENDER_TIMEOUT=15m Per-file timeout for Mender update transfers (environment variable)
Redis Operations¶
Hash: usb¶
Fields read/written:
mode- Current USB mode (normal,ums,ums-by-dbc)
Fields written:
status- Service status (idle,preparing,active,processing,awaiting-reboot,rebooting)awaiting-rebootcovers the hand-off to update-service and installation. While it is set,stepnames what the wait is on:waiting-mdb,waiting-dbc,waiting-dbc+mdb, thenwaiting-vehicle-state. After installation completes and the vehicle-state safety gate passes,rebootingis published briefly before the reboot or DBC power-cycle command. The status returns toidlewhen the trigger fails, the wait fails/times out, or a new UMS session cancels the pending operation.step- Current processing step (settings,wireguard,radio-gaga,uplink-service,onboot,updates,maps,scripts, or empty)last-result- Outcome of the last reboot phase (reboot-triggered,timeout,install-error,vehicle-state, orerror)last-result-detail- Human-readable detail for that outcomelast-result-time- RFC3339 time the outcome was recorded- All three are cleared on the next UMS entry.
lsc usb statusprints them. progress- Upload progress percentage (0–100) during file transfersdetail- Human-readable transfer sub-step (e.g.map.mbtiles (120/380 MB))
Subscribed channel: usb
mode- Triggers mode switch when published
List: usb:log¶
Processing events are pushed here in real-time during UMS exit processing. Capped at 100 entries. Also written to ums_log.txt on the drive at the end of processing.
LED feedback¶
Uses blinker channels 3, 4, 6, 7 via scooter:led:fade to indicate UMS state:
| State | LEDs |
|---|---|
| UMS active (host connected) | All 4 blinker channels on |
ums-by-dbc: first disconnect, waiting for PC |
Front blinkers (3, 4) only |
| Normal / off | All 4 off |
USB Modes¶
# Switch to USB Mass Storage mode
redis-cli HSET usb mode ums
redis-cli PUBLISH usb mode
# UMS mode with DBC-specific double-disconnect behavior
redis-cli HSET usb mode ums-by-dbc
redis-cli PUBLISH usb mode
# Return to normal (g_ether) mode
redis-cli HSET usb mode normal
redis-cli PUBLISH usb mode
Mode behavior:
- ums — returns to normal after first USB disconnect
- ums-by-dbc — stays in UMS after first disconnect, switches to normal after second disconnect (for DBC updates, which may disconnect and reconnect mid-process)
- normal — standard g_ether USB network mode
Brake exit¶
The service subscribes to the input-events channel and acts on exactly one
event, brake:left:hold (vehicle-service emits it after a 3 s hold). Other
namespaced gestures such as brake:right:press and seatbox:tap are ignored,
so a stray input cannot interrupt a transfer.
What the hold does depends on where the service is:
- While preparing (
statusispreparing): the entry is abandoned beforeSwitchModeruns. The drive is already unmounted and the gadget was never touched, sog_etherstays loaded and the DBC's link survives.usb.modeis reconciled back tonormalandstatusreturns toidle. Librescoot 1.2 and later. - Once UMS is active:
doSwitchToNormalruns, which is the same path as a USB eject: the full exit processing below happens, including any queued update install and reboot. It is not a bail-out.
The cancel flag is recorded before taking the service mutex, because
switchToUMS holds that mutex for the whole preparing phase; setting the flag
first lets the in-flight entry observe it and abandon itself.
scootui-qt mirrors this on the UMS overlay, labelling the left-brake hold
Cancel while status is preparing and Exit otherwise.
Before mounting, the service checks the image with fsck.fat. Recoverable errors are repaired in place. An image with no valid FAT boot sector, or one that stays inconsistent after repair, is discarded and recreated empty: any files staged on it are lost, and the cycle fails with an instruction to reconnect the drive and copy them again.
Virtual Drive¶
1 GB FAT32 image at /data/usb.drive:
/
├── settings.toml # copied from /data/settings.toml if present
├── wireguard/ # WireGuard VPN configs
│ └── *.conf
├── radio-gaga/
│ └── config.yaml # copied from /data/radio-gaga/config.yaml
├── uplink-service/
│ └── config.yaml # copied from /data/uplink-service/config.yaml
├── onboot.sh # copied from the on-boot script if present
├── system-update/ # place .mender or .delta update files here
│ ├── librescoot-mdb-*.mender
│ └── librescoot-dbc-*.mender
├── maps/ # place map files here
│ ├── *.mbtiles
│ └── *tiles.tar or valhalla_tiles_*.tar, plain or .zst
├── scripts/
│ ├── mdb.sh # shell script to run on MDB
│ └── dbc.sh # shell script to transfer and run on DBC
├── log-bundles/ # pre-populated: bundles previously captured with lsc
├── diagnostics/ # pre-populated on UMS entry (read-only for user)
│ ├── mdb/
│ └── dbc/ # only if DBC was reachable at UMS entry
└── ums_log.txt # written on exit, survives the post-processing wipe
File Processing¶
On UMS entry¶
- Copies
/data/settings.tomlto drive root (if present) - Copies
/data/wireguard/*.conftowireguard/ - Copies
/data/radio-gaga/config.yamltoradio-gaga/and/data/uplink-service/config.yamltouplink-service/ - Copies the on-boot script to
onboot.sh - Creates
system-update/,maps/,scripts/andlog-bundles/directories - Copies existing log bundles from
/data/log-bundlestolog-bundles/ - Collects diagnostics to
diagnostics/mdb/(journal, dmesg, system info) anddiagnostics/dbc/if DBC is reachable. The MDBsystem-info.txtends with a=== modem ===section read from theinternetandmodemhashes (IMEI, ICCID, IMSI, operator, access tech, signal, registration, connectivity, IP, health, SIM/PIN/APN state); fields Redis has no value for print as-
The config files above are round-trips: whatever comes back on exit is read into place, and an untouched file is a no-op.
On UMS exit (returning to normal mode)¶
- Settings - copies
settings.tomlback to/data/, restarts settings-service if changed - WireGuard - syncs
*.conffiles to/data/wireguard/, removes local configs absent from drive, restarts settings-service if changed - radio-gaga - copies
radio-gaga/config.yamlback to/data/radio-gaga/, restartsradio-gaga.serviceif changed - uplink-service - copies
uplink-service/config.yamlback to/data/uplink-service/, restartslibrescoot-uplink.serviceif changed - onboot - copies
onboot.shback into place - Updates - MDB
.mender/.deltafiles installed locally viascooter:update:mdb; DBC.mender/.deltafiles transferred to DBC and queued viascooter:update:dbc - Maps - transfers
.mbtilestomap.mbtiles.tmpon the DBC and renames it into/data/maps/map.mbtiles, so the installed file is only ever a complete transfer; transfers Valhalla tile archives to/data/valhalla/tiles.taron DBC. Avalhalla_tiles_*.tar.zstis uploaded compressed and decompressed on the DBC, into a temp file that only replacestiles.taronce the whole stream has decoded; the installed file is always the plain seekable tar, because Valhalla mmaps it as itstile_extract. After each artifact lands, the service reads it back on the DBC (sha256sumplusstat), records it in/data/maps/metadata.jsonand mirrors it into themapshash. The region comes from the published filename (tiles_<slug>.mbtiles,valhalla_tiles_<slug>.tar); a renamed or generically named file clears the recorded region rather than leaving the previous one to describe tiles it no longer refers to - Scripts - runs
scripts/mdb.shlocally; transfersscripts/dbc.shto DBC and runs it remotely - Writes
ums_log.txtto drive root, then cleans the drive (preservingums_log.txt)
Each step is independent: a failure is logged to usb:log and the remaining
steps still run.
Post-update reboot: if the exit processing queued an MDB or DBC update install, the service sets status to awaiting-reboot and a background watcher performs the install pushes and waits for completion (10 min timeout). Once the vehicle-state safety gate passes it publishes rebooting, allows the dashboard to paint that final phase, then triggers a reboot. The reboot is gated on the vehicle state being in an allowed set (stand-by, parked, shutting-down); if the state is anything else, the reboot is skipped. MDB updates reboot the MDB via scooter:power; DBC-only updates power-cycle the dashboard via scooter:hardware. The watcher is cancellable: re-entering UMS cancels a pending reboot. When no update is queued, status goes straight back to idle with no reboot. The outcome is recorded on usb.last-result with its detail and time, so a cycle that gave up says why.
Hardware¶
- Network mode:
g_etherkernel module - Link state: switching into UMS records whether
usb0was up. Switching back bringsg_etherback but re-enablesusb0only if it had been up on entry, so a deliberately down link stays down. - UMS mode:
g_mass_storagekernel module - Requires root for
modprobe/rmmodoperations - DBC file transfers: HTTP PUT to port 8080 on
192.168.7.2(primary); SCP fallback. MDB serves staging files over HTTP at192.168.7.1:31337.
File Locations¶
| Path | Purpose |
|---|---|
/data/usb.drive |
Virtual USB drive image |
/data/settings.toml |
Device settings |
/data/wireguard/ |
WireGuard VPN configs |
/data/ota/ |
OTA update staging |
/data/dbc/ |
DBC file staging |