Discovery
find opens the first match. These calls list every box and open one by a stable identity, or by the kind of device it clones.
See also: connecting, choosing a port, and the box handshake.
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.
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_id Open 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.
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_box Open 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.
use medius::Device;
let mouse_box = Device::find_mouse_box()?;
mouse_box.move_rel(10, 0)?;find_keyboard_box Open the first box cloning a keyboard
fn find_keyboard_box() -> Result<Device>
Blocks
find_mouse_box for a keyboard clone, with the same errors.
use medius::{Device, Key};
let kbd_box = Device::find_keyboard_box()?;
kbd_box.press(Key::A)?;find_where Open 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.
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 & reconnect Same 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 AsyncDevice Same 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.
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