1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-07-11 13:24:19 -04:00

Enable native Fobos SDR source plugin on Linux

This commit is contained in:
Alex Antonov UT2UM
2026-06-01 09:20:01 +03:00
parent 13fdc156a2
commit 3f85144bed
12 changed files with 214 additions and 103 deletions
+63 -1
View File
@@ -5,6 +5,68 @@ option(FOBOS_DEBUG_FILE_LOG "Write Fobos SDR diagnostic log file" OFF)
# Fobos SDR runtime packages. On Windows official builds these are expected
# to come from external/windows/fobos-sdr and external/windows/fobos-regular
# in the SDRangel Windows dependency repo.
#
# On Linux the plugin is intended to runtime-load libfobos_sdr.so / libfobos.so.
# CMake still verifies headers and libraries early so developer builds fail with
# a clear diagnostic instead of a hidden runtime loader error.
if(UNIX AND NOT APPLE)
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
pkg_check_modules(FOBOS_SDR_PC QUIET libfobos_sdr)
pkg_check_modules(FOBOS_REGULAR_PC QUIET libfobos)
endif()
set(FOBOS_SDR_INCLUDE_DIR "${FOBOS_SDR_INCLUDE_DIR}" CACHE PATH "Fobos SDR Agile include directory")
set(FOBOS_SDR_LIBRARY "${FOBOS_SDR_LIBRARY}" CACHE FILEPATH "Fobos SDR Agile runtime library")
set(FOBOS_REGULAR_INCLUDE_DIR "${FOBOS_REGULAR_INCLUDE_DIR}" CACHE PATH "Fobos SDR regular include directory")
set(FOBOS_REGULAR_LIBRARY "${FOBOS_REGULAR_LIBRARY}" CACHE FILEPATH "Fobos SDR regular runtime library")
if(NOT FOBOS_SDR_INCLUDE_DIR AND DEFINED ENV{FOBOS_SDR_DIR})
set(FOBOS_SDR_INCLUDE_DIR "$ENV{FOBOS_SDR_DIR}/include" CACHE PATH "Fobos SDR Agile include directory" FORCE)
endif()
if(NOT FOBOS_SDR_LIBRARY AND DEFINED ENV{FOBOS_SDR_DIR})
set(FOBOS_SDR_LIBRARY "$ENV{FOBOS_SDR_DIR}/lib/libfobos_sdr.so" CACHE FILEPATH "Fobos SDR Agile runtime library" FORCE)
endif()
if(NOT FOBOS_REGULAR_INCLUDE_DIR AND DEFINED ENV{FOBOS_DIR})
set(FOBOS_REGULAR_INCLUDE_DIR "$ENV{FOBOS_DIR}/include" CACHE PATH "Fobos SDR regular include directory" FORCE)
endif()
if(NOT FOBOS_REGULAR_LIBRARY AND DEFINED ENV{FOBOS_DIR})
set(FOBOS_REGULAR_LIBRARY "$ENV{FOBOS_DIR}/lib/libfobos.so" CACHE FILEPATH "Fobos SDR regular runtime library" FORCE)
endif()
if(NOT FOBOS_SDR_INCLUDE_DIR AND FOBOS_SDR_PC_INCLUDE_DIRS)
list(GET FOBOS_SDR_PC_INCLUDE_DIRS 0 FOBOS_SDR_INCLUDE_DIR)
set(FOBOS_SDR_INCLUDE_DIR "${FOBOS_SDR_INCLUDE_DIR}" CACHE PATH "Fobos SDR Agile include directory" FORCE)
endif()
if(NOT FOBOS_REGULAR_INCLUDE_DIR AND FOBOS_REGULAR_PC_INCLUDE_DIRS)
list(GET FOBOS_REGULAR_PC_INCLUDE_DIRS 0 FOBOS_REGULAR_INCLUDE_DIR)
set(FOBOS_REGULAR_INCLUDE_DIR "${FOBOS_REGULAR_INCLUDE_DIR}" CACHE PATH "Fobos SDR regular include directory" FORCE)
endif()
if(NOT FOBOS_SDR_LIBRARY AND FOBOS_SDR_PC_LIBRARY_DIRS)
list(GET FOBOS_SDR_PC_LIBRARY_DIRS 0 FOBOS_SDR_LIBRARY_DIR)
set(FOBOS_SDR_LIBRARY "${FOBOS_SDR_LIBRARY_DIR}/libfobos_sdr.so" CACHE FILEPATH "Fobos SDR Agile runtime library" FORCE)
endif()
if(NOT FOBOS_REGULAR_LIBRARY AND FOBOS_REGULAR_PC_LIBRARY_DIRS)
list(GET FOBOS_REGULAR_PC_LIBRARY_DIRS 0 FOBOS_REGULAR_LIBRARY_DIR)
set(FOBOS_REGULAR_LIBRARY "${FOBOS_REGULAR_LIBRARY_DIR}/libfobos.so" CACHE FILEPATH "Fobos SDR regular runtime library" FORCE)
endif()
if(NOT EXISTS "${FOBOS_SDR_INCLUDE_DIR}/fobos_sdr.h")
message(FATAL_ERROR "Fobos SDR Agile header not found: ${FOBOS_SDR_INCLUDE_DIR}/fobos_sdr.h")
endif()
if(NOT EXISTS "${FOBOS_SDR_LIBRARY}")
message(FATAL_ERROR "Fobos SDR Agile runtime library not found: ${FOBOS_SDR_LIBRARY}")
endif()
if(NOT EXISTS "${FOBOS_REGULAR_INCLUDE_DIR}/fobos.h")
message(FATAL_ERROR "Fobos SDR regular header not found: ${FOBOS_REGULAR_INCLUDE_DIR}/fobos.h")
endif()
if(NOT EXISTS "${FOBOS_REGULAR_LIBRARY}")
message(FATAL_ERROR "Fobos SDR regular runtime library not found: ${FOBOS_REGULAR_LIBRARY}")
endif()
endif()
if(WIN32)
set(FOBOS_SDR_INCLUDE_DIR "${FOBOS_SDR_INCLUDE_DIR}" CACHE PATH "Fobos SDR Agile include directory")
set(FOBOS_SDR_LIBRARY "${FOBOS_SDR_LIBRARY}" CACHE FILEPATH "Fobos SDR Agile import library")
@@ -80,7 +142,7 @@ if(NOT BUILD_SHARED_LIBS)
set_property(GLOBAL APPEND PROPERTY STATIC_PLUGINS_PROPERTY ${TARGET_NAME})
endif()
if(WIN32)
if(WIN32 OR UNIX)
target_include_directories(${TARGET_NAME} PRIVATE ${FOBOS_SDR_INCLUDE_DIR} ${FOBOS_REGULAR_INCLUDE_DIR})
endif()
+2 -2
View File
@@ -40,7 +40,7 @@
#include <QPair>
#include <QList>
#include "ui_FOBOSgui.h"
#include "ui_fobosgui.h"
#include "gui/colormapper.h"
#include "gui/glspectrum.h"
#include "gui/basicdevicesettingsdialog.h"
@@ -50,7 +50,7 @@
#include "dsp/dspcommands.h"
#include "util/db.h"
#include "FOBOSgui.h"
#include "fobosgui.h"
#include "device/deviceapi.h"
#include "device/deviceuiset.h"
+2 -2
View File
@@ -26,8 +26,8 @@
#include "util/messagequeue.h"
#include "FOBOSsettings.h"
#include "FOBOSinput.h"
#include "fobossettings.h"
#include "fobosinput.h"
class DeviceUISet;
+2 -2
View File
@@ -30,9 +30,9 @@
#include "SWGDeviceSettings.h"
#include "SWGDeviceState.h"
#include "FOBOSinput.h"
#include "fobosinput.h"
#include "device/deviceapi.h"
#include "FOBOSworker.h"
#include "fobosworker.h"
#include "dsp/dspcommands.h"
MESSAGE_CLASS_DEFINITION(FOBOSInput::MsgConfigureFOBOS, Message)
+1 -1
View File
@@ -27,7 +27,7 @@
#include <QNetworkRequest>
#include <dsp/devicesamplesource.h>
#include "FOBOSsettings.h"
#include "fobossettings.h"
class DeviceAPI;
class FOBOSWorker;
+4 -4
View File
@@ -22,12 +22,12 @@
#include "plugin/pluginapi.h"
#ifdef SERVER_MODE
#include "FOBOSinput.h"
#include "fobosinput.h"
#else
#include "FOBOSgui.h"
#include "fobosgui.h"
#endif
#include "FOBOSplugin.h"
#include "FOBOSwebapiadapter.h"
#include "fobosplugin.h"
#include "foboswebapiadapter.h"
const PluginDescriptor FOBOSPlugin::m_pluginDescriptor = {
QStringLiteral("FOBOS"),
+1 -1
View File
@@ -19,7 +19,7 @@
#include <QtGlobal>
#include "util/simpleserializer.h"
#include "FOBOSsettings.h"
#include "fobossettings.h"
FOBOSSettings::FOBOSSettings()
{
@@ -21,8 +21,8 @@
///////////////////////////////////////////////////////////////////////////////////
#include "SWGDeviceSettings.h"
#include "FOBOSinput.h"
#include "FOBOSwebapiadapter.h"
#include "fobosinput.h"
#include "foboswebapiadapter.h"
FOBOSWebAPIAdapter::FOBOSWebAPIAdapter()
{}
@@ -21,7 +21,7 @@
///////////////////////////////////////////////////////////////////////////////////
#include "device/devicewebapiadapter.h"
#include "FOBOSsettings.h"
#include "fobossettings.h"
class FOBOSWebAPIAdapter : public DeviceWebAPIAdapter
{
+91 -44
View File
@@ -8,12 +8,17 @@
#include <QDebug>
#include <QDateTime>
#include <QStringList>
#include <QLibrary>
#include <QByteArray>
#include <algorithm>
#include <cmath>
#include <chrono>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>
#include <vector>
#ifdef _WIN32
@@ -28,8 +33,13 @@ namespace
#if defined(FOBOS_DEBUG_FILE_LOG)
static const char* kLogPath = "sdrangel_fobos_source.log";
#endif
#ifdef _WIN32
static const char* kAgileDll = "fobos_sdr.dll";
static const char* kRegularDll = "fobos.dll";
#else
static const char* kAgileDll = "libfobos_sdr.so";
static const char* kRegularDll = "libfobos.so";
#endif
static const uint32_t kSyncComplexBufferLength = 65536; // Sync read block size, about 8.2 ms at 8 MS/s
static const uint32_t kSyncFloatStorage = kSyncComplexBufferLength * 2u; // interleaved float I/Q
static const uint32_t kFifoChunkComplexLength = kSyncComplexBufferLength; // One FIFO write per read block
@@ -46,10 +56,71 @@ namespace
static const bool kDefaultExternalClock = false;
#ifdef _WIN32
using FobosLibraryHandle = HMODULE;
#else
using DWORD = unsigned long;
using HMODULE = void*;
using FobosLibraryHandle = HMODULE;
static QString g_lastLibraryError;
static void SetLastError(DWORD) {}
static DWORD GetLastError() { return 0; }
static QString linuxRuntimeCandidate(const char* envName, const char* libName)
{
const char* root = std::getenv(envName);
if (!root || !*root) {
return QString();
}
return QString::fromLocal8Bit(root) + QStringLiteral("/lib/") + QString::fromLatin1(libName);
}
static HMODULE LoadLibraryA(const char* name)
{
QStringList candidates;
const QString libName = QString::fromLatin1(name ? name : "");
if (libName.contains(QStringLiteral("fobos_sdr"))) {
const QString envPath = linuxRuntimeCandidate("FOBOS_SDR_DIR", "libfobos_sdr.so");
if (!envPath.isEmpty()) { candidates << envPath; }
}
if (libName.contains(QStringLiteral("fobos")) && !libName.contains(QStringLiteral("fobos_sdr"))) {
const QString envPath = linuxRuntimeCandidate("FOBOS_DIR", "libfobos.so");
if (!envPath.isEmpty()) { candidates << envPath; }
}
candidates << libName;
for (const QString& candidate : candidates) {
QLibrary* lib = new QLibrary(candidate);
if (lib->load()) {
g_lastLibraryError.clear();
return static_cast<void*>(lib);
}
g_lastLibraryError = QStringLiteral("%1: %2").arg(candidate, lib->errorString());
delete lib;
}
return nullptr;
}
static QFunctionPointer GetProcAddress(HMODULE handle, const char* symbol)
{
QLibrary* lib = static_cast<QLibrary*>(handle);
return lib ? lib->resolve(symbol) : nullptr;
}
static void Sleep(unsigned int msec)
{
std::this_thread::sleep_for(std::chrono::milliseconds(msec));
}
#endif
static QMutex g_sessionMutex;
static HMODULE g_agileLibrary = nullptr; // DLL is process-scoped; device is not.
static HMODULE g_regularLibrary = nullptr; // regular/classic DLL, process-scoped as well.
static bool g_deviceBusy = false; // prevent two SDRangel device sets from using one Fobos.
static FobosLibraryHandle g_agileLibrary = nullptr; // runtime library is process-scoped; device is not.
static FobosLibraryHandle g_regularLibrary = nullptr; // regular/classic runtime library, process-scoped as well.
static bool g_deviceBusy = false; // prevent two SDRangel device sets from using one Fobos.
static void formatLastError(DWORD err, char* out, size_t outSize)
{
@@ -57,6 +128,7 @@ namespace
return;
}
out[0] = '\0';
#ifdef _WIN32
DWORD n = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
@@ -73,8 +145,12 @@ namespace
--n;
}
}
}
#else
(void) err;
const QByteArray bytes = g_lastLibraryError.toLocal8Bit();
std::snprintf(out, outSize, "%s", bytes.constData());
#endif
}
}
FOBOSWorker::FOBOSWorker(SampleSinkFifo* sampleFifo, QObject* parent) :
@@ -110,9 +186,8 @@ FOBOSWorker::FOBOSWorker(SampleSinkFifo* sampleFifo, QObject* parent) :
m_readerActive(false),
m_readerFinished(false),
m_dev(nullptr),
m_runtimeBackend(FobosRuntimeBackend::None)
#ifdef _WIN32
, m_libraryHandle(nullptr),
m_runtimeBackend(FobosRuntimeBackend::None),
m_libraryHandle(nullptr),
m_errorName(nullptr),
m_closeDev(nullptr),
m_readSync(nullptr),
@@ -133,9 +208,8 @@ FOBOSWorker::FOBOSWorker(SampleSinkFifo* sampleFifo, QObject* parent) :
m_regularSetUserGpo(nullptr),
m_regularSetClkSource(nullptr),
m_regularSetLnaGain(nullptr),
m_regularSetVgaGain(nullptr)
#endif
, m_totalReads(0),
m_regularSetVgaGain(nullptr),
m_totalReads(0),
m_totalSamples(0),
m_totalWritten(0),
m_failedReads(0)
@@ -180,7 +254,6 @@ void FOBOSWorker::stopWork()
m_stopRequested.store(true);
m_running.store(false);
#ifdef _WIN32
bool readerJoined = true;
// Do not call stop_sync while read_sync is active.
@@ -204,7 +277,6 @@ void FOBOSWorker::stopWork()
}
cleanupAfterReaderJoined(readerJoined);
#endif
}
void FOBOSWorker::setSamplerate(int samplerate)
@@ -346,7 +418,6 @@ void FOBOSWorker::setPattern2() {}
bool FOBOSWorker::runAgileStart()
{
#ifdef _WIN32
logLine("============================================================");
logLine("SDRangel Fobos SDR Agile native source");
logTimestamp();
@@ -639,17 +710,11 @@ bool FOBOSWorker::runAgileStart()
logLine("reader_thread=STARTED");
emit backendStatusChanged(QStringLiteral("Agile"), agileBackendDetails);
return true;
#else
logLine("Fobos SDR Agile dynamic runtime backend is currently implemented for Windows only");
m_running.store(false);
return false;
#endif
}
bool FOBOSWorker::runRegularStart()
{
#ifdef _WIN32
logLine("============================================================");
logLine("SDRangel Fobos SDR regular native source");
logTimestamp();
@@ -872,15 +937,10 @@ bool FOBOSWorker::runRegularStart()
logLine("regular_reader_thread=STARTED");
emit backendStatusChanged(QStringLiteral("Regular"), regularBackendDetails);
return true;
#else
m_running.store(false);
return false;
#endif
}
int FOBOSWorker::callSetFrequency(fobos_dev_t* dev, double valueHz)
{
#ifdef _WIN32
if (m_runtimeBackend == FobosRuntimeBackend::Regular && m_regularSetFrequency) {
double actual = 0.0;
int r = m_regularSetFrequency(dev, valueHz, &actual);
@@ -890,13 +950,11 @@ int FOBOSWorker::callSetFrequency(fobos_dev_t* dev, double valueHz)
if (m_setFrequency) {
return m_setFrequency(dev, valueHz);
}
#endif
return -9999;
}
int FOBOSWorker::callSetSamplerate(fobos_dev_t* dev, double valueHz)
{
#ifdef _WIN32
if (m_runtimeBackend == FobosRuntimeBackend::Regular && m_regularSetSamplerate)
{
double actual = 0.0;
@@ -907,13 +965,11 @@ int FOBOSWorker::callSetSamplerate(fobos_dev_t* dev, double valueHz)
{
return m_setSamplerate(dev, valueHz);
}
#endif
return -9999;
}
int FOBOSWorker::callSetDirectSampling(fobos_dev_t* dev, int inputMode)
{
#ifdef _WIN32
const int direct = (inputMode == 0) ? 0 : 1;
if (m_runtimeBackend == FobosRuntimeBackend::Regular && m_regularSetDirectSampling) {
return m_regularSetDirectSampling(dev, static_cast<unsigned int>(direct));
@@ -921,13 +977,11 @@ int FOBOSWorker::callSetDirectSampling(fobos_dev_t* dev, int inputMode)
if (m_setDirectSampling) {
return m_setDirectSampling(dev, direct);
}
#endif
return 0;
}
int FOBOSWorker::callSetAutoBandwidth(fobos_dev_t* dev, unsigned int bandwidthPercent)
{
#ifdef _WIN32
if (m_runtimeBackend == FobosRuntimeBackend::Regular) {
(void) dev;
(void) bandwidthPercent;
@@ -937,59 +991,50 @@ int FOBOSWorker::callSetAutoBandwidth(fobos_dev_t* dev, unsigned int bandwidthPe
const double ratio = static_cast<double>(bandwidthPercent) * 0.01;
return m_setAutoBandwidth(dev, ratio);
}
#endif
return 0;
}
int FOBOSWorker::callSetGpo(fobos_dev_t* dev, unsigned int gpoMask)
{
#ifdef _WIN32
if (m_runtimeBackend == FobosRuntimeBackend::Regular && m_regularSetUserGpo) {
return m_regularSetUserGpo(dev, static_cast<uint8_t>(gpoMask & 0xffu));
}
if (m_setUserGpo) {
return m_setUserGpo(dev, gpoMask & 0xffu);
}
#endif
return 0;
}
int FOBOSWorker::callSetClockSource(fobos_dev_t* dev, bool externalClock)
{
#ifdef _WIN32
if (m_runtimeBackend == FobosRuntimeBackend::Regular && m_regularSetClkSource) {
return m_regularSetClkSource(dev, externalClock ? 1 : 0);
}
if (m_setClkSource) {
return m_setClkSource(dev, externalClock ? 1 : 0);
}
#endif
return 0;
}
int FOBOSWorker::callSetLnaGain(fobos_dev_t* dev, unsigned int lnaGain)
{
#ifdef _WIN32
if (m_runtimeBackend == FobosRuntimeBackend::Regular && m_regularSetLnaGain) {
return m_regularSetLnaGain(dev, lnaGain);
}
if (m_setLnaGain) {
return m_setLnaGain(dev, lnaGain);
}
#endif
return -9999;
}
int FOBOSWorker::callSetVgaGain(fobos_dev_t* dev, unsigned int vgaGain)
{
#ifdef _WIN32
if (m_runtimeBackend == FobosRuntimeBackend::Regular && m_regularSetVgaGain) {
return m_regularSetVgaGain(dev, vgaGain);
}
if (m_setVgaGain) {
return m_setVgaGain(dev, vgaGain);
}
#endif
return -9999;
}
@@ -998,6 +1043,9 @@ void FOBOSWorker::readerLoop()
#ifdef _WIN32
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
logLine("reader_thread_priority=THREAD_PRIORITY_HIGHEST");
#else
logLine("reader_thread_priority=DEFAULT_PORTABLE");
#endif
fobos_dev_t* dev = m_dev.load();
if (!dev || !m_readSync) {
logLine("reader_loop=ABORT no_device_or_readSync");
@@ -1187,12 +1235,10 @@ void FOBOSWorker::readerLoop()
m_readerActive.store(false);
m_readerFinished.store(true);
#endif
}
void FOBOSWorker::cleanupAfterReaderJoined(bool readerJoined)
{
#ifdef _WIN32
fobos_dev_t* dev = m_dev.load();
if (!dev) {
@@ -1222,14 +1268,17 @@ void FOBOSWorker::cleanupAfterReaderJoined(bool readerJoined)
logLine("freelibrary_call=SKIPPED_PROCESS_SCOPED_DLL");
logLine("source_result=STOPPED_CLEANLY_READER_JOINED_CLOSE_DONE");
#endif
}
void FOBOSWorker::logLine(const char* fmt, ...) const
{
#if defined(FOBOS_DEBUG_FILE_LOG)
FILE* f = nullptr;
#ifdef _WIN32
fopen_s(&f, kLogPath, "a");
#else
f = std::fopen(kLogPath, "a");
#endif
if (!f) {
return;
}
@@ -1254,12 +1303,10 @@ void FOBOSWorker::logTimestamp() const
const char* FOBOSWorker::errorName(int code) const
{
#ifdef _WIN32
if (m_errorName) {
const char* s = m_errorName(code);
return s ? s : "null_error_name";
}
#endif
return "error_name_unavailable";
}
+43 -41
View File
@@ -14,6 +14,12 @@
#include <cstdint>
#include <thread>
#ifdef _WIN32
#define FOBOS_WORKER_CALL __cdecl
#else
#define FOBOS_WORKER_CALL
#endif
#include "dsp/samplesinkfifo.h"
#include "fobossettings.h"
@@ -61,46 +67,44 @@ signals:
void backendStatusChanged(const QString& backend, const QString& details);
private:
#ifdef _WIN32
using fobos_sdr_get_api_info_t = int (__cdecl *)(char* lib_version, char* drv_version);
using fobos_sdr_get_device_count_t = int (__cdecl *)();
using fobos_sdr_list_devices_t = int (__cdecl *)(char* serials);
using fobos_sdr_open_t = int (__cdecl *)(fobos_dev_t** out_dev, uint32_t index);
using fobos_sdr_close_t = int (__cdecl *)(fobos_dev_t* dev);
using fobos_sdr_get_board_info_t = int (__cdecl *)(fobos_dev_t* dev, char* hw_revision, char* fw_version, char* manufacturer, char* product, char* serial);
using fobos_sdr_error_name_t = const char* (__cdecl *)(int error_code);
using fobos_sdr_set_frequency_t = int (__cdecl *)(fobos_dev_t* dev, double value_hz);
using fobos_sdr_set_samplerate_t = int (__cdecl *)(fobos_dev_t* dev, double value_hz);
using fobos_sdr_get_samplerates_t = int (__cdecl *)(fobos_dev_t* dev, double* values, uint32_t* count);
using fobos_sdr_set_direct_sampling_t = int (__cdecl *)(fobos_dev_t* dev, int value);
using fobos_sdr_set_auto_bandwidth_t = int (__cdecl *)(fobos_dev_t* dev, double value);
using fobos_sdr_set_user_gpo_t = int (__cdecl *)(fobos_dev_t* dev, uint32_t value);
using fobos_sdr_set_clk_source_t = int (__cdecl *)(fobos_dev_t* dev, int value);
using fobos_sdr_set_lna_gain_t = int (__cdecl *)(fobos_dev_t* dev, unsigned int value);
using fobos_sdr_set_vga_gain_t = int (__cdecl *)(fobos_dev_t* dev, unsigned int value);
using fobos_sdr_start_sync_t = int (__cdecl *)(fobos_dev_t* dev, uint32_t buf_length);
using fobos_sdr_read_sync_t = int (__cdecl *)(fobos_dev_t* dev, float* buf, uint32_t* actual_buf_length);
using fobos_sdr_stop_sync_t = int (__cdecl *)(fobos_dev_t* dev);
using fobos_sdr_get_api_info_t = int (FOBOS_WORKER_CALL *)(char* lib_version, char* drv_version);
using fobos_sdr_get_device_count_t = int (FOBOS_WORKER_CALL *)();
using fobos_sdr_list_devices_t = int (FOBOS_WORKER_CALL *)(char* serials);
using fobos_sdr_open_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t** out_dev, uint32_t index);
using fobos_sdr_close_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev);
using fobos_sdr_get_board_info_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, char* hw_revision, char* fw_version, char* manufacturer, char* product, char* serial);
using fobos_sdr_error_name_t = const char* (FOBOS_WORKER_CALL *)(int error_code);
using fobos_sdr_set_frequency_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, double value_hz);
using fobos_sdr_set_samplerate_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, double value_hz);
using fobos_sdr_get_samplerates_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, double* values, uint32_t* count);
using fobos_sdr_set_direct_sampling_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, int value);
using fobos_sdr_set_auto_bandwidth_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, double value);
using fobos_sdr_set_user_gpo_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, uint32_t value);
using fobos_sdr_set_clk_source_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, int value);
using fobos_sdr_set_lna_gain_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, unsigned int value);
using fobos_sdr_set_vga_gain_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, unsigned int value);
using fobos_sdr_start_sync_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, uint32_t buf_length);
using fobos_sdr_read_sync_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, float* buf, uint32_t* actual_buf_length);
using fobos_sdr_stop_sync_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev);
using fobos_rx_get_api_info_t = int (__cdecl *)(char* lib_version, char* drv_version);
using fobos_rx_get_device_count_t = int (__cdecl *)();
using fobos_rx_list_devices_t = int (__cdecl *)(char* serials);
using fobos_rx_open_t = int (__cdecl *)(fobos_dev_t** out_dev, uint32_t index);
using fobos_rx_close_t = int (__cdecl *)(fobos_dev_t* dev);
using fobos_rx_get_board_info_t = int (__cdecl *)(fobos_dev_t* dev, char* hw_revision, char* fw_version, char* manufacturer, char* product, char* serial);
using fobos_rx_error_name_t = const char* (__cdecl *)(int error_code);
using fobos_rx_set_frequency_t = int (__cdecl *)(fobos_dev_t* dev, double value_hz, double* actual_hz);
using fobos_rx_set_samplerate_t = int (__cdecl *)(fobos_dev_t* dev, double value_hz, double* actual_hz);
using fobos_rx_get_samplerates_t = int (__cdecl *)(fobos_dev_t* dev, double* values, unsigned int* count);
using fobos_rx_set_direct_sampling_t = int (__cdecl *)(fobos_dev_t* dev, unsigned int enabled);
using fobos_rx_set_user_gpo_t = int (__cdecl *)(fobos_dev_t* dev, uint8_t value);
using fobos_rx_set_clk_source_t = int (__cdecl *)(fobos_dev_t* dev, int value);
using fobos_rx_set_lna_gain_t = int (__cdecl *)(fobos_dev_t* dev, unsigned int value);
using fobos_rx_set_vga_gain_t = int (__cdecl *)(fobos_dev_t* dev, unsigned int value);
using fobos_rx_start_sync_t = int (__cdecl *)(fobos_dev_t* dev, uint32_t buf_length);
using fobos_rx_read_sync_t = int (__cdecl *)(fobos_dev_t* dev, float* buf, uint32_t* actual_buf_length);
using fobos_rx_stop_sync_t = int (__cdecl *)(fobos_dev_t* dev);
#endif
using fobos_rx_get_api_info_t = int (FOBOS_WORKER_CALL *)(char* lib_version, char* drv_version);
using fobos_rx_get_device_count_t = int (FOBOS_WORKER_CALL *)();
using fobos_rx_list_devices_t = int (FOBOS_WORKER_CALL *)(char* serials);
using fobos_rx_open_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t** out_dev, uint32_t index);
using fobos_rx_close_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev);
using fobos_rx_get_board_info_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, char* hw_revision, char* fw_version, char* manufacturer, char* product, char* serial);
using fobos_rx_error_name_t = const char* (FOBOS_WORKER_CALL *)(int error_code);
using fobos_rx_set_frequency_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, double value_hz, double* actual_hz);
using fobos_rx_set_samplerate_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, double value_hz, double* actual_hz);
using fobos_rx_get_samplerates_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, double* values, unsigned int* count);
using fobos_rx_set_direct_sampling_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, unsigned int enabled);
using fobos_rx_set_user_gpo_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, uint8_t value);
using fobos_rx_set_clk_source_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, int value);
using fobos_rx_set_lna_gain_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, unsigned int value);
using fobos_rx_set_vga_gain_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, unsigned int value);
using fobos_rx_start_sync_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, uint32_t buf_length);
using fobos_rx_read_sync_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev, float* buf, uint32_t* actual_buf_length);
using fobos_rx_stop_sync_t = int (FOBOS_WORKER_CALL *)(fobos_dev_t* dev);
bool runAgileStart();
bool runRegularStart();
@@ -158,7 +162,6 @@ private:
std::thread m_readerThread;
FobosRuntimeBackend m_runtimeBackend;
#ifdef _WIN32
void* m_libraryHandle;
fobos_sdr_error_name_t m_errorName;
fobos_sdr_close_t m_closeDev;
@@ -182,7 +185,6 @@ private:
fobos_rx_set_clk_source_t m_regularSetClkSource;
fobos_rx_set_lna_gain_t m_regularSetLnaGain;
fobos_rx_set_vga_gain_t m_regularSetVgaGain;
#endif
uint64_t m_totalReads;
uint64_t m_totalSamples;