Skip to main content

Crate librtlsdr_rs

Crate librtlsdr_rs 

Source
Expand description

Pure-Rust port of librtlsdr — RTL2832U USB control + tuner drivers.

Talks to RTL-SDR dongles directly over USB via rusb, without the C librtlsdr library or its headers. Covers all five tuner families shipped in real-world dongles (R820T / R820T2 / R828D, E4000, FC0012, FC0013, FC2580).

§Quick start

use librtlsdr_rs::{RtlSdrDevice, RtlSdrError};

// Open the first dongle plugged in.
let mut dev = RtlSdrDevice::open(0)?;

// Tune to 100 MHz, 2.048 Msps.
dev.set_center_freq(100_000_000)?;
dev.set_sample_rate(2_048_000)?;

// Manual gain at 14.4 dB (`144` in tenths-of-dB happens to be
// an exact step on the R820T2 gain table). For arbitrary user
// input, snap to the nearest step via [`RtlSdrDevice::closest_gain`]
// first — passing a value not in the tuner's table results in
// the tuner silently rounding (or, on the E4000, returning an
// `InvalidGain` error).
dev.set_tuner_gain_mode(true)?;
dev.set_tuner_gain(144)?;

// Read 64 KB of interleaved I/Q samples.
dev.reset_buffer()?;
let mut buf = vec![0u8; 65_536];
let n = dev.read_sync(&mut buf)?;
assert!(n > 0);

§Public surface

The committed surface is intentionally narrow:

Sample values are interleaved unsigned 8-bit I/Q pairs, the native RTL-SDR format. Convert to centred i8 (or f32 in [-1, 1]) at the consumer if needed; we don’t impose a sample type on the read path.

§USB context + threading

RtlSdrDevice holds an Arc<rusb::DeviceHandle> internally so the device handle can be cloned across threads — rusb::DeviceHandle is Sync, which makes the type shareable between threads. The control methods on RtlSdrDevice take &mut self and serialise on the caller; that’s the supported single-thread pattern.

For raw bulk reads on a worker thread (e.g. an rtl_tcp-style server), call RtlSdrDevice::usb_handle to clone the underlying handle and use RtlSdrDevice::BULK_ENDPOINT for the endpoint address. Note that Sync alone does not guarantee that concurrent bulk and control transfers on the same handle are saferusb’s docs don’t make that claim explicitly, and libusb’s caveats restrict per-resource concurrent access. If you mix concurrent bulk and control on one handle, treat it as an unsupported design assumption you’ve verified against your libusb version + dongle hardware. The safer pattern is to quiesce control calls (or do them all from one thread) while a bulk-read worker is in flight.

§Faithful-port note

The crate is a port of the C librtlsdr source — register addresses, magic constants, and per-tuner I2C tables are transcribed directly from the upstream code. Some internal items aren’t currently called from Rust but are kept for completeness so future hardware-feature work is a register-table read away rather than a re-port. Hardware register manipulation requires extensive integer casts inherent in a faithful port of C driver code.

Re-exports§

pub use device::DeviceInfo;
pub use device::ReaderIter;
pub use device::RtlSdrDevice;
pub use device::RtlSdrDeviceBuilder;
pub use device::RtlSdrReader;
pub use device::SampleIter;
pub use device::get_device_count;
pub use device::get_device_name;
pub use device::get_device_usb_strings;
pub use device::get_index_by_serial;
pub use device::list_devices;
pub use error::RtlSdrError;
pub use error::TunerError;
pub use rusb;

Modules§

device
RTL-SDR device — high-level API for device control.
error
Error types for the RTL-SDR driver.

Enums§

Block
Block IDs for register addressing.
TunerType
Tuner type detected on the device.