7.0 KiB
SDR Device Layer
This document describes CubicSDR's SDR hardware abstraction layer, device discovery, device information model, and manual device support.
Overview
CubicSDR uses SoapySDR as its hardware abstraction layer. The device layer handles:
- Device discovery: Enumerating local and remote SDR hardware
- Device information: Querying capabilities (sample rates, gains, antennas)
- Manual devices: Adding devices not auto-discovered
- Device configuration: Per-device settings persistence
SDREnumerator (background thread)
|
+-- SoapySDR::Device::enumerate()
|
v
SDRDeviceInfo (per-device capabilities)
|
v
SDRDevicesDialog (UI selection)
|
v
SDRThread (active device usage)
SDREnumerator (src/sdr/SDREnumerator.h)
Background IOThread that discovers available SDR devices. Results are cached in a static map.
Enumeration Flow
-
SoapySDR initialization (once):
- Load SoapySDR modules (system, bundled, or user-specified path)
- Discover available factory functions (driver names)
- Detect if
remotefactory is available
-
Local enumeration:
- Call
SoapySDR::Device::enumerate()with no arguments - For each result, create
SDRDeviceInfoand populate driver/name - Attempt
SoapySDR::Device::make()to query hardware info - Apply saved device settings from
DeviceConfig - Store in
devs[""](empty string = local)
- Call
-
Remote enumeration:
- For each address in
remoteslist - Call
SoapySDR::Device::enumerate()withdriver=remote,remote={addr} - Same device creation and info querying as local
- Store in
devs[remoteAddr]
- For each address in
-
Manual device enumeration:
- For each entry in
manualslist - Call
SoapySDR::Device::enumerate()withdriver={factory},{params} - If enumeration fails, create device entry marked as unavailable with label "Not Found ({factory})"
- Store in
devs[""](same as local)
- For each entry in
Static State
| Map/Vector | Type | Purpose |
|---|---|---|
devs |
map<string, vector<SDRDeviceInfo*>> |
Devices keyed by remote address ("" = local) |
factories |
vector<string> |
Available SoapySDR driver names |
modules |
vector<string> |
Loaded SoapySDR module paths |
remotes |
vector<string> |
Configured remote server addresses |
manuals |
vector<SDRManualDef> |
Manual device definitions |
Notification
SDREnumerator sends notifications to the UI via wxGetApp().sdrEnumThreadNotify():
| State | Meaning |
|---|---|
SDR_ENUM_MESSAGE |
Status message (displayed in UI) |
SDR_ENUM_DEVICES_READY |
Enumeration complete, devices available |
SDR_ENUM_FAILED |
No modules available |
SDR_ENUM_TERMINATED |
Thread terminated |
SDRDeviceInfo (src/sdr/SDRDeviceInfo.h)
Represents a discovered or manually defined SDR device.
Identity
| Property | Type | Description |
|---|---|---|
name |
string |
Display name (from SoapySDR label or device field) |
serial |
string |
Device serial number |
driver |
string |
SoapySDR driver name |
hardware |
string |
Hardware revision |
tuner |
string |
Tuner chip type |
manufacturer |
string |
Device manufacturer |
product |
string |
Product name |
Device ID
getDeviceId() returns a unique identifier string. For local devices, this is typically the driver name and serial number. For remote devices, it includes the remote address. For manual devices, it includes the factory and parameters.
State
| Property | Type | Description |
|---|---|---|
available |
bool |
Device was successfully queried |
active |
atomic_bool |
Device is currently in use |
remote |
bool |
Device is on a remote server |
manual |
bool |
Device was manually defined |
timestamps |
bool |
Device supports timestamped streaming |
Hardware Queries
| Method | Returns | Description |
|---|---|---|
getSampleRates(direction, channel) |
vector<long> |
Available sample rates |
getSampleRateNear(direction, channel, rate) |
long |
Nearest supported sample rate |
getAntennaNames(direction, channel) |
vector<string> |
Available antenna ports |
getAntennaName(direction, channel) |
string |
Currently selected antenna |
getGains(direction, channel) |
SDRRangeMap |
Per-stage gain ranges |
getCurrentGain(direction, channel, name) |
double |
Current gain value |
hasCORR(direction, channel) |
bool |
Supports DC offset correction |
SoapySDR Integration
SDRDeviceInfo holds a SoapySDR::Device* pointer for direct hardware access:
- Set via
setSoapyDevice()afterSoapySDR::Device::make() - Used to query capabilities (sample rates, gains, antennas)
- Released via
SoapySDR::Device::unmake()after enumeration
Device Arguments
SoapySDR devices are configured via key-value argument strings:
| Argument | Purpose |
|---|---|
driver |
SoapySDR driver module name |
device |
Device identifier |
serial |
Device serial number |
remote |
Remote server address |
label |
Human-readable device label |
Stream arguments (stored in streamArgs):
| Argument | Purpose |
|---|---|
buflen |
Buffer length |
bufflen |
Alternative buffer length |
remote |
Remote streaming address |
Device settings (stored in DeviceConfig::settings):
- Driver-specific settings (e.g.,
bias_teefor RTL-SDR) - Applied during device enumeration and on device open
Manual Device Definition
SDRManualDef allows users to add devices not auto-discovered:
struct SDRManualDef {
std::string factory; // SoapySDR driver name
std::string params; // Comma-separated key=value pairs
};
Example:
- Factory:
rtlsdr - Params:
driver=rtlsdr,bias_tee=1
Manual devices are:
- Stored in
AppConfigundermanual_devices - Loaded into
SDREnumerator::manualsat startup - Enumerated alongside local devices
- If not found, shown as unavailable with "Not Found" label
Device Selection UI
SDRDevicesDialog (src/forms/SDRDevices/) provides:
- List of all discovered devices (local, remote, manual)
- Device properties display (sample rates, gains, antennas)
- Manual device add/remove
- Remote device add/remove
- Device activation (triggers
SDRThreadcreation)
Device Configuration
Per-device settings are persisted in DeviceConfig (see Configuration System):
- Sample rate, frequency offset, PPM correction
- AGC mode, antenna selection
- Per-gain-stage values
- Stream options
- Driver-specific settings
- Rig IF frequencies
Module Loading
SoapySDR modules are loaded in this order:
- User-specified path (
-mcommand line option) - Bundled modules (if
BUNDLE_SOAPY_MODSis defined):- Check
modules/subdirectory next to the executable - Optionally load system modules first (if
BUNDLED_MODS_ONLYis not defined)
- Check
- System modules (default
SoapySDR::loadModules())
Module discovery is controlled by SoapySDR::listModules() and SoapySDR::loadModule().