//! 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. pub const Operation = enum(u8) { hello = 1, child_added = 2, child_removed = 3, enumerate = 4, subscribe = 5, }; /// `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; for PCI: /// the class triple). identity: u64, /// The kernel device id this child was `device_register`ed as — what the /// manager hands a matched driver as its argv assignment — or `no_device` /// for an unregistered leaf (a USB port before the descriptor track). device_id: u64 = no_device, }; 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, }; /// An application asking for the tree (M18.3): the reply is an EnumerateReply /// header followed by `count` ChildEntry records. pub const Enumerate = extern struct { operation: u8 = @intFromEnum(Operation.enumerate), reserved0: u8 = 0, reserved1: u16 = 0, reserved2: u32 = 0, }; pub const EnumerateReply = extern struct { status: i32, /// ChildEntry records following this header. count: u32, }; pub const ChildEntry = extern struct { parent: u64, bus_address: u64, identity: u64, }; /// An application subscribing to published add/remove events (the input-service /// pattern): the subscriber's endpoint rides as the call's **capability**, and /// events arrive on it as buffered messages whose payload is the same /// ChildAdded / ChildRemoved struct the bus drivers send — one encoding, both /// directions. pub const Subscribe = extern struct { operation: u8 = @intFromEnum(Operation.subscribe), reserved0: u8 = 0, reserved1: u16 = 0, reserved2: u32 = 0, }; /// Upper bound on any message in this protocol — sizes the endpoint buffers. /// Capped by the kernel's IPC MESSAGE_MAXIMUM (256): an EnumerateReply carries /// up to ten ChildEntry records per call, plenty for the mirror's current /// bounds; paging joins the protocol if a tree ever outgrows one message. pub const message_maximum = 256;