Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Pure Rust driver for the Nuand BladeRF1 (x40/x115) SDR. No C libbladeRF dependency.
USB transport via nusb. Supports Windows, macOS, Linux, Android (via file
descriptor) and WebUSB (wasm32-unknown-unknown). Every I/O method can be
used synchronously or asynchronously.
Feature flags
| Flag | Default | Effect |
|---|---|---|
bladerf1 |
yes* | BladeRF1 support (x40/x115) |
bladerf2 |
no | BladeRF2 support — stub only |
xb100 |
yes | XB-100 LED expansion board |
xb200 |
yes | XB-200 transverter board |
xb300 |
yes | XB-300 amplifier board |
smol |
yes | nusb smol integration (blocking thread pool) |
tokio |
no | nusb tokio integration (spawn_blocking) |
Exactly like every nusb-based driver, one of smol/tokio is required on
native targets: nusb resolves device open, interface claim, alternate-setting
switches and clear-halt through the selected runtime's blocking pool. Neither
is needed on wasm32. If both are enabled nusb uses smol.
* Enabled implicitly by xb100, xb200, or xb300.
Usage
The device is accessed through session types that switch the FX3 USB alternate
setting and borrow &mut NiosCore. The borrow checker enforces exclusive access
at compile time.
Session types
| Session | USB alt setting | Capabilities |
|---|---|---|
RfLinkSession |
RfLink (0x01) | Tuning, gain, sample rate, bandwidth, streaming, expansion boards, triggers, loopback, corrections |
FlashSession |
SpiFlash (0x02) | SPI flash erase/write/verify, calibration region access |
ConfigSession |
Config (0x03) | FPGA loading, device configuration |
FlashSession and ConfigSession return Error::StreamsActive if any stream is running.
Sync or async
Every I/O method returns an [nusb::MaybeFuture] (re-exported as
libbladerf_rs::MaybeFuture). Call .wait() to block the current thread, or
.await it from async code:
use MaybeFuture;
use ;
use Channel;
// Blocking (native targets only)
let mut dev = from_first.wait?;
let mut rf = dev.rf_link_session.wait?;
rf.initialize.wait?;
rf.set_frequency.wait?;
let mut rx = builder.build.wait?;
rx.start.wait?;
let buffer = rx.read.wait?;
rx.recycle;
rx.close.wait?;
// Async — identical calls, `.await` instead of `.wait()`
let mut dev = from_first.await?;
let mut rf = dev.rf_link_session.await?;
rf.initialize.await?;
let mut rx = builder.build.await?;
rx.start.await?;
let buffer = rx.read.await?;
rx.recycle;
rx.close.await?;
dev.close.await?;
The crate mirrors nusb's semantics exactly: transfers are real futures
completed by nusb's event thread, and the handful of blocking syscalls (device
open, interface claim, alternate-setting switch, clear halt) are offloaded
through nusb's smol or tokio integration. With the default smol feature
both .wait() and .await work under any executor. With tokio instead,
.await must run inside a tokio runtime; .wait() works anywhere (the crate
enters a private runtime context for callers outside tokio).
Streaming timeouts (RxStream::read, TxStream::get_buffer,
TxStream::wait_completion) apply to the blocking path only. The awaited
futures ignore the timeout argument, consume at most one USB completion per
await and are cancel-safe, so wrap them in your executor's timeout
(tokio::time::timeout, gloo_timers, ...) if you need a deadline.
WebUSB
The crate compiles for wasm32-unknown-unknown. nusb's WebUSB backend needs
web-sys unstable APIs, so consumers must add to their .cargo/config.toml:
[]
= ["--cfg=web_sys_unstable_apis"]
Obtain a device with nusb::request_device (from a user gesture) or
nusb::list_devices, then open it with BladeRf1::from_device(device).await.
There is no .wait() on wasm, Drop performs no I/O, and transfers cannot be
cancelled, so always close() streams and the device explicitly.
Examples
Git-tracked examples (build and run from the repository root):
| Package | Purpose |
|---|---|
info |
Basic device info and FPGA version |
rx-tx |
Streaming RX/TX with metadata headers |
rx-async |
RX streaming with the awaited API on tokio (--features tokio) |
calibrate |
DC calibration on LMS6002D |
dc-cal-table |
DC calibration table management |
flash-firmware |
FX3 firmware flashing |
flash-fpga |
FPGA bitstream flashing |
Supported features
- RF control: frequency (host/FPGA tuning, quick-tune), gain (per-stage apportioning, gain modes, gain stage control), sample rate (integer and rational), bandwidth, LPF mode, RF port selection
- Streaming: zero-copy DMA via BufferPool (RX/TX), metadata headers, multiple sample formats (Sc16Q11, Sc8Q7, Sc16Q11Packed, *Meta variants), pack/unpack helpers
- DC calibration: on-demand LMS6002D calibration, flash-stored JSON calibration tables with auto-load on open and frequency-specific apply
- Flash: erase/write/verify, calibration region (DAC trim, FPGA size)
- FPGA: host-based loading, flash autoload, source query, firmware log reading
- Expansion boards: XB-100 (GPIO/LED), XB-200 (filter bank, upconverter, auto filter), XB-300 (amplifier, TRX, output power)
- Other: SMB clock, VCTCXO tamer, triggers, loopback (LMS + FPGA), corrections (DC/phase), RX mux, retune scheduling, timestamps, firmware flashing
Not supported (vs C libbladeRF)
- BladeRF2 — stub only, not implemented
- Synchronous API —
bladerf_sync_config/rx/txnot implemented - Bootloader — jump to bootloader, load firmware from bootloader
- OTP (one-time programmable) — read/write/lock
- Image helpers — flash image allocate/free/read/write
- Byte-level flash — byte-addressed erase/read/write (page/sector only)
- Wishbone — master read/write
- USB reset on open — configuration option
- Multi-device / MIMO — clock sync helpers
- Tuning mode get — missing getter
- Gain calibration tables — bladeRF2-specific (not applicable to BladeRF1)
Developers
Contributions are welcome. The architecture is documented in AGENTS.md.
The release and maintenance workflow is documented in docs/MAINTAINERS.md.
Commit messages
Commits must follow Conventional Commits.
A husky-rs commit-msg hook (.husky/commit-msg) validates each message with
git-cliff (cargo install git-cliff). The hook
installs automatically on cargo build / cargo test; set NO_HUSKY_HOOKS=1
to skip installation.
For debugging, compare USB traffic between libbladeRF and [libbladerf-rs] using Wireshark:
Filter example:
usb.bus_id == 1 and usb.device_address == 2
Datasheets
- SI5338 Datasheet
- SI5338 Reference Manual
- LMS6002D Datasheet
- LMS6002D Programming and Calibration Guide
- DAC161S055 Datasheet
Documentation
Testing
Unit tests (no hardware)
Integration tests (requires BladeRF1)
Specific test