listEnumerate every connected box

fn list() -> Vec<BoxInfo>

Blocks

Returns one BoxInfo per connected box: its Version (protocol, MAC, name) and its cloned DeviceInfo. A box that doesn't speak PROTO_VER has device None, so a box that needs a firmware update still shows up.

EXAMPLE
use medius::Device;

for b in Device::list() {
    // id(): MAC hex; name(): readable label; a DeviceInfo displays as "VVVV:PPPP product".
    match &b.device {
        Some(d) => println!("{}  {}  {}  {}", b.id(), b.name(), d, b.port.path),
        None => println!("{}  {}  protocol {}: update its firmware", b.id(), b.name(), b.version.proto_ver),
    }
}

open_by_idOpen the box with a given identity

fn open_by_id(id: &str) -> Result<Device>

Blocks

Opens the box whose identity matches id: the device chip's MAC hex (Version::mac_hex) or the CH343 serial. Returns Error::BadProtoVer if that box speaks another protocol, or Error::NotFound if no box matches.

EXAMPLE
use medius::{Device, Error};

// the MAC hex printed by Device::list(), stable across replugs:
match Device::open_by_id("123456789abc") {
    Ok(device) => device.move_rel(10, 0)?,
    Err(Error::BadProtoVer { got }) => println!("that box speaks protocol {got}: update its firmware"),
    Err(e) => return Err(e),
}

find_mouse_boxOpen the first box cloning a mouse

fn find_mouse_box() -> Result<Device>

Blocks

Opens the first box whose clone's DeviceKind is a mouse. If no box clones a mouse, a connected box on another protocol (its clone unread) gives Error::BadProtoVer. With neither, it returns Error::NotFound.

EXAMPLE
use medius::Device;

let mouse_box = Device::find_mouse_box()?;
mouse_box.move_rel(10, 0)?;

find_keyboard_boxOpen the first box cloning a keyboard

fn find_keyboard_box() -> Result<Device>

Blocks

find_mouse_box for a keyboard clone, with the same errors.

EXAMPLE
use medius::{Device, Key};

let kbd_box = Device::find_keyboard_box()?;
kbd_box.press(Key::A)?;

find_whereOpen the first box matching a predicate

fn find_where(pred: impl Fn(&BoxInfo) -> bool) -> Result<Device>

Blocks

The general form of the find_*_box helpers. Opens the first box whose BoxInfo satisfies pred, preferring one that speaks PROTO_VER. A match on another protocol returns Error::BadProtoVer, and no match returns Error::NotFound.

EXAMPLE
use medius::Device;

// the box cloning a Logitech device (device is None on a box on another protocol):
let device = Device::find_where(|b| b.device.as_ref().is_some_and(|d| d.vid == 0x046D))?;

Identity & reconnectSame physical box across replugs

A box's identity is its device chip's base MAC (Version::mac_hex) plus the CH343 adapter's serial. Serial paths renumber on replug, but the identity doesn't, so open_by_id re-finds the same box.

Opening a box ties reconnect to that identity. An automatic reconnect re-finds the same physical box across renumbered ports. It never adopts a different box, nor this box once it speaks another protocol.

On AsyncDeviceSame discovery, awaitable device_info

fn AsyncDevice::list() -> Vec<BoxInfo>
fn AsyncDevice::open_by_id(id: &str) -> Result<AsyncDevice>
fn AsyncDevice::find_mouse_box() -> Result<AsyncDevice>
fn AsyncDevice::find_keyboard_box() -> Result<AsyncDevice>

Blocks

AsyncDevice mirrors the discovery constructors. Like their Device counterparts, they block on reading each box and on the handshake. device_info is the awaitable query.

EXAMPLE
use medius::AsyncDevice;

let device = AsyncDevice::find_mouse_box()?; // blocks on the handshake
let info = futures::executor::block_on(device.device_info())?; // awaits the reply