nord_usb/lib.rs
1//! Clavia / Nord device transport and vendor protocol over USB.
2//!
3//! > This is an unofficial, community project: **not affiliated with, endorsed
4//! > by, or supported by Clavia DMI AB**. "Nord" and the instrument names are
5//! > Clavia's trademarks, used here only to identify which files this crate
6//! > reads.
7//!
8//! Layered so the protocol is testable without hardware:
9//!
10//! - [`wire`] — message framing and codec. Pure, fully decoded, no I/O.
11//! - [`transport`] — the byte pipe. The only part that touches a device.
12//! - [`session`] — the transaction wrapper every operation runs inside.
13//! - [`op`] — typed operations.
14//! - [`device`] — an instrument as a value: session brackets and its own geometry.
15//!
16//! The wire format was reverse-engineered from a corpus of NSM captures and is
17//! verified against every message in it.
18//!
19//! # Portability
20//!
21//! Desktop (macOS/Linux/Windows) via `nusb`, browsers via WebUSB. WebUSB is the
22//! binding constraint on the API shape — see [`transport::Transport`] for why there
23//! are no `Send` bounds, and why enumeration is deliberately backend-specific rather
24//! than part of the portable core.
25
26#[cfg(feature = "nusb")]
27pub mod deadline;
28pub mod device;
29pub mod envelope;
30pub mod error;
31pub mod op;
32pub mod session;
33pub mod sleep;
34pub mod transport;
35pub mod wire;
36
37pub use device::{Device, Geometry};
38pub use error::{Error, Result};
39pub use session::{ReadOnly, ReadWrite, Session};
40pub use transport::Transport;
41pub use wire::{Location, Message, ObjectClass, Service, Status};
42
43#[cfg(feature = "replay")]
44pub use transport::ReplayTransport;
45
46/// Block on a future without pulling in a full async runtime.
47///
48/// The crate is deliberately runtime-agnostic (see [`transport::Transport`] for why
49/// there are no `Send` bounds), so this exists for CLIs and tests that just want the
50/// answer. Browser callers already have an executor and should not use it.
51#[cfg(feature = "blocking")]
52pub fn block_on<F: std::future::Future>(fut: F) -> F::Output {
53 pollster::block_on(fut)
54}