Merge USB session safety and preserve GPS preference compatibility
This commit is contained in:
commit
24fcbf3247
62 files changed
+2479
-240
No files matched your search
@@ -208,6 +208,7 @@ should use command `0x42`. See [Companion radio binary protocol](companion_proto
|
||||
| Retry | [`get/set/clear recent.repeater`; `get recent.repeaters`](cli_commands.md#view-seed-or-clear-the-recent-repeater-table) | Repeater | Yes | Yes | Yes |
|
||||
| GPS | [`get gps`; `set gps on/off`](cli_commands.md#view-or-change-gps-state) | Compiled GPS | Feature | Feature | Feature |
|
||||
| GPS | [`gps sync`](cli_commands.md#sync-this-nodes-clock-with-gps-time) | Compiled GPS | Feature | Feature | Feature |
|
||||
| GPS | [`get/set gps.sync.interval`](cli_commands.md#set-the-automatic-gps-clock-sync-interval) | Compiled GPS and provider; 1-336 hours | Feature | Feature | Feature |
|
||||
| GPS | [`gps setloc`](cli_commands.md#set-this-nodes-location-based-on-the-gps-coordinates) | Compiled GPS | Feature | Feature | Feature |
|
||||
| GPS | [`gps advert [none/share/prefs]`](cli_commands.md#view-or-change-the-gps-advert-policy) | Compiled GPS | Feature | Feature | Feature |
|
||||
| Sensors | [`get/set telemetry.access`](cli_commands.md#view-or-change-telemetry-access-mode) | Sensor-capable role | Feature | Feature | Limited |
|
||||
@@ -382,6 +383,7 @@ should use command `0x42`. See [Companion radio binary protocol](companion_proto
|
||||
| Retry | [`get/set/clear recent.repeater`; `get recent.repeaters`](cli_commands.md#view-seed-or-clear-the-recent-repeater-table) | Repeater | Yes | Yes | Yes | Yes | Yes |
|
||||
| GPS | [`get gps`; `set gps on/off`](cli_commands.md#view-or-change-gps-state) | Compiled onboard GPS | Feature | Feature | Feature | Feature | Feature |
|
||||
| GPS | [`gps sync`](cli_commands.md#sync-this-nodes-clock-with-gps-time) | Compiled onboard GPS | Feature | Feature | Feature | Feature | Feature |
|
||||
| GPS | [`get/set gps.sync.interval`](cli_commands.md#set-the-automatic-gps-clock-sync-interval) | Compiled GPS and provider; 1-336 hours | Feature | Feature | Feature | Feature | Feature |
|
||||
| GPS | [`gps setloc`](cli_commands.md#set-this-nodes-location-based-on-the-gps-coordinates) | Compiled onboard GPS | Feature | Feature | Feature | Feature | Feature |
|
||||
| GPS | [`gps advert [none/share/prefs]`](cli_commands.md#view-or-change-the-gps-advert-policy) | Compiled onboard GPS | Feature | Feature | Feature | Feature | Feature |
|
||||
| Sensors | [`get/set telemetry.access`](cli_commands.md#view-or-change-telemetry-access-mode) | Sensor-capable full parser | Feature | Feature | Limited | Feature | Feature |
|
||||
|
||||
+39
-1
@@ -2422,7 +2422,8 @@ a trace already on air is allowed to finish. Locally initiated traffic and
|
||||
management replies are not cancelled.
|
||||
|
||||
The dynamic configuration field is `repeat.trace_off` (`0` or `1`). It is
|
||||
appended to `/com_prefs`; all previously saved field offsets stay unchanged.
|
||||
appended to `/com_prefs`; all field offsets in the published upstream layout
|
||||
stay unchanged.
|
||||
|
||||
---
|
||||
|
||||
@@ -4561,6 +4562,43 @@ On repeaters with device power saving enabled, the automatic GPS cycle wakes
|
||||
for up to 10 minutes and repeats seven days after GPS sleeps. A valid GPS time
|
||||
can correct the RTC either forward or backward. With device power saving off,
|
||||
an enabled GPS refreshes the RTC every 30 minutes.
|
||||
These are the legacy defaults; `gps.sync.interval` below overrides them.
|
||||
|
||||
---
|
||||
|
||||
#### Set the automatic GPS clock-sync interval
|
||||
|
||||
```text
|
||||
get gps.sync.interval
|
||||
set gps.sync.interval 1
|
||||
set gps.sync.interval 24
|
||||
set gps.sync.interval 336
|
||||
```
|
||||
|
||||
The interval is a whole number of **hours**, from **1 to 336** (two weeks).
|
||||
Larger numbers are capped, not rejected. For example:
|
||||
|
||||
```text
|
||||
set gps.sync.interval 999
|
||||
OK - GPS sync interval 336 hours (saved)
|
||||
```
|
||||
|
||||
Zero, negative numbers, fractional hours, and nonnumeric values are rejected.
|
||||
The setting is saved across reboots and supported by GPS-equipped repeater,
|
||||
room-server, sensor, and Companion builds. Until it is explicitly configured,
|
||||
the getter reports `default (board GPS sync policy)` and existing board timings
|
||||
are retained.
|
||||
|
||||
The selected interval controls periodic clock acquisitions both with GPS power
|
||||
saving and with a continuously powered receiver. Changing it reschedules a
|
||||
sleeping receiver without immediately powering it on. A GPS fix can take time;
|
||||
an unsuccessful acquisition retains the existing bounded awake window, then
|
||||
backs off before trying again. Device GPS/power switches still apply.
|
||||
|
||||
This does not change position-update `gps_interval`, location telemetry/cache
|
||||
timings, or mesh/NTP time synchronization. Location requests can still power GPS
|
||||
for a fix, but do not bypass the configured clock-sync interval. Explicit
|
||||
`gps sync` remains an immediate acquisition request where that command exists.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -118,6 +118,12 @@ The Companion app's `gps=1` / `gps=0` custom setting controls the same GPS.
|
||||
Only boards with a compiled GPS provider expose this setting. Sharing location
|
||||
with contacts is a separate setting.
|
||||
|
||||
Use `set gps.sync.interval <hours>` to save an automatic clock-sync interval of
|
||||
1-336 hours (two weeks); `get gps.sync.interval` reports it. Larger inputs are
|
||||
capped at 336 and the reply shows the applied value. Existing GPS timings are
|
||||
unchanged until configured. This controls clock synchronization, not the
|
||||
position-update `gps_interval` or location-sharing policy.
|
||||
|
||||
When the exact Full image includes MQTT, use WebConfig's MQTT cards or the
|
||||
same CLI settings used by infrastructure, such as `set mqtt1.preset custom`
|
||||
and `set mqtt1.server broker.example.com`. `set mqtt.enabled on|off` controls
|
||||
|
||||
@@ -41,12 +41,14 @@ Run only one PlatformIO process in the checkout at a time.
|
||||
|
||||
```sh
|
||||
python test/test_esp32_tinyusb_nonblocking.py
|
||||
python test/test_esp32_usb_session_fix.py
|
||||
python test/test_esp32_tinyusb_role_hygiene.py
|
||||
python test/test_esp32_tinyusb_cooperative_output.py
|
||||
python test/test_esp32_usb_serial_hygiene.py
|
||||
python test/test_nrf52_usb_logging_contract.py
|
||||
python test/test_nrf52_usb_lifecycle.py
|
||||
python test/test_common_cli_logging_transaction.py
|
||||
python test/test_companion_usb_logging_reply.py
|
||||
python test/test_usb_diagnostic_logging.py
|
||||
pio test -e native -f test_nrf52_debug_output -f test_serial_packet_log -f test_serial_mode_switch -f test_mesh_tables
|
||||
```
|
||||
@@ -84,6 +86,28 @@ ownership; USB is log-only during that session. Disabling logging restores USB
|
||||
traffic without accepting bytes typed during the log-only interval. A dedicated
|
||||
nRF52 logging port does not park the separate Companion port.
|
||||
|
||||
A framed USB logging command retains its original requester and queues its
|
||||
acknowledgement before changing ownership. The handoff advances without waiting
|
||||
for the host: live logging stays unchanged while the complete USB reply is
|
||||
backpressured. Disconnect/reset cancels that session's pending handoff; an
|
||||
already-saved preference can still take effect at the next boot. BLE/WiFi replies
|
||||
are never used as a fallback for a refused USB acknowledgement.
|
||||
|
||||
On native ESP32 TinyUSB, build-local framework hooks capture DTR and USB session
|
||||
boundaries synchronously in the USB owner task, before Arduino's delayed events.
|
||||
They purge old input at the boundary and reject late input while DTR is low,
|
||||
without deleting a new host's first query during main-loop cleanup. An armed
|
||||
old IN packet (or a racing writer) triggers immediate soft-disconnect, a minimum
|
||||
20 ms detached interval, and quarantine until fresh enumeration. Shared SDK
|
||||
files are not modified; a changed native-CDC descriptor fails the build closed
|
||||
until the hook is reviewed. This path is specific to the pinned Arduino-ESP32
|
||||
2.0.17 native CDC implementation; hardware Serial/JTAG and UART are unchanged.
|
||||
|
||||
Disabling diagnostics is not itself a protocol change and does not discard
|
||||
functional replies from the shared ESP32 text queue. Actual Binary/mOTA changes
|
||||
use the explicit terminal-output barrier. Touch and invalid-Ethernet-hostname
|
||||
diagnostics also honor the runtime logging gate and bounded USB stream.
|
||||
|
||||
Ethernet and enabled MQTT diagnostics honor the runtime logging gate and use
|
||||
the bounded USB facade. Infrastructure logging setters commit preferences
|
||||
before changing live output; failed saves leave previous settings unchanged.
|
||||
@@ -95,6 +119,10 @@ advance one row per service pass, using their existing output buffer. Reconnect
|
||||
cancels the old listing. The listing is a bounded live view, not an immutable
|
||||
snapshot of clients changed during output.
|
||||
|
||||
Stored dumps make progress even when HWCDC falls back to 256/512-byte TX rings.
|
||||
Recent-repeater headers/rows and EOF retain every unwritten suffix; a short
|
||||
write never causes their accepted prefix to be retried.
|
||||
|
||||
nRF52 FIFO cleanup also checks for an already-armed IN packet. If one exists
|
||||
at a session boundary (including a pending zero-length packet), both USB ports
|
||||
briefly detach and re-enumerate: a FIFO clear alone cannot recall endpoint RAM.
|
||||
@@ -103,3 +131,31 @@ without blocking the mesh loop. Dedicated CDC descriptors are added while
|
||||
detached even if the host has not yet completed enumeration. These recovery
|
||||
paths have native regression coverage; real host/board timing still requires
|
||||
hardware qualification.
|
||||
|
||||
The nRF52 callback only drops the pull-up and closes producer gates. The
|
||||
application loop sends the stack's unplug event afterward, so a full owner-task
|
||||
event queue cannot make its consumer wait on itself. The detach interval starts
|
||||
when that application-side stack detach actually occurs. A regression models a
|
||||
full finite event queue as well as the separate armed endpoint packet.
|
||||
|
||||
## Local qualification (2026-10-03)
|
||||
|
||||
These are the upstream USB-session qualification results before the subsequent
|
||||
USB watchdog, GPS preference, and repeater trace merge. The byte counts below
|
||||
describe those earlier binaries, not the current merged source.
|
||||
|
||||
- All 112 USB Python regression methods passed, plus nine logging-transaction,
|
||||
Bluetooth-control, and WiFi-status methods. The native facade includes a
|
||||
threaded close-versus-writer race and an unmount-with-reset-endpoints check.
|
||||
- `Xiao_S3_companion_radio_usb` built successfully with its default hardware
|
||||
Serial/JTAG transport: 880,709 flash bytes and 73,244 static RAM bytes.
|
||||
- A native-TinyUSB Xiao S3 USB Companion qualification build passed with debug
|
||||
and packet logging enabled: 928,133 flash bytes and 89,312 static RAM bytes.
|
||||
Its linked ELF contains the synchronous session hooks and endpoint query.
|
||||
- A RAK4631 Full Companion qualification build with two CDCs, debug/packet
|
||||
logging, and USB/BLE mOTA sources passed: 678,092 flash bytes and 154,428
|
||||
static RAM bytes. The runtime RAM and Bluetooth DFU safety checks also passed.
|
||||
|
||||
The two custom qualification builds used the lab profile
|
||||
`909.5 MHz / 500 kHz / SF5 / CR5`. No board was flashed, and no physical
|
||||
disconnect/reconnect or hardware endpoint recovery was claimed by these checks.
|
||||
@@ -163,6 +163,10 @@ as immediate alerts. Reading status does not renew the logging-client lease.
|
||||
|
||||
## Verification
|
||||
|
||||
The two qualification stages below precede the subsequent upstream USB/GPS
|
||||
and repeater trace merge. Their firmware byte margins describe those earlier
|
||||
images, not the current merged source.
|
||||
|
||||
Initial watchdog qualification on 2026-10-03, before the latest-event extension,
|
||||
passed 109 USB regression tests, 143 native test cases, 11 management protocol
|
||||
tests, and the browser decoder checks.
|
||||
@@ -196,3 +200,20 @@ can still exceed that tight budget. No features or filesystem space were cut
|
||||
to fit this extension. This is not an all-board release qualification or a
|
||||
physical USB recovery test. No hardware was flashed, and verification artifacts
|
||||
stayed outside `out`.
|
||||
|
||||
The subsequent USB/GPS/repeater-trace merge passed all 1,718 native cases,
|
||||
133 USB regression methods, 25 management/event/watchdog methods plus the
|
||||
browser decoder, and 10 GPS/trace/persistence methods. Companion preference
|
||||
tests exercise six platform/layout variants under fatal sanitizers. The
|
||||
compact final preference writer also matches the previous full image for
|
||||
256 tail-value sets per variant and preserves committed files through every
|
||||
partial-tail write/readback boundary and rename failure.
|
||||
|
||||
Compile checks for that merge passed standard XIAO S3 Full Companion, Station
|
||||
G2 Repeater and Room Server, native-USB XIAO S3 USB Companion with all five
|
||||
session/progress hooks linked, and XIAO nRF52 Repeater. The final compact writer
|
||||
passed both the bare STM32 CI recipe and the normal `1.17.1.9` recipe; the
|
||||
latter uses 229,020 of 229,376 app flash bytes (356 bytes of margin), retaining
|
||||
all features and the 32 KiB filesystem. The bare recipe is tighter still.
|
||||
These checks do not qualify every board or physical USB recovery. No device
|
||||
was flashed and existing `out` artifacts were not changed.
|
||||
Reference in new issue
Block a user