8.2 Host bridge protocol
A case host that offers a computer a link to the products behind it implements this protocol (USB-017, 8.1). The computer then reaches each product's console through the host, and updates a product's firmware through the host, without the product ever appearing on the computer's own USB. The machine-readable form is data/bridge_v1.json.
8.2.1 The link
The host is a USB device on the computer with one CDC interface. In console mode the interface carries the host's own text console, whose commands are the host maker's. The console command bridge switches it to bridge mode: framed binary, until a CLOSE frame on channel 0 or until the computer drops DTR. One interface for both keeps the computer from having to tell two interfaces apart.
8.2.2 Frames
Each frame is COBS-encoded and ends with one 0x00 byte; multi-byte fields are little-endian. CRC: CRC-16/CCITT-FALSE (poly 0x1021, init 0xFFFF, no reflection, no final XOR) over every field before it.
| Field | Bytes | |
|---|---|---|
ver |
1 | Protocol version, 1 |
chan |
1 | 0 is the control channel; 1 to 255 are assigned by open or update |
type |
1 | Frame type, below |
seq |
2 | Per channel; a reply echoes the request's seq |
len |
2 | Payload length, at most max_payload |
payload |
len | JSON for CTRL and EVENT; bytes for DATA; a u32 byte count for CREDIT |
crc |
2 | CRC over the fields above |
| Type | Code | |
|---|---|---|
CTRL |
1 | A request, or the reply to one |
EVENT |
2 | Something changed; no reply |
DATA |
3 | Bytes for a tunnel or an update |
CREDIT |
4 | The receiver grants more bytes on the channel |
CLOSE |
5 | The channel ends; on channel 0, bridge mode ends |
A frame with a bad CRC or a bad COBS encoding is dropped. The sender of a request retries it after a timeout. Flow control is by credit, per channel: the receiver grants bytes with CREDIT, and the sender never has more than that in flight. A host grants no more than the buffer it has for the channel.
8.2.3 Control channel
Requests and replies are CTRL frames on channel 0 with JSON payloads. hello is the first frame of a session.
Each request is a JSON object whose cmd names the command; its other fields and the reply's are below.
cmd |
Request fields | Reply fields | |
|---|---|---|---|
hello |
proto | proto, host (fw, serial), ports, maxPayload | The first frame of a session; versions and limits |
ports |
— | for each port: port, power, mode (app, update, empty), usb (vid, pid, manufacturer, product, serial, classes), last | Each downstream port; last is the product that was on it before it entered update mode |
open |
port | chan | A tunnel: a byte pipe to the product's console interface |
close |
chan | — | Ends a tunnel or an update |
update |
port, method, size, sha256, product, and the method's own | chan, credit | Streams a firmware image on DATA frames; the method names how the host writes it |
power_cycle |
port | — | Switches the port's power off and on (USB-013) |
| Event | Payload fields | |
|---|---|---|
attach |
the port's ports entry | A product appeared on a port |
detach |
port | A product left a port |
state |
port, mode | A port's mode changed |
update |
chan, stage, pct; or stage error with code and message | Progress of an update |
A product's identity in ports is its iSerial (USB-005), which survives the product's reboots and a move to another port. last is the identity a port had before it entered update mode, when a boot loader answers there in the product's place; it lets the computer recover a product that stopped in its boot loader.
8.2.4 Updates
update names a method, and the host runs that method's stages, reporting each in an update event. The host streams the image: it holds no copy, writes each block as it arrives, and checks the SHA-256 of the whole stream before the last block. One update runs at a time; tunnels to other products stay open. An abort before the write leaves the product running; an abort during the write leaves it in its boot loader, from which the same update recovers it. The one method defined suits any product whose boot loader presents a UF2 mass-storage volume; the boot ROMs of the RP2040 and RP2350 microcontrollers are two such loaders, and a product names its UF2 family in the update request.
| Method | For | Stages | |
|---|---|---|---|
uf2-msc |
Any product whose boot loader presents a UF2 mass-storage volume | PREFLIGHT, ENTER, WAIT_LOADER, CHECK, WRITE, WAIT_APP, VERIFY, DONE | The host asks the product to enter its boot loader, waits for the mass-storage volume on the same port, checks the first UF2 block's family and size, writes each 512-byte block as it arrives, and waits for the product to return with the same iSerial |
| Error | |
|---|---|
no_module |
Nothing in app mode on the port |
product_mismatch |
The port's iProduct is not the update's product |
no_loader |
The product did not enter its boot loader |
loader_timeout |
No boot loader appeared on the port |
bad_image |
The image's format, family, or size is wrong |
write_failed |
The host could not write a block |
hash_mismatch |
The streamed image's SHA-256 is not the one announced |
no_app |
The product did not return after the write; the port stays in update mode, recoverable |
A host that updates a product whose outputs a row depends on, such as a video reference generator, asks the user before it starts: the row loses them until the product returns.