Medius - Rust LibraryOptions

Options

Persistent box settings

Options are persistent box settings, each one set and read on its own. There are four: imperfect clones, movement riding, emit-rate pacing, and the box name. All persist in NVS and survive a reboot. See the native OPTION command for the wire contract.

OptionSetRead
imperfect cloneallow_imperfect_clonesquery_imperfect
movement ridingset_movement_ridingquery_movement_riding
emit-rate pacingset_emit_pacequery_emit_pace
box nameset_name / clear_nameVersion::name

allow_imperfect_clones

Clone an over-capacity device anyway
fn allow_imperfect_clones(&self, allow: bool) -> Result<()>

Fire-and-forget

By default the box refuses a device it can't clone faithfully. true opts into cloning an over-capacity device anyway, the rest faithful and the over-capacity interface dead; false is faithful-only (the default). It's persisted in NVS. When the setting changes for an attached over-capacity device the box reboots itself to re-clone, so it lands without unplugging anything; a normal device is unaffected (no reboot).

PARAMETERS
ParameterTypeDescription
allowboolClone an over-capacity device anyway, or stay faithful-only.
EXAMPLE
use medius::Device;

let device = Device::find()?;
device.allow_imperfect_clones(true)?;   // reboots + re-clones if an over-capacity device is attached

set_movement_riding

Inject motion only on a native move
fn set_movement_riding(&self, window: Option<Duration>) -> Result<()>

Fire-and-forget

Some(window) turns movement riding on: injected cursor and wheel motion ride a native cursor-motion report seen within window, the box emits no synthetic motion frame, and motion left unridden past the window is dropped rather than dumped on the next move. So injected motion's report density matches the real mouse's, erasing the density tell. None turns it off (the default). The window rounds to whole milliseconds, a non-zero Some is at least 1 ms, and it clamps to 65535 ms; persisted in NVS.

The tradeoff is deliberate: pure idle injection, moving the cursor while the user holds still, stops working while riding is on. Button, key, and media injection are unaffected.

PARAMETERS
ParameterTypeDescription
windowOption<Duration>Some with the ride window, or None to turn it off.
EXAMPLE
use std::time::Duration;
use medius::Device;

let device = Device::find()?;
device.set_movement_riding(Some(Duration::from_millis(20)))?;  // ride native moves
device.set_movement_riding(None)?;                             // back to gapless fill

set_emit_pace

Pick what paces injected motion
fn set_emit_pace(&self, pace: EmitPace) -> Result<()>

Fire-and-forget

Picks what sets the emit-rate ceiling for injected motion. EmitPace::Learned is the default: the box paces injection to the rate the real mouse actually reports at. EmitPace::Interval paces to the cloned mouse's declared poll rate (itsbInterval). EmitPace::Fixed(hz) paces to a rate you set; the 1 ms frame clock snaps it to 1000/n Hz and caps it at 1 kHz. It raises the ceiling only, so idle stays idle (the box still emits a frame solely when injection is pending). Persisted in NVS.

The learnt default keeps injected motion's cadence matched to the native mouse. The other modes are for a host that models its own report density and wants the box to stop re-pacing an already-shaped stream.

PARAMETERS
ParameterTypeDescription
paceEmitPaceLearned, Interval, or Fixed(hz).
EXAMPLE
use medius::{Device, EmitPace};

let device = Device::find()?;
device.set_emit_pace(EmitPace::Fixed(1000))?;  // emit at a fixed 1 kHz
device.set_emit_pace(EmitPace::Learned)?;      // back to the learnt native pace

set_name

Give the box a human-readable name
fn set_name(&self, name: &str) -> Result<()>

Fire-and-forget

Sets the box's name, its readable partner to the MAC. Like the other setters it sends the value and lets the box own the rules: the firmware keeps the leading printable-ASCII run capped at 32 bytes, and an empty string clears it. Unlike the other options it is read not by a query but off Version::name, like the MAC.

PARAMETERS
ParameterTypeDescription
name&strThe new name, 1 to 32 printable ASCII characters.
EXAMPLE
use medius::Device;

let device = Device::find()?;
device.set_name("Loki")?;              // the box now answers to "Loki"
let name = device.query_version()?.name;  // read it back off Version

clear_name

Back to the synthesized default
fn clear_name(&self) -> Result<()>

Fire-and-forget

Clears the custom name, reverting the box to a firmware-synthesized Medius-XXXX default derived from its MAC.

EXAMPLE
use medius::Device;

let device = Device::find()?;
device.clear_name()?;                  // back to "Medius-XXXX"

query_imperfect

Read the imperfect-clone state
fn query_imperfect(&self) -> Result<ImperfectStatus>

Blocks

Returns an ImperfectStatus: the opt-in toggle, whether the attached device is over-capacity, and whether the live clone went over-capacity anyway with one interface dead.

EXAMPLE
use medius::Device;

let device = Device::find()?;
let status = device.query_imperfect()?;
if status.over_capacity && !status.allowed {
    // the device was refused; opt in to clone it imperfectly
    device.allow_imperfect_clones(true)?;
}

query_movement_riding

Read the ride window
fn query_movement_riding(&self) -> Result<Option<Duration>>

Blocks

Returns the current ride window as a Duration, or None when movement riding is off.

EXAMPLE
use medius::Device;

let device = Device::find()?;
match device.query_movement_riding()? {
    Some(window) => println!("riding, window {window:?}"),
    None => println!("off"),
}

query_emit_pace

Read the pacing mode and rate
fn query_emit_pace(&self) -> Result<EmitPaceStatus>

Blocks

Returns an EmitPaceStatus: the selected EmitPace mode plus resolved_hz, the ceiling actually in effect (0 when the pace is learnt/adaptive, or no device is attached yet in Interval mode).

EXAMPLE
use medius::{Device, EmitPace};

let device = Device::find()?;
let status = device.query_emit_pace()?;
if let EmitPace::Fixed(hz) = status.mode {
    println!("fixed {hz} Hz, emitting at {} Hz", status.resolved_hz);
}

On AsyncDevice

setters fire, queries await

AsyncDevice keeps allow_imperfect_clones, set_movement_riding, set_emit_pace, set_name, and clear_name fire-and-forget (no await) and makes query_imperfect, query_movement_riding, and query_emit_pace futures, like the other queries.

EXAMPLE
use std::time::Duration;
use medius::Device;

let device = Device::find()?.into_async();
device.set_movement_riding(Some(Duration::from_millis(20)))?;  // sync, no await
let window = device.query_movement_riding().await?;            // awaits