//! The device-manager protocol (docs/device-manager.md): what drivers and //! applications say to the device manager over its well-known endpoint. The //! vfs-protocol pattern — extern-struct messages, a version in the handshake, //! reserved fields — so both sides depend on the contract by name. Deliberately //! contains nothing lifecycle-shaped: stopping, liveness (the zero-length ping), //! and exit reasons are the universal vocabulary of //! docs/process-lifecycle.md, not this protocol. /// The protocol version a driver states in its hello. A manager that cannot /// serve a driver's version refuses the hello, and the mismatch is loud at /// startup instead of quiet corruption later. pub const version: u16 = 1; /// What kind of driver is talking (docs/driver-model.md's shapes). pub const Role = enum(u8) { /// Owns a controller and reports the devices behind it (`child_added`). bus = 1, /// Serves one device, reached through a bus's transfer protocol. device = 2, }; /// The message kinds. `enumerate`/`subscribe` land in M18.3. pub const Operation = enum(u8) { hello = 1, child_added = 2, child_removed = 3, }; /// `Hello.device_id` for a driver that serves no enumerated device (a test /// fixture, a synthetic source). pub const no_device: u64 = ~@as(u64, 0); /// The handshake, sent once by every driver the manager spawns — the manager's /// one self-enforced deadline: spawned and silent past it means wrong binary, /// wrong version, or wedged before main, and the stop sequence follows. pub const Hello = extern struct { operation: u8 = @intFromEnum(Operation.hello), /// A Role value. role: u8, /// The protocol version this driver was built against (`version`). version: u16 = version, reserved: u32 = 0, /// The device this driver was assigned (its argv[1]), or `no_device`. device_id: u64, }; pub const hello_size = @sizeOf(Hello); /// The manager's answer to a hello. Nonzero status = refused (version mismatch, /// unknown sender); a refused driver should exit cleanly. pub const HelloReply = extern struct { status: i32, reserved: u32 = 0, }; pub const reply_size = @sizeOf(HelloReply); /// A bus driver reporting one device it discovered behind its controller /// (docs/device-manager.md "the tree"). Identity is the bus's native language — /// for USB a port-speed class; the (class, subclass, protocol) triple joins it /// once control transfers exist (the USB track). The manager mirrors the child /// into its tree; when the reporting driver dies, the manager prunes everything /// it reported (the children describe protocol state that died with it) and the /// restarted instance rediscovers and re-reports. pub const ChildAdded = extern struct { operation: u8 = @intFromEnum(Operation.child_added), reserved0: u8 = 0, reserved1: u16 = 0, reserved2: u32 = 0, /// The reporting driver's own device (the controller) — the child's parent. parent: u64, /// Where on the bus (for USB: the root port number, 1-based). bus_address: u64, /// Bus-specific identity (for USB: the PORTSC port-speed class). identity: u64, }; pub const child_added_size = @sizeOf(ChildAdded); /// A bus driver reporting a device gone (hot-unplug). Not yet sent by any /// driver — the port scan has no unplug interrupt — but the manager handles it; /// death-pruning covers removal until hotplug lands. pub const ChildRemoved = extern struct { operation: u8 = @intFromEnum(Operation.child_removed), reserved0: u8 = 0, reserved1: u16 = 0, reserved2: u32 = 0, parent: u64, bus_address: u64, }; pub const child_removed_size = @sizeOf(ChildRemoved); /// The manager's answer to a tree report. pub const ReportReply = extern struct { status: i32, reserved: u32 = 0, }; /// Upper bound on any message in this protocol — sizes the endpoint buffers. pub const message_maximum = 64;