First program
One file: connect, read the firmware version, move, click, wait for one native motion event, free.
Every fallible call returns a MediusStatus; medius_last_error_message has the detail. What the commands mean is in the Library and Native sections.
medius.h and the library: Build & features. New to the box? Start with the Native quickstart.
find() ──▶ open + handshake blocks query_version() ──▶ read the version blocks move() / press() ──▶ inject input fire-and-forget catch_events() ──▶ subscribe by filter fire-and-forget recv() ──▶ next native event blocks free() ──▶ close, NULL-safe local
ProgramEvery call, with error checks
#include <stdio.h>
#include <medius.h>
/* 0 on success; 1 on failure, after printing the last error */
static int check(MediusStatus s, const char *what) {
if (s == MEDIUS_STATUS_OK) return 0;
char msg[256];
medius_last_error_message(msg, sizeof msg); /* detail for the last failure */
fprintf(stderr, "%s failed (status %d): %s\n", what, (int)s, msg);
return 1;
}
int main(void) {
MediusDevice *dev = NULL;
if (check(medius_device_find(&dev), "find")) /* open first box + handshake */
return 1;
printf("medius-capi %s (abi %u)\n", medius_version_string(), medius_abi_version());
MediusVersion v;
if (!check(medius_device_query_version(dev, &v), "query_version"))
printf("firmware %u.%u.%u (proto %u)\n", v.fw_major, v.fw_minor, v.fw_patch, v.proto_ver);
check(medius_device_move_rel(dev, 100, -50), "move_rel"); /* fire-and-forget */
check(medius_device_press(dev, medius_usage_button(MEDIUS_BUTTON_LEFT)), "press");
check(medius_device_soft_release(dev, medius_usage_button(MEDIUS_BUTTON_LEFT)), "release");
/* one subscription entry: X, Y, the wheel and AC Pan, both directions */
MediusCatchFilter axes = medius_catch_filter_watch_axes();
MediusEventStream *events = NULL;
if (!check(medius_device_catch_events(dev, &axes, 1, &events), "catch_events")) {
MediusCatchEvent ev; /* blocks for one native event */
if (medius_event_stream_recv(events, &ev) == MEDIUS_STATUS_OK &&
ev.kind == MEDIUS_CATCH_EVENT_KIND_MOTION)
printf("motion: dx=%d dy=%d dz=%d\n",
ev.data.motion.dx, ev.data.motion.dy, ev.data.motion.dz);
medius_event_stream_free(events); /* unsubscribe */
}
medius_device_free(dev); /* close link, join threads */
return 0;
}medius-capi 3.4.6 (abi 10)
firmware 3.4.6 (proto 9)
motion: dx=12 dy=-4 dz=0The subscription is an array of MediusCatchFilter entries; this program passes one. Add medius_catch_filter_watch_class for keys, or medius_catch_filter_traffic for a vendor endpoint's raw packets.
The call reads the array without retaining it, so a local is fine. All helpers: API index.
medius_event_stream_recv blocks until the filters match an event (here, a native mouse motion). Polling, more classes and event loops are on Streams.
Run it gcc or clang, link libmedius_capi
Run from the unpacked release (medius.h under include/, libmedius_capi.so under lib/). cc, gcc, and clang all work.
cc first.c -Iinclude -Llib -lmedius_capi -o first
LD_LIBRARY_PATH=lib ./first # so the loader finds libmedius_capi.so| Flag | Effect |
|---|---|
-Iinclude | Where medius.h lives. |
-Llib | Where libmedius_capi lives. |
-lmedius_capi | Link the library (file name is libmedius_capi). |
Static linking (libmedius_capi.a), Windows, and the mock feature macro are on Build & features.
WalkthroughErrors, out-params, freeing, blocking
| Mechanic | In C |
|---|---|
| Errors | Every fallible call returns a MediusStatus: MEDIUS_STATUS_OK (0) or a failure. Read the text with medius_last_error_message(buf, cap) right after the failing call. |
| Results | Data comes back through an out-pointer: medius_device_query_version(dev, &v) fills v. |
| Freeing | Each handle has a *_free: medius_device_free, medius_event_stream_free, medius_log_stream_free, each a no-op on NULL. Catch events are fixed-size structs with nothing to free. |
| Fire-and-forget | move_rel, wheel, press, inject, and the lock / LED calls queue a frame and return at once (the fire-and-forget model). |
| Blocks | medius_device_find / _open (the handshake), every medius_device_query_*, and medius_event_stream_recv wait for a reply or an event. |
| Sharing | medius_device_clone / medius_event_stream_clone return another handle to the same link; free each clone. See Lifecycle. |
MediusStatus medius_device_find(MediusDevice **out); uintptr_t medius_last_error_message(char *buf, uintptr_t cap); /* returns full length */
medius_last_error_message holds the calling thread's latest failure; read it before the next call overwrites it. It returns the full length (excluding the NUL); retry with a larger buffer if it was truncated.
Call reference Each call's Library and Native page
| Call | Pages |
|---|---|
medius_device_find | Connection · the handshake |
medius_device_query_version | Requests |
medius_device_move_rel | Move · Native move |
medius_device_press / _soft_release | Inject · the injection model |
medius_device_catch_events / medius_event_stream_recv | Catch · in C, Streams |
medius_device_free | Lifecycle |
API index and Types & errors list every call and type; both mirror the medius crate (source).