Skip to main content

Crate anybox

Crate anybox 

Source
Expand description

one API for the most popular passthrough boxes. you connect, and anybox figures out which box it is, the firmware, and what it can do, then you call the same methods without having to worry about which box is plugged in

use anybox::{Button, Event, Key};

fn main() -> anybox::Result<()> {
    let device = anybox::connect()?;
    device.move_by(100, 0)?;
    device.click(Button::Left)?;
    device.tap_key(Key::A)?;

    for event in device.events() {
        if let Event::Button { button, pressed: true, .. } = event {
            println!("{button:?} down");
        }
    }
    Ok(())
}

if a box can’t do something, the call fails with Error::Unsupported and says why, nothing is faked or changed behind your back. Device::snapshot tells you up front what the box in front of you can do right now, which also depends on what’s plugged into it. things only one box has stay reachable through that box’s own API, like device.medius() on a Medius

the README has the full picture, which box does what, the differences between them, and how to add your own fallback for something a box can’t do: https://github.com/etherealrl/anybox

Re-exports§

pub use medius;

Structs§

BoxTime
Capabilities
what this box, on this firmware, with this mouse behind it, can do
Capability
Click
Closed
Connect
Device
one connected box. every call checks what the box can do first, so nothing is faked and nothing is silently dropped. dropping it lets go of every button and key you were holding and closes the port
EventKinds
which input a receiver wants, combined with |. a receiver only gets what it asked for, the box streams what any receiver wants, and connection events and drops reach every receiver
Events
a receiver of events from one device. it ends once the device is gone and you’ve read everything queued, or once you close it
Found
one box a scan saw
Info
Key
a keyboard key by its HID usage (page 0x07). the consts cover the usual keys, and Key(n) gets you any other one from 0x04 to 0xE7
MediaKey
a media key by its HID consumer usage (page 0x0C)
MockPoller
the poller of a device made with Device::mock_medius_manual, ticked by hand so a test doesn’t wait on its timing
Scanned
one port a scan looked at. result is the box on it, or the error a search of just that port gives. mostly that’s busy (the box you already have open shows up as busy too, so leave its port out), not allowed, too old, NoBoxCan for a box that can’t do what can asked, or NotFound when nothing answered
Snapshot
who the box is and what it can do, both always read from the same connection
Stamp
UsbIds
a USB vendor and product id

Enums§

Action
every action a box gets asked whether it can do, and the one an error is about
Axis
a physical axis you can lock or scale
Button
ClickTiming
what click() and the key and media taps do on a box that can’t time them itself
Clock
each box clock is its own counter, so only compare stamps that come from the same one
Direction
which way along an axis. positive is the way the box moves for a positive value, so right for X, down for Y, up for the wheel and right for pan
DropSource
Error
Event
Execution
how a box does an action
Family
the box families anybox knows how to talk to
FerrumApi
the two ways into a Ferrum
Firmware
Quirk
a way this box behaves differently that anybox can’t hide, so it tells you instead of smoothing it over
RecvTimeoutError
StableId
Timing
TryRecvError

Functions§

candidates
the ports a search would look at, in port order, without opening any of them or sending them a byte. it can’t tell whether a box is on one, only where one could be, so it’s cheap enough to call every second and run scan when the list changes. a Ferrum has no USB id anybox knows, so its port is never listed here. a YSC V1 sits behind the same chip as a Medius or a MAKCU, so its port shows up here, but only .family(Family::Ysc) ever looks for a V1 on it
connect
connects to the first box found, in port order
monotonic_ns
now in nanoseconds on the OS monotonic clock, the one Instant reads: QueryPerformanceCounter on Windows, CLOCK_MONOTONIC on Linux and CLOCK_UPTIME_RAW on macOS. Python’s time.perf_counter_ns() and .NET’s Stopwatch read the same one on Windows and Linux. it only compares on the same machine within one boot
scan
every port a search looks at and what’s on it, in port order, so a picker can show the boxes you can use and why you can’t use the others. it opens, describes and closes every box, so it’s slow (a YSC search takes about 2 s a port), candidates() is the cheap one to call often

Type Aliases§

Result