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;
}
EXAMPLE OUTPUT
medius-capi 3.4.6 (abi 10)
firmware 3.4.6 (proto 9)
motion: dx=12 dy=-4 dz=0

The 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 itgcc 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
FlagEffect
-IincludeWhere medius.h lives.
-LlibWhere libmedius_capi lives.
-lmedius_capiLink 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

MechanicIn C
ErrorsEvery 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.
ResultsData comes back through an out-pointer: medius_device_query_version(dev, &v) fills v.
FreeingEach 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-forgetmove_rel, wheel, press, inject, and the lock / LED calls queue a frame and return at once (the fire-and-forget model).
Blocksmedius_device_find / _open (the handshake), every medius_device_query_*, and medius_event_stream_recv wait for a reply or an event.
Sharingmedius_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 referenceEach call's Library and Native page

CallPages
medius_device_findConnection · the handshake
medius_device_query_versionRequests
medius_device_move_relMove · Native move
medius_device_press / _soft_releaseInject · the injection model
medius_device_catch_events / medius_event_stream_recvCatch · in C, Streams
medius_device_freeLifecycle

API index and Types & errors list every call and type; both mirror the medius crate (source).