1#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
6#![allow(unsafe_op_in_unsafe_fn, clippy::missing_safety_doc)]
7pub type nros_platform_ret_t = i8;
10pub type nros_platform_log_writer_fn_t = ::core::option::Option<
11 unsafe extern "C" fn(
12 severity: u8,
13 name_ptr: *const u8,
14 name_len: usize,
15 msg_ptr: *const u8,
16 msg_len: usize,
17 ),
18>;
19pub type nros_platform_log_flush_fn_t = ::core::option::Option<unsafe extern "C" fn()>;
20#[doc = " @file platform_timer.h\n @brief Canonical C ABI for the nros platform timer surface.\n\n Companion to `<nros/platform.h>`; sits beside the core 39-symbol\n ABI as the Phase 110.E platform-timer interface. Carved into a\n separate header because bare-metal / single-shot consumers can\n omit timer support without losing the canonical platform symbols.\n\n # Handle model\n\n Platform timer handles are opaque `void *`. The implementation\n allocates whatever it needs to track the underlying primitive\n (`TimerHandle_t` on FreeRTOS, `TX_TIMER *` on ThreadX, `timer_t`\n on POSIX, `*mut k_timer` on Zephyr); the runtime never inspects\n the bytes pointed at.\n\n # Return-value conventions\n\n - `create_periodic` / `create_oneshot` return non-NULL on success\n and `NULL` on failure (analogous to libc `malloc`).\n - `cancel` returns 1 when the cancellation prevented the callback\n from firing, 0 if the callback already fired (or the timer was\n already cancelled or destroyed), -1 on unrecoverable error.\n - `destroy` is best-effort; idempotent on already-destroyed handles.\n\n # Threading / context\n\n Callbacks are invoked from a platform-defined timer context — a\n direct ISR on Zephyr / bare-metal, deferred to the FreeRTOS timer\n task on FreeRTOS, a real-time signal on POSIX. Callback bodies\n must be short, must not call back into nros_platform_* heap or\n blocking primitives, and must use atomic operations for shared\n state. `user_data` must outlive the timer handle."]
21pub type nros_platform_timer_callback_t =
22 ::core::option::Option<unsafe extern "C" fn(user_data: *mut core::ffi::c_void)>;
23#[repr(C)]
24#[derive(Debug, Copy, Clone)]
25pub struct nros_platform_task_attr_t {
26 #[doc = " Task name for the kernel's own tables and crash dumps. `NULL` = the\n port's default. Ports whose kernel has no name concept ignore it."]
27 pub name: *const core::ffi::c_char,
28 #[doc = " Minimum stack size in BYTES. `0` = the port's default.\n\n A FLOOR, not an exact size (issue 0612). Every port has a minimum of its\n own — `PTHREAD_STACK_MIN`, `configMINIMAL_STACK_SIZE`, `TX_MINIMUM_STACK`\n — and those differ by an order of magnitude, and on POSIX differ by\n ARCHITECTURE (16384 on glibc/x86_64, 131072 on glibc/aarch64). So no\n portable caller can name a number that is legal everywhere, and a port\n that treats a small request as an error turns a reasonable ask into a\n dead capability: that is exactly how `Executor::signal_fd()` returned\n `NotInitialized` on every Linux host. A port raises this to its own\n minimum; it never lowers it, and never refuses for being too small.\n\n Always bytes, never words: FreeRTOS's `xTaskCreate` takes words, and the\n private struct it replaced called the field `stack_depth` while ThreadX's\n identically-named field was bytes. The conversion belongs in the one port\n that needs it, not in every caller."]
29 pub stack_bytes: usize,
30 #[doc = " Caller-provided stack memory, or `NULL` to let the port obtain it.\n\n ThreadX requires the stack from its caller; POSIX, FreeRTOS and ESP-IDF\n let the kernel allocate and ignore this. A port that needs memory and is\n given `NULL` obtains it itself and releases it in `task_free`."]
31 pub stack_mem: *mut core::ffi::c_void,
32 #[doc = " Scheduling priority in the NORMALISED band: `0` = least urgent, larger\n = more urgent, `NROS_PLATFORM_PRIORITY_INHERIT` = keep the creating\n task's.\n\n phase-364 W5. This was \"platform-native\", and the natives disagree: `0`\n is the HIGHEST priority on ThreadX and the LOWEST on FreeRTOS, while\n Zephyr runs lower-is-more-urgent with negatives reserved for cooperative\n threads. A tier priority is authored ONCE, in `system.toml`, and\n deployed to several of them — so the same number meant \"run me first\" on\n one board and \"run me last\" on another, with nothing in the ABI\n recording which convention a port used.\n\n Each port maps this band onto its own range and documents the map at its\n `task_init`. Use `NROS_PLATFORM_PRIORITY_RAW(n)` to bypass the band when\n tuning one RTOS against its own documentation — that is a legitimate\n thing to do, and the band should not make it impossible."]
33 pub priority: i32,
34 #[doc = " SMP core to pin to, or `-1` for unpinned. Ignored on single-core."]
35 pub core: i8,
36 #[doc = " `NROS_PLATFORM_TASK_*` flags below."]
37 pub flags: u8,
38}
39pub const NROS_PLATFORM_RET_OK: i32 = 0;
40pub const NROS_PLATFORM_RET_ERROR: i32 = -1;
41pub const NROS_PLATFORM_RET_UNSUPPORTED: i32 = -5;
42pub const NROS_PLATFORM_RET_NOMEM: i32 = -6;
43pub const NROS_PLATFORM_RET_INVALID: i32 = -7;
44pub const NROS_PLATFORM_RET_TIMEOUT: i32 = -8;
45pub const NROS_PLATFORM_TASK_DETACHED: i32 = 1;
46pub const NROS_PLATFORM_PRIORITY_MIN: i32 = 0;
47pub const NROS_PLATFORM_PRIORITY_MAX: i32 = 255;
48pub const NROS_PLATFORM_PRIORITY_INHERIT: i32 = -2147483648;
49pub const NROS_PLATFORM_TASK_STORAGE_SIZE: i32 = 512;
50pub const NROS_PLATFORM_MUTEX_STORAGE_SIZE: i32 = 256;
51pub const NROS_PLATFORM_MUTEX_REC_STORAGE_SIZE: i32 = 256;
52pub const NROS_PLATFORM_CONDVAR_STORAGE_SIZE: i32 = 256;
53pub const NROS_PLATFORM_STORAGE_ALIGN: i32 = 8;
54unsafe extern "C" {
55 #[doc = " Monotonic nanoseconds since a platform-defined epoch (boot, program\n start, …). Never decreases. Wraps after ~584 years.\n\n Must be backed by a hardware counter or the OS tick — never by a\n software counter that only advances when polled.\n\n Available immediately after platform init, before any other nros\n subsystem. SHOULD be callable from an ISR; a port whose clock is not\n ISR-safe must say so in its port documentation.\n\n RFC-0073: this replaced the former `clock_ms` / `clock_us` pair. Ports\n that can convert without a runtime division should — where the counter\n frequency divides 1e9 (25/50/100/125/200/250 MHz) a compile-time\n ns-per-cycle multiply is ~2.5x cheaper than the divide it replaces."]
56 pub fn nros_platform_clock_ns() -> u64;
57}
58unsafe extern "C" {
59 #[doc = " Granularity of `nros_platform_clock_ns`, in nanoseconds: the smallest\n non-zero difference two successive reads can report.\n\n Examples: 1000000 for a 1 kHz tick, 40 for a 25 MHz cycle counter,\n 1000 for a microsecond hardware timer.\n\n Must be non-zero, and constant for the lifetime of the program after\n platform init. A port whose underlying rate is only known at runtime\n returns the resolved value; one whose rate can change under it returns\n the COARSEST value it may exhibit. There is no \"unknown\" encoding — a\n port that cannot answer honestly is reporting a clock it cannot\n honestly offer."]
60 pub fn nros_platform_clock_resolution_ns() -> u64;
61}
62unsafe extern "C" {
63 #[doc = " Microseconds since the UNIX EPOCH (1970-01-01T00:00:00Z), or `0` when\n this platform has no wall-clock source.\n\n READ THIS BEFORE REACHING FOR `nros_platform_clock_ns` (issue 0758).\n The two clocks in this header differ by one word in their names and by\n the only property that matters for interop:\n\n - `nros_platform_clock_ns` is MONOTONIC and boot-relative. Use it for\n durations, deadlines, spin gaps, timeouts — anything comparing two\n readings from THIS image. It is meaningless to a peer.\n - `nros_platform_epoch_us` is ABSOLUTE. Use it for message stamps and\n anything a peer will compare against its own clock.\n\n Reaching for the wrong one does not fail to build and does not fail\n locally; it fails at a peer, which is the expensive place to find out.\n The concrete case is the consumer this exists for: an embedded island\n stamped control commands from its boot epoch and Autoware's\n `vehicle_cmd_gate` rejected every one as stale, so autonomous mode could\n never actuate.\n\n `0` MEANS \"NO WALL CLOCK\", not \"the epoch\". Per this header's clock rule\n (see the top of file: \"If the platform has no clock, return `0`\") this\n never errors. A caller that gets `0` knows the image cannot stamp\n absolute time and should keep publishing boot-relative stamps knowingly,\n rather than publishing a confidently wrong absolute one. 1970 is not a\n plausible reading, so the sentinel costs no real value.\n\n Not required to be monotonic: a platform that acquires its epoch after\n boot (SNTP, RTC handoff) will JUMP when it does, and may jump backwards.\n Callers needing monotonicity use `nros_platform_clock_ns`.\n\n Need not be ISR-safe, and unlike `nros_platform_clock_ns` need not be\n available immediately after platform init — a port that acquires its\n epoch over the network necessarily answers `0` until it has."]
64 pub fn nros_platform_epoch_us() -> u64;
65}
66unsafe extern "C" {
67 #[doc = " Allocate `size` bytes; return `NULL` on failure. May be called from\n any thread."]
68 pub fn nros_platform_alloc(size: usize) -> *mut core::ffi::c_void;
69}
70unsafe extern "C" {
71 #[doc = " Resize the block at `ptr` to `size` bytes. Equivalent to libc\n `realloc`: `NULL` ptr → fresh alloc; `0` size → free + return `NULL`.\n Preserves contents up to `min(old, new)`."]
72 pub fn nros_platform_realloc(
73 ptr: *mut core::ffi::c_void,
74 size: usize,
75 ) -> *mut core::ffi::c_void;
76}
77unsafe extern "C" {
78 #[doc = " Free a previously allocated block. `NULL` is a no-op."]
79 pub fn nros_platform_dealloc(ptr: *mut core::ffi::c_void);
80}
81unsafe extern "C" {
82 #[doc = " Bytes currently allocated from the platform heap, or `0` if the port\n does not instrument it. Phase 230 / RFC-0034 D7: the true unified figure\n where the platform owns one kernel heap shared by the C side and the\n Rust `#[global_allocator]`."]
83 pub fn nros_platform_heap_used_bytes() -> usize;
84}
85unsafe extern "C" {
86 #[doc = " Smallest number of bytes ever left unused on the CALLING task's stack, or\n `0` if this port cannot report it.\n\n HEADROOM, not usage, because that is what both kernels natively track and\n it is the number a safety argument needs: how close the worst observed\n excursion came to the end of the stack.\n\n The heap has had `nros_platform_heap_used_bytes` since RFC-0034 D7; the\n stack had nothing, and stack overflow is the classic way one component\n corrupts another's state. ISO 26262 treats spatial freedom from\n interference as a first-class requirement and AUTOSAR pairs memory\n protection with stack monitoring for exactly this reason. Without a\n portable probe the only recourse is a per-RTOS one: this repo's Zephyr\n lane greps `thread_analyzer` printk output in CI, which is a text scrape\n of a debug facility standing in for a platform capability, and reports\n nothing on any other port.\n\n SELF only, deliberately. Both kernels answer for the calling task with no\n handle (`uxTaskGetStackHighWaterMark(NULL)`, `k_thread_stack_space_get`\n with `k_current_get()`), whereas answering for an arbitrary task needs a\n native handle this ABI does not carry -- on Zephyr the task storage is a\n `pthread_t` and the mapping to `k_thread *` is not public. A task\n reporting its own headroom is also the shape the callers want: each tier\n says how much of its own stack it has ever needed.\n\n `0` means \"this port does not instrument it\", matching\n `nros_platform_heap_used_bytes`. It is not a claim that the stack is\n full."]
87 pub fn nros_platform_task_stack_unused_bytes() -> usize;
88}
89unsafe extern "C" {
90 #[doc = " Total managed heap size in bytes (used + free), or `0` if unknown."]
91 pub fn nros_platform_heap_total_bytes() -> usize;
92}
93unsafe extern "C" {
94 #[doc = " Sleep at least `us` microseconds. Spin if the platform clock has no\n sub-millisecond timer."]
95 pub fn nros_platform_sleep_us(us: usize);
96}
97unsafe extern "C" {
98 #[doc = " Sleep at least `ms` milliseconds."]
99 pub fn nros_platform_sleep_ms(ms: usize);
100}
101unsafe extern "C" {
102 #[doc = " Sleep at least `s` seconds."]
103 pub fn nros_platform_sleep_s(s: usize);
104}
105unsafe extern "C" {
106 #[doc = " Voluntarily yield the current task / thread. On bare-metal,\n `core::hint::spin_loop()` is acceptable; on RTOSes use the native\n cooperative-yield primitive (`k_yield`, `vPortYield`,\n `tx_thread_relinquish`, `sched_yield`, …). RTOS yields are **not**\n ISR-safe."]
107 pub fn nros_platform_yield_now();
108}
109unsafe extern "C" {
110 #[doc = " Random `u8`. Cryptographically random where the platform has an\n entropy source; otherwise a seeded PRNG. Must be deterministic\n within a single test session for reproducibility."]
111 pub fn nros_platform_random_u8() -> u8;
112}
113unsafe extern "C" {
114 #[doc = " Random `u16`. See `random_u8` notes."]
115 pub fn nros_platform_random_u16() -> u16;
116}
117unsafe extern "C" {
118 #[doc = " Random `u32`. See `random_u8` notes."]
119 pub fn nros_platform_random_u32() -> u32;
120}
121unsafe extern "C" {
122 #[doc = " Random `u64`. See `random_u8` notes."]
123 pub fn nros_platform_random_u64() -> u64;
124}
125unsafe extern "C" {
126 #[doc = " Fill `len` bytes at `buf` with random data."]
127 pub fn nros_platform_random_fill(buf: *mut core::ffi::c_void, len: usize);
128}
129unsafe extern "C" {
130 #[doc = " Wall-clock nanoseconds since the Unix epoch, or `0` if the platform has\n no real-time clock.\n\n ONE symbol for one fact, mirroring what RFC-0073 / phase-352 did for the\n monotonic clock. It replaced `time_now_ms` + `time_since_epoch_secs` +\n `time_since_epoch_nanos` (issue 0532 item 5).\n\n Why the split had to go, beyond tidiness: the ABI spent ONE INSTANT over\n two symbols, and each call sampled the clock separately (the POSIX port\n issued its own `clock_gettime` in each). A second boundary landing between\n the two reads paired the OLD second with the NEW sub-second remainder — a\n timestamp that jumped a full second BACKWARDS, rarely and silently. Both\n `nros-core` and `nros-node` carried a bounded re-read loop to paper over\n it; a single read cannot tear, so those loops are gone.\n\n `u64` ns spans ~584 years from 1970, so it also retires the `uint32_t`\n seconds field, which overflowed in 2106.\n\n Ports convert from whatever they have — a port with only seconds returns\n `secs * 1000000000ULL`, and one with no RTC returns 0. Callers wanting\n milliseconds divide by 1000000; wanting a `(secs, nanos)` pair, divide and\n remainder by 1000000000."]
131 pub fn nros_platform_time_now_ns() -> u64;
132}
133unsafe extern "C" {
134 #[doc = " Fill `attr` with the defaults — equivalent to passing `NULL` to\n `task_init`.\n\n Callers use this rather than a designated initialiser so that a field added\n to the struct later stays source-compatible for out-of-tree ports."]
135 pub fn nros_platform_task_attr_init(attr: *mut nros_platform_task_attr_t);
136}
137unsafe extern "C" {
138 #[doc = " Spawn a new task. `task` is opaque caller-provided storage (size from\n `nros_platform_task_storage_size`); `attr` is a\n `nros_platform_task_attr_t *`, or `NULL` for every default; `entry` is the\n task entry point; `arg` is forwarded to `entry`.\n\n Returns `NROS_PLATFORM_RET_OK`, or `INVALID` (a NULL where storage or an\n entry is required), `NOMEM` (resources exhausted now — retry may succeed) or\n `UNSUPPORTED` (this port has no tasks at all)."]
139 pub fn nros_platform_task_init(
140 task: *mut core::ffi::c_void,
141 attr: *mut core::ffi::c_void,
142 entry: ::core::option::Option<
143 unsafe extern "C" fn(arg1: *mut core::ffi::c_void) -> *mut core::ffi::c_void,
144 >,
145 arg: *mut core::ffi::c_void,
146 ) -> i8;
147}
148unsafe extern "C" {
149 #[doc = " Block until `task` exits. Cleans up task storage on success."]
150 pub fn nros_platform_task_join(task: *mut core::ffi::c_void) -> i8;
151}
152unsafe extern "C" {
153 #[doc = " Mark `task` as detached — its storage is reclaimed on exit without\n a join."]
154 pub fn nros_platform_task_detach(task: *mut core::ffi::c_void) -> i8;
155}
156unsafe extern "C" {
157 #[doc = " Request `task` to terminate at the next cancellation point.\n Cooperative: a task that never reaches a cancel point will not stop."]
158 pub fn nros_platform_task_cancel(task: *mut core::ffi::c_void) -> i8;
159}
160unsafe extern "C" {
161 #[doc = " Terminate the calling task immediately. Does not return."]
162 pub fn nros_platform_task_exit();
163}
164unsafe extern "C" {
165 #[doc = " Free task storage allocated by `task_init`. Called after `task_join`\n or `task_detach + exit`."]
166 pub fn nros_platform_task_free(task: *mut *mut core::ffi::c_void);
167}
168unsafe extern "C" {
169 #[doc = " Opaque-storage sizing for `task`, mirroring the wake primitive's\n probes below. Both are pure functions (no global state) and may be\n called before `nros_platform_task_init`.\n\n phase-359 W10 — added because `task_init`'s \"size determined by the\n implementor\" had no way to ASK. A C caller can write\n `pthread_t t;` and pass `&t`; a Rust caller cannot, and hard-coding\n a size is precisely issue 0570 (Rust's 20-byte `pthread_attr_t` met\n NuttX's 56-byte one and smashed the caller's frame). The wake\n primitive already solved this the right way; tasks now match it."]
170 pub fn nros_platform_task_storage_size() -> usize;
171}
172unsafe extern "C" {
173 pub fn nros_platform_task_storage_align() -> usize;
174}
175unsafe extern "C" {
176 #[doc = " Opaque-storage sizing for the lock family, matching `wake` and `task`.\n Pure functions, callable before the corresponding `_init`."]
177 pub fn nros_platform_mutex_storage_size() -> usize;
178}
179unsafe extern "C" {
180 pub fn nros_platform_mutex_storage_align() -> usize;
181}
182unsafe extern "C" {
183 pub fn nros_platform_mutex_rec_storage_size() -> usize;
184}
185unsafe extern "C" {
186 pub fn nros_platform_mutex_rec_storage_align() -> usize;
187}
188unsafe extern "C" {
189 pub fn nros_platform_condvar_storage_size() -> usize;
190}
191unsafe extern "C" {
192 pub fn nros_platform_condvar_storage_align() -> usize;
193}
194unsafe extern "C" {
195 pub fn nros_platform_mutex_init(m: *mut core::ffi::c_void) -> i8;
196}
197unsafe extern "C" {
198 pub fn nros_platform_mutex_drop(m: *mut core::ffi::c_void) -> i8;
199}
200unsafe extern "C" {
201 pub fn nros_platform_mutex_lock(m: *mut core::ffi::c_void) -> i8;
202}
203unsafe extern "C" {
204 pub fn nros_platform_mutex_try_lock(m: *mut core::ffi::c_void) -> i8;
205}
206unsafe extern "C" {
207 pub fn nros_platform_mutex_unlock(m: *mut core::ffi::c_void) -> i8;
208}
209unsafe extern "C" {
210 #[doc = " Initialise a recursive mutex (same-thread re-entry permitted).\n Required by zenoh-pico."]
211 pub fn nros_platform_mutex_rec_init(m: *mut core::ffi::c_void) -> i8;
212}
213unsafe extern "C" {
214 pub fn nros_platform_mutex_rec_drop(m: *mut core::ffi::c_void) -> i8;
215}
216unsafe extern "C" {
217 pub fn nros_platform_mutex_rec_lock(m: *mut core::ffi::c_void) -> i8;
218}
219unsafe extern "C" {
220 pub fn nros_platform_mutex_rec_try_lock(m: *mut core::ffi::c_void) -> i8;
221}
222unsafe extern "C" {
223 pub fn nros_platform_mutex_rec_unlock(m: *mut core::ffi::c_void) -> i8;
224}
225unsafe extern "C" {
226 pub fn nros_platform_condvar_init(cv: *mut core::ffi::c_void) -> i8;
227}
228unsafe extern "C" {
229 pub fn nros_platform_condvar_drop(cv: *mut core::ffi::c_void) -> i8;
230}
231unsafe extern "C" {
232 pub fn nros_platform_condvar_signal(cv: *mut core::ffi::c_void) -> i8;
233}
234unsafe extern "C" {
235 pub fn nros_platform_condvar_signal_all(cv: *mut core::ffi::c_void) -> i8;
236}
237unsafe extern "C" {
238 #[doc = " Phase 124.B.7.a — ISR-safe signal.\n\n Callable from interrupt context. `nros_platform_condvar_signal`\n is NOT ISR-safe on every platform (POSIX `pthread_cond_signal`\n isn't on the async-signal-safe function list; RTOS condvar\n primitives often require thread context). Backends MUST use\n this variant when triggering from an ISR or POSIX signal handler.\n\n Per-platform implementation:\n * POSIX: `pipe` write — async-signal-safe; a runtime worker thread\n forwards to the underlying condvar. (Linux may use `eventfd`\n instead, which is NOT POSIX — `signalfd`/`eventfd` are Linux\n syscalls, which is why `nros-node`'s worker is\n `target_os = \"linux\"`-gated.)\n * Zephyr: `k_sem_give` on the wake semaphore (ISR-safe).\n * FreeRTOS: `xSemaphoreGiveFromISR` + `portYIELD_FROM_ISR` on\n the wake semaphore.\n * NuttX: `sem_post` (POSIX-safe under NuttX) on the wake sem.\n * ThreadX: `tx_event_flags_set` on the wake event flag group\n (ISR-safe).\n * Bare-metal: atomic flag store + `__SEV()` (Cortex-M).\n\n Returns non-zero on error (e.g. ISR-unsafe call on a backend\n that mandates ISR-context-only via a separate primitive).\n Backends without an ISR-safe path return non-zero so callers\n can fall back to thread-context signal (with the obvious\n latency cost)."]
239 pub fn nros_platform_condvar_signal_from_isr(cv: *mut core::ffi::c_void) -> i8;
240}
241unsafe extern "C" {
242 #[doc = " Atomically release `m` and block on `cv`. The mutex is re-acquired\n before this function returns."]
243 pub fn nros_platform_condvar_wait(cv: *mut core::ffi::c_void, m: *mut core::ffi::c_void) -> i8;
244}
245unsafe extern "C" {
246 #[doc = " Like `condvar_wait`, but with an absolute monotonic deadline in\n MILLISECONDS on the `nros_platform_clock_ns()` epoch — i.e.\n `clock_ns() / 1000000`. Returns non-zero on timeout.\n\n Spelt out because this said \"`clock_ms` units\" after RFC-0073 /\n phase-352 W6 retired `nros_platform_clock_ms`: it named a function\n that no longer exists, leaving a port author no way to resolve the\n unit from this header. The unit itself never changed — every port\n names the parameter `abstime_ms` and the Rust trait says\n milliseconds — so this is the wording catching up, not an ABI\n change."]
247 pub fn nros_platform_condvar_wait_until(
248 cv: *mut core::ffi::c_void,
249 m: *mut core::ffi::c_void,
250 abstime: u64,
251 ) -> i8;
252}
253unsafe extern "C" {
254 pub fn nros_platform_wake_init(w: *mut core::ffi::c_void) -> i8;
255}
256unsafe extern "C" {
257 pub fn nros_platform_wake_drop(w: *mut core::ffi::c_void) -> i8;
258}
259unsafe extern "C" {
260 pub fn nros_platform_wake_wait_ms(w: *mut core::ffi::c_void, timeout_ms: u32) -> i8;
261}
262unsafe extern "C" {
263 pub fn nros_platform_wake_signal(w: *mut core::ffi::c_void) -> i8;
264}
265unsafe extern "C" {
266 pub fn nros_platform_wake_signal_from_isr(w: *mut core::ffi::c_void) -> i8;
267}
268unsafe extern "C" {
269 #[doc = " Opaque-storage sizing. Both helpers are pure functions (no global\n state) and may be called before `nros_platform_wake_init`."]
270 pub fn nros_platform_wake_storage_size() -> usize;
271}
272unsafe extern "C" {
273 pub fn nros_platform_wake_storage_align() -> usize;
274}
275unsafe extern "C" {
276 pub fn nros_platform_critical_section_acquire() -> u32;
277}
278unsafe extern "C" {
279 pub fn nros_platform_critical_section_release(token: u32);
280}
281unsafe extern "C" {
282 pub fn nros_platform_log_write(
283 severity: u8,
284 name_ptr: *const u8,
285 name_len: usize,
286 msg_ptr: *const u8,
287 msg_len: usize,
288 );
289}
290unsafe extern "C" {
291 pub fn nros_platform_log_flush();
292}
293unsafe extern "C" {
294 pub fn nros_platform_register_log_writer(
295 writer: nros_platform_log_writer_fn_t,
296 flusher: nros_platform_log_flush_fn_t,
297 );
298}
299unsafe extern "C" {
300 pub fn nros_platform_panic(msg: *const core::ffi::c_char, len: usize);
301}
302unsafe extern "C" {
303 #[doc = " Resolve `(address, port)` strings into the caller-allocated endpoint\n storage at `ep`. Both strings are NUL-terminated."]
304 pub fn nros_platform_tcp_create_endpoint(
305 ep: *mut core::ffi::c_void,
306 address: *const u8,
307 port: *const u8,
308 ) -> i8;
309}
310unsafe extern "C" {
311 #[doc = " Release any resources held by the endpoint at `ep`."]
312 pub fn nros_platform_tcp_free_endpoint(ep: *mut core::ffi::c_void);
313}
314unsafe extern "C" {
315 #[doc = " Open a TCP client connection to `endpoint`."]
316 pub fn nros_platform_tcp_open(
317 sock: *mut core::ffi::c_void,
318 endpoint: *const core::ffi::c_void,
319 timeout_ms: u32,
320 ) -> i8;
321}
322unsafe extern "C" {
323 #[doc = " Open a listening TCP socket bound to `endpoint`."]
324 pub fn nros_platform_tcp_listen(
325 sock: *mut core::ffi::c_void,
326 endpoint: *const core::ffi::c_void,
327 ) -> i8;
328}
329unsafe extern "C" {
330 #[doc = " Close a TCP socket."]
331 pub fn nros_platform_tcp_close(sock: *mut core::ffi::c_void);
332}
333unsafe extern "C" {
334 #[doc = " Read up to `len` bytes. Returns bytes received, or\n `NROS_PLATFORM_NET_SOCKET_ERROR` on error."]
335 pub fn nros_platform_tcp_read(
336 sock: *const core::ffi::c_void,
337 buf: *mut u8,
338 len: usize,
339 ) -> usize;
340}
341unsafe extern "C" {
342 #[doc = " Read exactly `len` bytes. Returns `len` on success, or\n `NROS_PLATFORM_NET_SOCKET_ERROR` on error."]
343 pub fn nros_platform_tcp_read_exact(
344 sock: *const core::ffi::c_void,
345 buf: *mut u8,
346 len: usize,
347 ) -> usize;
348}
349unsafe extern "C" {
350 #[doc = " Send `len` bytes. Returns bytes sent, or\n `NROS_PLATFORM_NET_SOCKET_ERROR` on error."]
351 pub fn nros_platform_tcp_send(
352 sock: *const core::ffi::c_void,
353 buf: *const u8,
354 len: usize,
355 ) -> usize;
356}
357unsafe extern "C" {
358 pub fn nros_platform_udp_create_endpoint(
359 ep: *mut core::ffi::c_void,
360 address: *const u8,
361 port: *const u8,
362 ) -> i8;
363}
364unsafe extern "C" {
365 pub fn nros_platform_udp_free_endpoint(ep: *mut core::ffi::c_void);
366}
367unsafe extern "C" {
368 pub fn nros_platform_udp_open(
369 sock: *mut core::ffi::c_void,
370 endpoint: *const core::ffi::c_void,
371 timeout_ms: u32,
372 ) -> i8;
373}
374unsafe extern "C" {
375 #[doc = " Bind a UDP socket in listen / server mode. Optional — return -1\n on platforms that don't expose a UDP-server primitive."]
376 pub fn nros_platform_udp_listen(
377 sock: *mut core::ffi::c_void,
378 endpoint: *const core::ffi::c_void,
379 timeout_ms: u32,
380 ) -> i8;
381}
382unsafe extern "C" {
383 pub fn nros_platform_udp_close(sock: *mut core::ffi::c_void);
384}
385unsafe extern "C" {
386 pub fn nros_platform_udp_read(
387 sock: *const core::ffi::c_void,
388 buf: *mut u8,
389 len: usize,
390 ) -> usize;
391}
392unsafe extern "C" {
393 pub fn nros_platform_udp_read_exact(
394 sock: *const core::ffi::c_void,
395 buf: *mut u8,
396 len: usize,
397 ) -> usize;
398}
399unsafe extern "C" {
400 #[doc = " Send `len` bytes to `endpoint`."]
401 pub fn nros_platform_udp_send(
402 sock: *const core::ffi::c_void,
403 buf: *const u8,
404 len: usize,
405 endpoint: *const core::ffi::c_void,
406 ) -> usize;
407}
408unsafe extern "C" {
409 #[doc = " Set the recv timeout in milliseconds; `0` means block indefinitely."]
410 pub fn nros_platform_udp_set_recv_timeout(sock: *const core::ffi::c_void, timeout_ms: u32);
411}
412unsafe extern "C" {
413 pub fn nros_platform_udp_mcast_open(
414 sock: *mut core::ffi::c_void,
415 endpoint: *const core::ffi::c_void,
416 lep: *mut core::ffi::c_void,
417 timeout_ms: u32,
418 iface: *const u8,
419 ) -> i8;
420}
421unsafe extern "C" {
422 pub fn nros_platform_udp_mcast_listen(
423 sock: *mut core::ffi::c_void,
424 endpoint: *const core::ffi::c_void,
425 timeout_ms: u32,
426 iface: *const u8,
427 join: *const u8,
428 ) -> i8;
429}
430unsafe extern "C" {
431 pub fn nros_platform_udp_mcast_close(
432 sockrecv: *mut core::ffi::c_void,
433 socksend: *mut core::ffi::c_void,
434 rep: *const core::ffi::c_void,
435 lep: *const core::ffi::c_void,
436 );
437}
438unsafe extern "C" {
439 pub fn nros_platform_udp_mcast_read(
440 sock: *const core::ffi::c_void,
441 buf: *mut u8,
442 len: usize,
443 lep: *const core::ffi::c_void,
444 addr: *mut core::ffi::c_void,
445 ) -> usize;
446}
447unsafe extern "C" {
448 pub fn nros_platform_udp_mcast_read_exact(
449 sock: *const core::ffi::c_void,
450 buf: *mut u8,
451 len: usize,
452 lep: *const core::ffi::c_void,
453 addr: *mut core::ffi::c_void,
454 ) -> usize;
455}
456unsafe extern "C" {
457 pub fn nros_platform_udp_mcast_send(
458 sock: *const core::ffi::c_void,
459 buf: *const u8,
460 len: usize,
461 endpoint: *const core::ffi::c_void,
462 ) -> usize;
463}
464unsafe extern "C" {
465 #[doc = " Switch a socket to non-blocking mode."]
466 pub fn nros_platform_socket_set_non_blocking(sock: *const core::ffi::c_void) -> i8;
467}
468unsafe extern "C" {
469 #[doc = " Accept a pending connection from `sock_in` into `sock_out`."]
470 pub fn nros_platform_socket_accept(
471 sock_in: *const core::ffi::c_void,
472 sock_out: *mut core::ffi::c_void,
473 ) -> i8;
474}
475unsafe extern "C" {
476 #[doc = " Socket-layer shutdown + close. Distinct from\n `nros_platform_tcp_close` because zenoh-pico's helper layer\n exposes both."]
477 pub fn nros_platform_socket_close(sock: *mut core::ffi::c_void);
478}
479unsafe extern "C" {
480 #[doc = " Wait for socket events on a multi-peer set. Optional on platforms\n without a poll/select primitive."]
481 pub fn nros_platform_socket_wait_event(
482 peers: *mut core::ffi::c_void,
483 mutex: *mut core::ffi::c_void,
484 ) -> i8;
485}
486unsafe extern "C" {
487 #[doc = " Pump the underlying network stack to process pending I/O.\n No-op on platforms with a kernel-driven socket layer (POSIX,\n Zephyr, lwIP, NetX Duo). Bare-metal smoltcp targets advance\n the stack from this entry point."]
488 pub fn nros_platform_network_poll();
489}
490unsafe extern "C" {
491 #[doc = " Register a periodic timer that invokes `callback(user_data)` every\n `period_us` microseconds. Returns the platform-native handle on\n success, NULL on failure."]
492 pub fn nros_platform_timer_create_periodic(
493 period_us: u32,
494 callback: nros_platform_timer_callback_t,
495 user_data: *mut core::ffi::c_void,
496 ) -> *mut core::ffi::c_void;
497}
498unsafe extern "C" {
499 #[doc = " Register a one-shot timer that invokes `callback(user_data)` once\n after `timeout_us` microseconds. Returns the platform-native\n handle on success, NULL on failure."]
500 pub fn nros_platform_timer_create_oneshot(
501 timeout_us: u32,
502 callback: nros_platform_timer_callback_t,
503 user_data: *mut core::ffi::c_void,
504 ) -> *mut core::ffi::c_void;
505}
506unsafe extern "C" {
507 #[doc = " Cancel + free the timer. Drains in-flight callback invocations\n before returning so `user_data` is no longer accessed. Idempotent\n on already-destroyed handles."]
508 pub fn nros_platform_timer_destroy(handle: *mut core::ffi::c_void);
509}
510unsafe extern "C" {
511 #[doc = " Cancel a previously-armed timer. Returns:\n\n - 1 if cancellation prevented the callback from firing,\n - 0 if the callback already fired (or the timer was already\n cancelled / destroyed),\n - -1 on unrecoverable error.\n\n Distinct from `destroy` — the handle remains valid after\n `cancel` and may be re-armed by the application's own\n bookkeeping if the implementation supports it."]
512 pub fn nros_platform_timer_cancel(handle: *mut core::ffi::c_void) -> i8;
513}