API index
Every C function, linked to what it doesThe whole medius_* surface from medius.h, grouped. Each row is the C signature and a one-line summary; follow the link for what the call does. The semantics live in the Rust library (the medius crate) and the Native API, not here. Structs, enums, and constants are on Types & errors; streams on Streams.
Most calls are fire-and-forget. They return as soon as the frame is queued and never wait on the box. The queries, plus open / find, block for the box's reply. Every fallible call returns a MediusStatus (MEDIUS_STATUS_OK is 0) and writes its result through an out-param; medius_last_error_message() gives the last failure's text on the calling thread.
MediusDevice *dev = NULL;
if (medius_device_find(&dev) != MEDIUS_STATUS_OK) {
char buf[256];
medius_last_error_message(buf, sizeof buf); /* why it failed */
return 1;
}
MediusVersion v;
medius_device_query_version(dev, &v); /* result written to &v */
medius_device_free(dev);Opaque handles (MediusDevice, MediusEventStream, MediusLogStream, MediusMockBox) each have a *_free; you own them. Catch events and log lines are fixed-size structs, so there is nothing to free per event.
Connecting & lifecycle
Open, share, and release the linkSee Connection and Lifecycle.
| Function | Does |
|---|---|
medius_device_open(const char *path, MediusDevice **out) | Open a serial path and handshake. |
medius_device_find(MediusDevice **out) | Open the first box found by USB id. |
medius_device_clone(const MediusDevice *dev) | Another handle to the same link (ref-counted); returns MediusDevice *. Null in → null out. |
medius_device_free(MediusDevice *dev) | Free a handle; joins the reader/keepalive threads when the last clone drops. Null is a no-op. |
medius_find_ports(MediusPortInfo *out, uintptr_t cap, uintptr_t *out_total) | List present ports into out (up to cap); writes total to *out_total, returns the number written. See MediusPortInfo. |
Discovery
Enumerate boxes and open one by identityPick a box out of several by a stable identity (device MAC or CH343 serial), or by the kind of device it clones. See Discovery.
| Function | Does |
|---|---|
medius_list(MediusBoxInfo *out, uintptr_t cap, uintptr_t *out_total) | Enumerate every connected box into out (up to cap): opens, handshakes, and reads each one's version + cloned-device info. Writes the total to *out_total, returns the number written. See MediusBoxInfo. |
medius_device_open_by_id(const char *id, MediusDevice **out) | Open the box whose identity matches id (device MAC hex or CH343 serial) and handshake. |
medius_device_find_mouse_box(MediusDevice **out) | Open the first box whose clone is a mouse. |
medius_device_find_keyboard_box(MediusDevice **out) | Open the first box whose clone is a keyboard. |
Movement
Relative cursor and wheelSee Move. +x right, +y down. Build the axis struct with the motion helpers.
| Function | Does |
|---|---|
medius_device_move_rel(MediusDevice *dev, int16_t dx, int16_t dy) | Nudge the cursor by a signed 16-bit delta. |
medius_device_wheel(MediusDevice *dev, int16_t delta) | Scroll the wheel. |
medius_device_move_axis(MediusDevice *dev, MediusMotion motion) | Drive one axis from a medius_motion_cursor(...) or medius_motion_wheel(...). |
Inject
Drive any usage: button, key, or mediaOne verb set over a MediusUsage (button, key, or media). Build it with the input helpers; see Inject, the injection model, and the id spaces on Usage IDs.
| Function | Does |
|---|---|
medius_device_inject(MediusDevice *dev, MediusUsage input, MediusAction action) | Apply a MediusAction to a usage. |
medius_device_press(MediusDevice *dev, MediusUsage input) | Hold the usage down (MEDIUS_ACTION_PRESS). |
medius_device_soft_release(MediusDevice *dev, MediusUsage input) | Release, unless the user is physically holding it. |
medius_device_force_release(MediusDevice *dev, MediusUsage input) | Release even against a physical hold. |
A MediusKey or MediusMediaKey is a raw HID usage.
Locks
Block the user's own inputSee Lock. A MediusLockTarget picks an axis or usage (button, key, or media) and a MediusLockDirection picks an edge. Read the returned entries with medius_locks_is_locked.
| Function | Does |
|---|---|
medius_device_lock(MediusDevice *dev, MediusLockTarget target, MediusLockDirection dir) | Lock an axis or usage on an edge. |
medius_device_unlock(MediusDevice *dev, MediusLockTarget target, MediusLockDirection dir) | Release a lock. |
medius_device_lock_all(MediusDevice *dev, MediusBlanket what, MediusLockDirection dir) | Blanket lock a whole class (aim, wheel, buttons, keys, or media). |
medius_device_unlock_all(MediusDevice *dev, MediusBlanket what, MediusLockDirection dir) | Release a blanket lock. |
LED, admin & options
Status light, resets, persistent settings| Function | Does |
|---|---|
medius_device_led(MediusDevice *dev, MediusLedTarget target, MediusLedMode mode, uint8_t level) | Drive the status LED. See LED. |
medius_device_reset(MediusDevice *dev) | Clear all overrides. See Admin. |
medius_device_reapply(MediusDevice *dev) | Re-send the active settings. |
medius_device_reconnect(MediusDevice *dev) | Force a reconnect to the mouse. |
medius_device_reboot(MediusDevice *dev, MediusRebootTarget target) | Reboot a chip to run or download mode. |
medius_device_allow_imperfect_clones(MediusDevice *dev, bool allow) | Opt in to cloning over-capacity devices. See Options. |
medius_device_set_movement_riding(MediusDevice *dev, bool enabled, uint32_t window_ms) | Set movement riding; enabled == false clears the window (rounded to whole ms). |
medius_device_set_emit_pace(MediusDevice *dev, MediusEmitMode mode, uint16_t hz) | Pick what paces injected motion; hz is the target rate for FIXED. See Options. |
medius_device_set_name(MediusDevice *dev, const char *name) | Set the box's human-readable name (1 to 32 printable ASCII). See Name. |
medius_device_clear_name(MediusDevice *dev) | Clear the name, back to the synthesized default. Read it back on MediusVersion.name. |
Queries
Read box state; each blocks for one replySee Requests. Each blocks for the box's reply, writes a struct documented on Types & errors, and returns MEDIUS_STATUS_ERR_QUERY_TIMEOUT if no reply arrives.
| Function | Writes to *out |
|---|---|
medius_device_query_version(dev, MediusVersion *out) | MediusVersion: protocol + firmware version. |
medius_device_query_health(dev, MediusHealth *out) | MediusHealth: link, mouse, clone, injection flags. |
medius_device_device_info(dev, MediusDeviceInfo *out) | MediusDeviceInfo: the cloned device's USB identity, kind, and product. |
medius_device_caps(dev, MediusCaps *out) | MediusCaps: mouse/keyboard capabilities. |
medius_device_query_rate(dev, MediusRate *out) | MediusRate: native report rate and poll period. |
medius_device_query_stats(dev, MediusStats *out) | MediusStats: box-side telemetry. |
medius_device_query_locks(dev, MediusLocks *out) | MediusLocks: the active locks (entry list). |
medius_device_query_catch(dev, MediusCatchState *out) | MediusCatchState: subscription mask + dropped count. |
medius_device_query_imperfect(dev, MediusImperfectStatus *out) | MediusImperfectStatus: imperfect-clone state. |
medius_device_query_movement_riding(dev, bool *out_enabled, uint32_t *out_window_ms) | Whether riding is on, and the window in ms (0 when off). |
medius_device_query_emit_pace(dev, MediusEmitPaceStatus *out) | MediusEmitPaceStatus: pacing mode + rate in effect. |
medius_device_counters(dev, MediusCountersSnapshot *out) | MediusCountersSnapshot: host-side wire counters. |
Streams
Subscribe to live input and logsConsuming events is covered on Streams; the catch feature itself on Catch and logs on Logs & counters. medius_device_catch_events takes an OR of the MEDIUS_CATCH_MASK_* bits as its subscription.
| Function | Does |
|---|---|
medius_device_catch_events(MediusDevice *dev, MediusCatchMask mask, MediusEventStream **out) | Subscribe to physical mouse/key/media events. |
medius_event_stream_clone(const MediusEventStream *stream) | Another handle to the same subscription. Null in → null out. |
medius_event_stream_free(MediusEventStream *stream) | Free a handle; the subscription ends with the last one. |
medius_event_stream_recv(stream, MediusCatchEvent *out) | Block for the next event; MEDIUS_STATUS_ERR_DISCONNECTED on close. |
medius_event_stream_try_recv(stream, MediusCatchEvent *out) | Next buffered event; returns false if none (never blocks). |
medius_event_stream_recv_timeout(stream, uint64_t timeout_ms, MediusCatchEvent *out) | Block up to timeout_ms; false on timeout or close. |
medius_event_stream_dropped(stream) | Events dropped because the consumer fell behind. |
medius_device_logs(MediusDevice *dev, MediusLogStream **out) | Open the device log-line stream. |
medius_log_stream_clone / medius_log_stream_free | Clone / free a log-stream handle. |
medius_log_stream_recv / try_recv / recv_timeout(stream, …, MediusLogLine *out) | Pull the next MediusLogLine (block / non-block / timed). |
Buffered clip playback
Preload a per-frame stream, box-clockedBuild an entry stream with an opaque MediusClipBuilder, then drive playback through an opaque MediusClip handle from medius_device_clip. Each owns its allocation: free the builder with medius_clip_builder_free and the handle with medius_clip_free. Concept on Clip.
| Function | Does |
|---|---|
medius_clip_builder_new() / _free(b) / _clear(b) | Allocate / free / reset a builder. |
medius_clip_builder_gap(b, uint16_t frames) | A gap run (0 = no-op). |
medius_clip_builder_move(b, dx, dy) / _wheel(b, dz) | A cursor / wheel motion frame. |
medius_clip_builder_press / _release / _force_release(b, usage) | A one-edge press / soft-release / force-release frame; usage is a MediusUsage (button, key, or media). |
medius_clip_builder_edge(b, usage, action) | A one-edge frame for any MediusUsage with an explicit MediusAction. |
medius_clip_builder_frame(b, dx, dy, wheel, inputs, actions, n) | A motion delta plus up to 8 edges on one frame: parallel MediusUsage / MediusAction arrays. Build the inputs with medius_usage_button/_key/_media. |
MediusClipBuilder *b = medius_clip_builder_new();
/* move (+10, -4) AND press Left on the same frame */
MediusUsage inputs[1] = { medius_usage_button(MEDIUS_BUTTON_LEFT) };
MediusAction actions[1] = { MEDIUS_ACTION_PRESS };
medius_clip_builder_frame(b, 10, -4, 0, inputs, actions, 1);| Function | Effect |
|---|---|
medius_device_clip(dev, out) / medius_clip_free(clip) | Open / free a clip handle. |
medius_clip_append(clip, b) | Append the builder's entries to the ring. |
medius_clip_set_autolock(clip, const MediusBlanket *scope, uintptr_t scope_len) | The auto-lock scope: the MediusBlanket groups scope points at (NULL / 0 = no lock). Set before the first append. |
medius_clip_set_loop(clip, uint8_t on) / _set_retain(clip, uint8_t on) | Loop at the clip end (retained only) / retain the loaded clip so it can rewind and replay (0 = streaming, the default). |
medius_clip_finalize(clip) | Fix a retained clip's end so it can replay and loop. |
medius_clip_bind(clip, MediusClipTrigger trigger) | Add or overwrite a MediusClipTrigger: a MediusEdge of on drives a MediusClipAction; consume hides the input from the game. |
medius_clip_unbind(clip, MediusUsage usage, MediusEdge edge) / _clear_triggers(clip) | Remove the binding on that usage + edge; drop every binding. |
medius_clip_start(clip) / _stop(clip) | Rewind and play (or resume a pause) / stop, flush a streaming clip (rewind a retained one), and release held input and the auto-lock. |
medius_clip_pause(clip) / _resume(clip) | Halt mid-clip, retaining the cursor and held input / continue from the paused cursor. |
medius_clip_restart(clip) / _toggle(clip) | Force a rewind and play, even mid-playback / play if idle or paused, stop if playing. |
medius_clip_clear(clip) | Discard the loaded clip, free the ring, and clear a Faulted state. |
medius_clip_query_status(clip, out) | Fill a MediusClipStatus: ring depth, progress, and playback counters. |
medius_clip_query_config(clip, out) | Fill a MediusClipSettings: auto-lock scope, loop/retain, finalized, and the trigger set. |
Usage, motion & lock-target builders
Make the value structs the calls takePure constructors: no device, no wire traffic. See Inject, Move, and Lock.
| Function | Returns |
|---|---|
medius_usage_button(MediusButton button) | MediusUsage for medius_device_inject. |
medius_usage_key(MediusKey key) | MediusUsage addressing a keyboard key. |
medius_usage_media(MediusMediaKey media) | MediusUsage addressing a media key. |
medius_motion_cursor(int16_t dx, int16_t dy) | MediusMotion for medius_device_move_axis. |
medius_motion_wheel(int16_t delta) | MediusMotion for a wheel scroll. |
medius_lock_target_axis(MediusLockTargetKind kind) | MediusLockTarget for an axis (X / Y / Wheel). |
medius_lock_target_usage(MediusUsage usage) | MediusLockTarget for a usage (button, key, or media). |
Struct inspectors
Read query / event results without the wireHelpers that interpret a struct you already have. They take it by value (or pointer) and do no I/O. Each mirrors the matching method on the Rust type.
| Function | Returns |
|---|---|
medius_locks_is_locked(const MediusLocks *locks, MediusLockTarget target, MediusLockDirection dir) | bool: is that target/edge locked (Both needs both edges). See Lock. |
medius_rate_native_hz(MediusRate rate, float *out_hz) | bool: writes the native rate in Hz; false when there is no continuous cadence. |
medius_usage_event_is_held(const MediusUsageEvent *event, MediusUsage usage) | bool: is that usage (button, key, or media) held in the snapshot. |
medius_clip_status_is_held(const MediusClipStatus *status, MediusUsage usage) | bool: is the clip holding that usage down. |
medius_caps_has_mouse(MediusCaps caps) | bool: a mouse interface is bound. See Requests. |
medius_caps_has_keyboard(MediusCaps caps) | bool: a keyboard interface is bound. |
medius_caps_is_composite(MediusCaps caps) | bool: the clone is multi-HID-interface. |
Global functions
Library-level helpers and errors| Function | Does |
|---|---|
medius_last_error_message(char *buf, uintptr_t cap) | Copy the last error's text into buf; returns the full length (size a buffer and retry). See errors. |
medius_last_error_proto_ver() | The proto-version byte from the last MEDIUS_STATUS_ERR_BAD_PROTO_VER, or 0. |
medius_default_query_timeout_ms() | The default query reply wait, in ms. |
medius_default_keepalive_cadence_ms() | The default keepalive interval, in ms. |
medius_abi_version() | The C ABI version (bumped on any breaking header change). |
medius_version_string() | The crate version as a static NUL-terminated string. |
medius_flash(const char *port, const char *bin_path, bool host) | Flash firmware via esptool. MEDIUS_FEATURE_FLASH only; see Flash and Build & features. |
Mock box
Scriptable fake for tests, feature-gatedAll of these are wrapped in #ifdef MEDIUS_FEATURE_MOCK (the mock cargo feature). The concept lives on Mock; turning the feature on is on Build & features.
| Function | Does |
|---|---|
medius_mock_new() | A fresh mock that records commands and auto-answers queries. |
medius_mock_clone / medius_mock_free(MediusMockBox *mock) | Share (same state) / free a mock handle. |
medius_device_with_mock(const MediusMockBox *mock, MediusDevice **out) | Build a MediusDevice over the mock without a handshake. |
medius_device_open_mock(const MediusMockBox *mock, MediusDevice **out) | Build a MediusDevice over the mock and run the handshake. |
medius_mock_set_version / _health / _device_info / _caps / _mouse_caps / _kbd_caps / _rate / _stats / _locks / _catch_state / _imperfect_status | Set the value the mock answers to each query. |
medius_mock_set_movement_riding(mock, bool enabled, uint32_t window_ms) | Set the movement-riding window the mock reports. |
medius_mock_silent(MediusMockBox *mock) | Stop answering queries for timeout tests (still records). |
medius_mock_push_raw(mock, const uint8_t *bytes, uintptr_t len) | Inject raw inbound bytes, as if the box sent them. |
medius_mock_push_log(mock, MediusLogLevel level, const char *text) | Push a LOG line onto the device's log stream. |
medius_mock_push_motion(mock, uint8_t seq, MediusMotionEvent event) | Push a MediusMotionEvent as a Motion catch event. |
medius_mock_push_usages(mock, uint8_t seq, const MediusUsageEvent *event) | Push a MediusUsageEvent as a Usages catch event. |
medius_mock_recorded(MediusMockBox *mock) | How many commands the host has sent. |
medius_mock_saw(mock, MediusFrameType ty) | Whether at least one frame of that type was sent. |
medius_mock_clear_recorded(MediusMockBox *mock) | Clear the recorded-command log. |
medius_mock_recorded_frame(mock, uintptr_t idx, MediusFrameType *out_ty, uint8_t *out_seq, uint8_t *payload_buf, uintptr_t cap) | Read recorded frame idx: type, SEQ, and payload bytes. |