establishment: usb-transfer stops being a name

P1 of docs/establishment-planes-plan.md. The bus no longer binds
/protocol/usb-transfer — the bind race made whichever instance came second
unreachable, which on a real three-controller Ryzen meant a mouse no class
driver could reach ("could not open device 50"). Each instance hands its
serving endpoint up in the hello that already delegates its controller, and
class drivers receive their OWN controller's channel from helloForChannel —
routed by the manager's lineage, retried while a provider is mid-restart,
on one manager handle so retries never spend handle-table slots.

usb.open(bus, id) now takes the channel it used to look up; the name rows
leave protocol.csv with the code (bind 67, opens 119/120/122); the
conformance fixture's prose stops claiming the bus binds; and the stale
input-client import leaves the bus with the channel one.

Gate: 19 QEMU cases green (usb family, hubs, both IOMMU variants, fat chain,
boot-from-USB, orderly shutdown, conformance).
This commit is contained in:
Daniel Samson
2026-08-09 11:48:31 +01:00
parent 77fe4d220e
commit d603d40b5c
10 changed files with 84 additions and 67 deletions
@@ -35,11 +35,14 @@
//! enumerating an xHCI bus (the `usb-storage` scenario);
//! - `scanout` — the virtio-gpu driver, which needs an emulated virtio-gpu the
//! default harness does not attach (the `virtio-gpu` scenario);
//! - `device-manager`, `power` and `usb-transfer` — the three P4b rebased. All
//! three come with the device manager: it *is* the first, it spawns the
//! discovery service that binds the second, and the xHCI driver it spawns
//! binds the third. So booting a provider for any one of them means booting
//! the whole driver tree here.
//! - `device-manager` and `power` — both come with the device manager: it *is*
//! the first and spawns the discovery service that binds the second, so
//! booting a provider for either means booting the whole driver tree here.
//! - `usb-transfer` — never a registry name at all: several bus processes
//! provide it (one per controller) and consumers get their controller's
//! channel from the device manager's hello, routed by lineage
//! (communication.md "Establishment: two planes"). Its row below checks the
//! contract's shape only.
//!
//! That is the reason this scenario stays at two providers rather than five or
//! eight. It is not only the cost of booting half the system to send two
@@ -120,12 +123,11 @@ const contracts = [_]Contract{
contractOf(vfs_protocol.Protocol, false), // the FAT server — needs a volume
contractOf(block_protocol.Protocol, false), // usb-storage — needs the xHCI chain
contractOf(scanout_protocol.Protocol, false), // virtio-gpu — needs the device
// The three P4b rebased. Each needs the device manager (and, for the last
// two, what the device manager starts), which is more than this scenario
// boots — see the header.
// device-manager and power need the device manager (and what it starts),
// which is more than this scenario boots — see the header.
contractOf(device_manager_protocol.Protocol, false),
contractOf(power_protocol.Protocol, false), // the discovery service
contractOf(usb_transfer_protocol.Protocol, false), // the xHCI bus driver
contractOf(usb_transfer_protocol.Protocol, false), // never bound: per-controller, routed by hello
};
/// A verb number no protocol in the system defines, and none plausibly will: far