Skip to content

fbuild-serial: USB-level bootloader re-enumeration detection (complement to #688 serial-line classifier) #693

Description

@zackees

TL;DR

#688 proposes a BootModeClassifier registry for recognizing wedged-device signatures on the serial stream. That covers serial-visible failures: ESP ROM download, ARM HardFault, etc. It does not cover USB-level bootloader re-entry — when a board transitions to a bootloader by changing its USB VID:PID and presenting a new interface.

Concretely:

  • RP2040 BOOTSEL → board disappears from the host as a CDC serial device and reappears as a USB MSC drive (2E8A:0003 Bootrom). Without USB-level awareness, fbuild sees "monitor died" and retries, never noticing the bootloader is open.
  • SAMD21 / SAMD51 DFU → similar: native USB CDC drops, USB DFU interface appears (Atmel 03EB:6124).
  • Teensy HID bootloader → similar: serial drops, HID 16C0:0478 interface appears.

This is a different problem from #688 (no serial line to classify) and a different problem from #687's BoardFamily (#687 says "this is how to enter bootloader," not "I observed bootloader entry").

Proposed shape

A small USB-device watcher on top of serialport::available_ports() (or platform-specific equivalents) that:

  1. Snapshots the set of USB devices at deploy start.
  2. After triggering bootloader entry (e.g. TouchBaud1200), watches for the expected new VID:PID with a timeout.
  3. Returns a typed event (BootloaderEntered { vid, pid, device_path }) that the deployer consumes.
pub enum BootloaderSignature {
    Rp2040BootSel,                  // 2E8A:0003 USB MSC
    SamdDfu,                        // 03EB:6124 USB DFU
    SamdMassStorage { class: u8 },  // SAMD-CIRCUITPY etc.
    TeensyHidBootloader,            // 16C0:0478
    EspRomDownloader,               // already a serial-line concern; flag both
}

pub fn watch_for_bootloader(
    expected: BootloaderSignature,
    timeout: Duration,
) -> Result<DeviceHandle>;

This is the missing piece for "we touched 1200 baud and the port disappeared; let's confirm the bootloader is actually there before we try to flash."

Acceptance criteria

  • bootloader_watcher module in fbuild-serial or fbuild-deploy.
  • At least one signature implemented + unit-tested: RP2040 BOOTSEL.
  • TouchBaud1200 reset path in #687 consumes the watcher and returns a typed error if the bootloader doesn't appear within the timeout — instead of silently retrying.
  • CI test: stubbed USB device snapshot with the expected VID:PID inserted at T+1s; watcher returns success.

Refs

Filed from the audit fan-out on FastLED/FastLED#3339.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions