Expand description
Phase 115.A — runtime-pluggable custom transport vtable.
Defines the platform-side hook that lets users plug a custom transport (USB-CDC, BLE, RS-485, semihosting bridge, ring-buffer loopback) at runtime without changing board crate, Cargo features, or rebuilding.
The shape mirrors micro-ROS’s
rmw_uros_set_custom_transport(framing, params, open, close, write, read)
and the C ABI exposed by nros-c / nros-cpp as
nros_transport_ops_t.
§Why a fn-pointer vtable, not a Rust trait
- alloc-free. A
Box<dyn CustomTransport>would force thealloccrate on every no_std backend that wants to use the runtime hook. nano-ros’s bare-metal / FreeRTOS / NuttX / ThreadX targets ship without a global allocator on the default feature flags, sodynis a non-starter. - C ABI parity. The user-facing surface is
nros_transport_ops_t(a#[repr(C)]struct of fn pointers + avoid *). A Rust-side fn-ptr vtable means theset_custom_transportC entry just memcpys the incoming struct into the static — no glue, no shims, no trampolines. - Matches XRCE’s existing shape.
uxr_set_custom_transport_callbacksalready takes 4 raw fn pointers; the Rust wrapper atnros-rmw-xrce::init_transportlikewise. A trait would just be an extra layer that has to be type-erased into fn pointers anyway.
See docs/roadmap/phase-115-runtime-transport-vtable.md § A.1
for the full discussion.
§Threading contract (v1)
readandwritemay NOT be called concurrently from different threads. The active backend serialises them through thedrive_io/ spin-once path. Custom transports written against this contract can use a single-buffer state machine without internal locking.- Callbacks must NOT be invoked from interrupt context. Wrap
ISR-driven hardware in a queue +
readpoller. user_datais opaque to the runtime — itsSend/Syncdiscipline is the caller’s responsibility. The vtable struct itself isSend + Syncbecause the four fn pointers always are.
Structs§
- Nros
Transport Ops - Phase 115.A — runtime-pluggable custom transport. Caller fills in
the four fn pointers, hands the struct to
set_custom_transport, and the active backend treats it as the read / write surface for every wire frame.
Constants§
- NROS_
TRANSPORT_ OPS_ ABI_ VERSION_ V1 - Phase 115.A.2 — current ABI version of
NrosTransportOps.
Functions§
- peek_
custom_ transport - Phase 115.A — peek at the currently-registered transport without
consuming it. Used by backends that need to re-attach on session
reconnect, or by tests that want to verify a registration landed.
Returns
Noneif nothing was registered. - set_
custom_ ⚠transport - Phase 115.A — register a custom transport vtable. Must be called
before the first
Rmw::open(ornros_support_initfrom the C surface). v1 leaves enforcement of “before init” to backend code — they reject re-registration withNROS_RMW_RET_ALREADY_INITafterRmw::opensucceeds. - take_
custom_ transport - Phase 115.A — drain the registered transport. Returns the
previously-registered vtable (
Noneif nothing was registered) and clears the slot. Backends call this fromRmw::openwhenplatform-customis the active platform; the vtable then lives inside the session for the rest of the process lifetime.