srsran_rf: support dynamic loading of RF plugins

This adds flexible plugin-like loading of the individual RF
implementations (zmq, uhd, soapy,...) as per availability at runtime.
Unlike before, the binary application is not terminated if the
dependencies of individual RF interfaces are not installed on the
executing system.  To do this, the plugins are not linked by the linker
at compile time, but opened at runtime via dlopen() and dropped in case
of failure due to missing dependencies.
master
Robert Falkenberg 3 years ago
parent acecb1c303
commit 3a73d84294

@ -57,6 +57,7 @@ option(DISABLE_SIMD "Disable SIMD instructions" OFF)
option(AUTO_DETECT_ISA "Autodetect supported ISA extensions" ON) option(AUTO_DETECT_ISA "Autodetect supported ISA extensions" ON)
option(ENABLE_GUI "Enable GUI (using srsGUI)" ON) option(ENABLE_GUI "Enable GUI (using srsGUI)" ON)
option(ENABLE_RF_PLUGINS "Enable RF plugins" ON)
option(ENABLE_UHD "Enable UHD" ON) option(ENABLE_UHD "Enable UHD" ON)
option(ENABLE_BLADERF "Enable BladeRF" ON) option(ENABLE_BLADERF "Enable BladeRF" ON)
option(ENABLE_SOAPYSDR "Enable SoapySDR" ON) option(ENABLE_SOAPYSDR "Enable SoapySDR" ON)

@ -54,7 +54,7 @@ endif(SRSGUI_FOUND)
if (ZEROMQ_FOUND) if (ZEROMQ_FOUND)
add_executable(zmq_remote_rx zmq_remote_rx.c) add_executable(zmq_remote_rx zmq_remote_rx.c)
target_link_libraries(zmq_remote_rx srsran_phy srsran_rf) target_link_libraries(zmq_remote_rx srsran_phy srsran_rf ${ZEROMQ_LIBRARIES})
endif (ZEROMQ_FOUND) endif (ZEROMQ_FOUND)
################################################################# #################################################################

@ -63,6 +63,73 @@ typedef struct {
typedef void (*srsran_rf_error_handler_t)(void* arg, srsran_rf_error_t error); typedef void (*srsran_rf_error_handler_t)(void* arg, srsran_rf_error_t error);
/* RF frontend API */
typedef struct {
const char* name;
const char* (*srsran_rf_devname)(void* h);
int (*srsran_rf_start_rx_stream)(void* h, bool now);
int (*srsran_rf_stop_rx_stream)(void* h);
void (*srsran_rf_flush_buffer)(void* h);
bool (*srsran_rf_has_rssi)(void* h);
float (*srsran_rf_get_rssi)(void* h);
void (*srsran_rf_suppress_stdout)(void* h);
void (*srsran_rf_register_error_handler)(void* h, srsran_rf_error_handler_t error_handler, void* arg);
int (*srsran_rf_open)(char* args, void** h);
int (*srsran_rf_open_multi)(char* args, void** h, uint32_t nof_channels);
int (*srsran_rf_close)(void* h);
double (*srsran_rf_set_rx_srate)(void* h, double freq);
int (*srsran_rf_set_rx_gain)(void* h, double gain);
int (*srsran_rf_set_rx_gain_ch)(void* h, uint32_t ch, double gain);
int (*srsran_rf_set_tx_gain)(void* h, double gain);
int (*srsran_rf_set_tx_gain_ch)(void* h, uint32_t ch, double gain);
double (*srsran_rf_get_rx_gain)(void* h);
double (*srsran_rf_get_tx_gain)(void* h);
srsran_rf_info_t* (*srsran_rf_get_info)(void* h);
double (*srsran_rf_set_rx_freq)(void* h, uint32_t ch, double freq);
double (*srsran_rf_set_tx_srate)(void* h, double freq);
double (*srsran_rf_set_tx_freq)(void* h, uint32_t ch, double freq);
void (*srsran_rf_get_time)(void* h, time_t* secs, double* frac_secs);
void (*srsran_rf_sync_pps)(void* h);
int (*srsran_rf_recv_with_time)(void* h,
void* data,
uint32_t nsamples,
bool blocking,
time_t* secs,
double* frac_secs);
int (*srsran_rf_recv_with_time_multi)(void* h,
void** data,
uint32_t nsamples,
bool blocking,
time_t* secs,
double* frac_secs);
int (*srsran_rf_send_timed)(void* h,
void* data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);
int (*srsran_rf_send_timed_multi)(void* h,
void** data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);
} rf_dev_t;
typedef struct {
const char* plugin_name;
void* dl_handle;
rf_dev_t* rf_api;
} srsran_rf_plugin_t;
SRSRAN_API int srsran_rf_load_plugins();
SRSRAN_API int srsran_rf_open(srsran_rf_t* h, char* args); SRSRAN_API int srsran_rf_open(srsran_rf_t* h, char* args);
SRSRAN_API int srsran_rf_open_multi(srsran_rf_t* h, char* args, uint32_t nof_channels); SRSRAN_API int srsran_rf_open_multi(srsran_rf_t* h, char* args, uint32_t nof_channels);

@ -11,13 +11,32 @@ if(RF_FOUND)
add_library(srsran_rf_utils STATIC rf_utils.c) add_library(srsran_rf_utils STATIC rf_utils.c)
target_link_libraries(srsran_rf_utils srsran_phy) target_link_libraries(srsran_rf_utils srsran_phy)
# Include common RF files # Top-level RF library sources
set(SOURCES_RF "") set(SOURCES_RF "")
list(APPEND SOURCES_RF rf_imp.c) list(APPEND SOURCES_RF rf_imp.c)
# Lists of static (builtin) and dynamic RF plugins
set(STATIC_PLUGINS "")
set(DYNAMIC_PLUGINS "")
if (ENABLE_RF_PLUGINS)
add_definitions(-DENABLE_RF_PLUGINS)
endif (ENABLE_RF_PLUGINS)
# RF plugins
if (UHD_FOUND) if (UHD_FOUND)
add_definitions(-DENABLE_UHD) add_definitions(-DENABLE_UHD)
list(APPEND SOURCES_RF rf_uhd_imp.cc) set(SOURCES_UHD rf_uhd_imp.cc)
if (ENABLE_RF_PLUGINS)
add_library(srsran_rf_uhd SHARED ${SOURCES_UHD})
set_target_properties(srsran_rf_uhd PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
list(APPEND DYNAMIC_PLUGINS srsran_rf_uhd)
else (ENABLE_RF_PLUGINS)
add_library(srsran_rf_uhd STATIC ${SOURCES_UHD})
list(APPEND STATIC_PLUGINS srsran_rf_uhd)
endif (ENABLE_RF_PLUGINS)
target_link_libraries(srsran_rf_uhd srsran_rf_utils srsran_phy ${UHD_LIBRARIES} ${Boost_LIBRARIES})
install(TARGETS srsran_rf_uhd DESTINATION ${LIBRARY_DIR})
# If found, add a macro to inform the UHD driver about the available feature # If found, add a macro to inform the UHD driver about the available feature
if (UHD_ENABLE_X300_FW_RESET) if (UHD_ENABLE_X300_FW_RESET)
@ -31,70 +50,100 @@ if(RF_FOUND)
endif(UHD_ENABLE_CUSTOM_RFNOC) endif(UHD_ENABLE_CUSTOM_RFNOC)
endif (UHD_FOUND) endif (UHD_FOUND)
if (UHD_FOUND AND UHD_ENABLE_CUSTOM_RFNOC)
add_executable(rfnoc_test rfnoc_test.cc)
target_link_libraries(rfnoc_test srsran_rf ${UHD_LIBRARIES} ${Boost_LIBRARIES} /usr/lib/x86_64-linux-gnu/libboost_system.so)
message(info ${Boost_LIBRARIES})
endif (UHD_FOUND AND UHD_ENABLE_CUSTOM_RFNOC)
if (BLADERF_FOUND) if (BLADERF_FOUND)
add_definitions(-DENABLE_BLADERF) add_definitions(-DENABLE_BLADERF)
list(APPEND SOURCES_RF rf_blade_imp.c) set(SOURCES_BLADE rf_blade_imp.c)
if (ENABLE_RF_PLUGINS)
add_library(srsran_rf_blade SHARED ${SOURCES_BLADE})
set_target_properties(srsran_rf_blade PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
list(APPEND DYNAMIC_PLUGINS srsran_rf_blade)
else (ENABLE_RF_PLUGINS)
add_library(srsran_rf_blade STATIC ${SOURCES_BLADE})
list(APPEND STATIC_PLUGINS srsran_rf_blade)
endif (ENABLE_RF_PLUGINS)
target_link_libraries(srsran_rf_blade srsran_rf_utils srsran_phy ${BLADERF_LIBRARIES})
install(TARGETS srsran_rf_blade DESTINATION ${LIBRARY_DIR})
endif (BLADERF_FOUND) endif (BLADERF_FOUND)
if (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR) if (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR)
add_definitions(-DENABLE_SOAPYSDR) add_definitions(-DENABLE_SOAPYSDR)
list(APPEND SOURCES_RF rf_soapy_imp.c) set(SOURCES_SOAPY rf_soapy_imp.c)
if (ENABLE_RF_PLUGINS)
add_library(srsran_rf_soapy SHARED ${SOURCES_SOAPY})
set_target_properties(srsran_rf_soapy PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
list(APPEND DYNAMIC_PLUGINS srsran_rf_soapy)
else (ENABLE_RF_PLUGINS)
add_library(srsran_rf_soapy STATIC ${SOURCES_SOAPY})
list(APPEND STATIC_PLUGINS srsran_rf_soapy)
endif (ENABLE_RF_PLUGINS)
target_link_libraries(srsran_rf_soapy srsran_rf_utils srsran_phy ${SOAPYSDR_LIBRARIES})
install(TARGETS srsran_rf_soapy DESTINATION ${LIBRARY_DIR})
endif (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR) endif (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR)
if(SKIQ_FOUND) if(SKIQ_FOUND)
add_executable(skiq_pps_test skiq_pps_test.c) add_executable(skiq_pps_test skiq_pps_test.c)
target_link_libraries(skiq_pps_test ${SKIQ_LIBRARIES} rt pthread m) target_link_libraries(skiq_pps_test ${SKIQ_LIBRARIES} rt pthread m)
add_definitions(-DENABLE_SIDEKIQ) add_definitions(-DENABLE_SIDEKIQ)
list(APPEND SOURCES_RF rf_skiq_imp.c rf_skiq_imp_card.c rf_skiq_imp_port.c) set(SOURCES_SKIQ rf_skiq_imp.c rf_skiq_imp_card.c rf_skiq_imp_port.c)
if (ENABLE_RF_PLUGINS)
add_library(srsran_rf_skiq SHARED ${SOURCES_SKIQ})
set_target_properties(srsran_rf_skiq PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
list(APPEND DYNAMIC_PLUGINS srsran_rf_skiq)
else (ENABLE_RF_PLUGINS)
add_library(srsran_rf_skiq STATIC ${SOURCES_SKIQ})
list(APPEND STATIC_PLUGINS srsran_rf_skiq)
endif (ENABLE_RF_PLUGINS)
target_link_libraries(srsran_rf_skiq srsran_rf_utils srsran_phy ${SKIQ_LIBRARIES} rt)
install(TARGETS srsran_rf_skiq DESTINATION ${LIBRARY_DIR})
endif(SKIQ_FOUND) endif(SKIQ_FOUND)
if (ZEROMQ_FOUND) if (ZEROMQ_FOUND)
add_definitions(-DENABLE_ZEROMQ) add_definitions(-DENABLE_ZEROMQ)
list(APPEND SOURCES_RF rf_zmq_imp.c rf_zmq_imp_tx.c rf_zmq_imp_rx.c) set(SOURCES_ZMQ rf_zmq_imp.c rf_zmq_imp_tx.c rf_zmq_imp_rx.c)
if (ENABLE_RF_PLUGINS)
add_library(srsran_rf_zmq SHARED ${SOURCES_ZMQ})
set_target_properties(srsran_rf_zmq PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
list(APPEND DYNAMIC_PLUGINS srsran_rf_zmq)
else (ENABLE_RF_PLUGINS)
add_library(srsran_rf_zmq STATIC ${SOURCES_ZMQ})
list(APPEND STATIC_PLUGINS srsran_rf_zmq)
endif (ENABLE_RF_PLUGINS)
target_link_libraries(srsran_rf_zmq srsran_rf_utils srsran_phy ${ZEROMQ_LIBRARIES})
install(TARGETS srsran_rf_zmq DESTINATION ${LIBRARY_DIR})
endif (ZEROMQ_FOUND) endif (ZEROMQ_FOUND)
# Add sources of file-based RF directly to the RF library (not as a plugin)
list(APPEND SOURCES_RF rf_file_imp.c rf_file_imp_tx.c rf_file_imp_rx.c) list(APPEND SOURCES_RF rf_file_imp.c rf_file_imp_tx.c rf_file_imp_rx.c)
# Top-level RF library
add_library(srsran_rf_object OBJECT ${SOURCES_RF}) add_library(srsran_rf_object OBJECT ${SOURCES_RF})
set_property(TARGET srsran_rf_object PROPERTY POSITION_INDEPENDENT_CODE 1) set_property(TARGET srsran_rf_object PROPERTY POSITION_INDEPENDENT_CODE 1)
if (ENABLE_RF_PLUGINS)
add_library(srsran_rf STATIC $<TARGET_OBJECTS:srsran_rf_object>) add_dependencies(srsran_rf_object ${DYNAMIC_PLUGINS})
add_library(srsran_rf_shared SHARED $<TARGET_OBJECTS:srsran_rf_object>) add_library(srsran_rf SHARED $<TARGET_OBJECTS:srsran_rf_object>)
target_link_libraries(srsran_rf dl)
# Add $ORIGIN (i.e. current location of this library) to rpath of srsran_rf.
# This ensures that it will find the plugins that reside in the same directory as the library
set_target_properties(srsran_rf PROPERTIES BUILD_RPATH "\$ORIGIN/")
set_target_properties(srsran_rf PROPERTIES INSTALL_RPATH "\$ORIGIN/")
else (ENABLE_RF_PLUGINS)
# Without RF plugins, we aggregate everything in a static library (builtin plugins)
add_library(srsran_rf STATIC $<TARGET_OBJECTS:srsran_rf_object>)
target_link_libraries(srsran_rf ${STATIC_PLUGINS})
endif (ENABLE_RF_PLUGINS)
target_link_libraries(srsran_rf srsran_rf_utils srsran_phy) target_link_libraries(srsran_rf srsran_rf_utils srsran_phy)
set_target_properties(srsran_rf PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION}) set_target_properties(srsran_rf PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
target_link_libraries(srsran_rf_shared srsran_rf_utils srsran_phy) install(TARGETS srsran_rf DESTINATION ${LIBRARY_DIR})
set_target_properties(srsran_rf_shared PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
if (UHD_FOUND)
target_link_libraries(srsran_rf ${UHD_LIBRARIES} ${Boost_LIBRARIES}) # Ubuntu 18.04 requires 'system' from Boost_LIBRARIES
target_link_libraries(srsran_rf_shared ${UHD_LIBRARIES} ${Boost_LIBRARIES})
endif (UHD_FOUND)
if (BLADERF_FOUND)
target_link_libraries(srsran_rf ${BLADERF_LIBRARIES})
target_link_libraries(srsran_rf_shared ${BLADERF_LIBRARIES})
endif (BLADERF_FOUND)
if (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR) # Tests
target_link_libraries(srsran_rf ${SOAPYSDR_LIBRARIES}) if (UHD_FOUND AND UHD_ENABLE_CUSTOM_RFNOC)
target_link_libraries(srsran_rf_shared ${SOAPYSDR_LIBRARIES}) add_executable(rfnoc_test rfnoc_test.cc)
endif (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR) target_link_libraries(rfnoc_test srsran_rf ${UHD_LIBRARIES} ${Boost_LIBRARIES} /usr/lib/x86_64-linux-gnu/libboost_system.so)
message(info ${Boost_LIBRARIES})
if(SKIQ_FOUND) endif (UHD_FOUND AND UHD_ENABLE_CUSTOM_RFNOC)
target_link_libraries(srsran_rf ${SKIQ_LIBRARIES} rt)
target_link_libraries(srsran_rf_shared ${SKIQ_LIBRARIES} rt)
endif(SKIQ_FOUND)
if (ZEROMQ_FOUND) if (ZEROMQ_FOUND)
target_link_libraries(srsran_rf ${ZEROMQ_LIBRARIES})
target_link_libraries(srsran_rf_shared ${ZEROMQ_LIBRARIES})
add_executable(rf_zmq_test rf_zmq_test.c) add_executable(rf_zmq_test rf_zmq_test.c)
target_link_libraries(rf_zmq_test srsran_rf) target_link_libraries(rf_zmq_test srsran_rf)
#add_test(rf_zmq_test rf_zmq_test) #add_test(rf_zmq_test rf_zmq_test)
@ -103,6 +152,4 @@ if(RF_FOUND)
add_executable(rf_file_test rf_file_test.c) add_executable(rf_file_test rf_file_test.c)
target_link_libraries(rf_file_test srsran_rf) target_link_libraries(rf_file_test srsran_rf)
add_test(rf_file_test rf_file_test) add_test(rf_file_test rf_file_test)
INSTALL(TARGETS srsran_rf DESTINATION ${LIBRARY_DIR})
endif(RF_FOUND) endif(RF_FOUND)

@ -15,6 +15,7 @@
#include <unistd.h> #include <unistd.h>
#include "rf_blade_imp.h" #include "rf_blade_imp.h"
#include "rf_plugin.h"
#include "srsran/phy/common/timestamp.h" #include "srsran/phy/common/timestamp.h"
#include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/vector.h" #include "srsran/phy/utils/vector.h"
@ -535,3 +536,44 @@ int rf_blade_send_timed(void* h,
return nsamples; return nsamples;
} }
rf_dev_t srsran_rf_dev_blade = {"bladeRF",
rf_blade_devname,
rf_blade_start_rx_stream,
rf_blade_stop_rx_stream,
rf_blade_flush_buffer,
rf_blade_has_rssi,
rf_blade_get_rssi,
rf_blade_suppress_stdout,
rf_blade_register_error_handler,
rf_blade_open,
.srsran_rf_open_multi = rf_blade_open_multi,
rf_blade_close,
rf_blade_set_rx_srate,
rf_blade_set_rx_gain,
rf_blade_set_rx_gain_ch,
rf_blade_set_tx_gain,
rf_blade_set_tx_gain_ch,
rf_blade_get_rx_gain,
rf_blade_get_tx_gain,
rf_blade_get_info,
rf_blade_set_rx_freq,
rf_blade_set_tx_srate,
rf_blade_set_tx_freq,
rf_blade_get_time,
NULL,
rf_blade_recv_with_time,
rf_blade_recv_with_time_multi,
rf_blade_send_timed,
.srsran_rf_send_timed_multi = rf_blade_send_timed_multi};
#ifdef ENABLE_RF_PLUGINS
int register_plugin(rf_dev_t** rf_api)
{
if (rf_api == NULL) {
return SRSRAN_ERROR;
}
*rf_api = &srsran_rf_dev_blade;
return SRSRAN_SUCCESS;
}
#endif /* ENABLE_RF_PLUGINS */

@ -10,11 +10,16 @@
* *
*/ */
#ifndef SRSRAN_RF_BLADE_IMP_H_
#define SRSRAN_RF_BLADE_IMP_H_
#include "srsran/config.h" #include "srsran/config.h"
#include "srsran/phy/rf/rf.h" #include "srsran/phy/rf/rf.h"
#define DEVNAME "bladerf" #define DEVNAME "bladerf"
extern rf_dev_t srsran_rf_dev_blade;
SRSRAN_API int rf_blade_open(char* args, void** handler); SRSRAN_API int rf_blade_open(char* args, void** handler);
SRSRAN_API int rf_blade_open_multi(char* args, void** handler, uint32_t nof_channels); SRSRAN_API int rf_blade_open_multi(char* args, void** handler, uint32_t nof_channels);
@ -90,3 +95,5 @@ SRSRAN_API int rf_blade_send_timed(void* h,
bool blocking, bool blocking,
bool is_start_of_burst, bool is_start_of_burst,
bool is_end_of_burst); bool is_end_of_burst);
#endif /* SRSRAN_RF_BLADE_IMP_H_ */

@ -13,276 +13,58 @@
#include "srsran/phy/rf/rf.h" #include "srsran/phy/rf/rf.h"
#include <stdbool.h> #include <stdbool.h>
/* RF frontend API */
typedef struct {
const char* name;
const char* (*srsran_rf_devname)(void* h);
int (*srsran_rf_start_rx_stream)(void* h, bool now);
int (*srsran_rf_stop_rx_stream)(void* h);
void (*srsran_rf_flush_buffer)(void* h);
bool (*srsran_rf_has_rssi)(void* h);
float (*srsran_rf_get_rssi)(void* h);
void (*srsran_rf_suppress_stdout)(void* h);
void (*srsran_rf_register_error_handler)(void* h, srsran_rf_error_handler_t error_handler, void* arg);
int (*srsran_rf_open)(char* args, void** h);
int (*srsran_rf_open_multi)(char* args, void** h, uint32_t nof_channels);
int (*srsran_rf_close)(void* h);
double (*srsran_rf_set_rx_srate)(void* h, double freq);
int (*srsran_rf_set_rx_gain)(void* h, double gain);
int (*srsran_rf_set_rx_gain_ch)(void* h, uint32_t ch, double gain);
int (*srsran_rf_set_tx_gain)(void* h, double gain);
int (*srsran_rf_set_tx_gain_ch)(void* h, uint32_t ch, double gain);
double (*srsran_rf_get_rx_gain)(void* h);
double (*srsran_rf_get_tx_gain)(void* h);
srsran_rf_info_t* (*srsran_rf_get_info)(void* h);
double (*srsran_rf_set_rx_freq)(void* h, uint32_t ch, double freq);
double (*srsran_rf_set_tx_srate)(void* h, double freq);
double (*srsran_rf_set_tx_freq)(void* h, uint32_t ch, double freq);
void (*srsran_rf_get_time)(void* h, time_t* secs, double* frac_secs);
void (*srsran_rf_sync_pps)(void* h);
int (*srsran_rf_recv_with_time)(void* h,
void* data,
uint32_t nsamples,
bool blocking,
time_t* secs,
double* frac_secs);
int (*srsran_rf_recv_with_time_multi)(void* h,
void** data,
uint32_t nsamples,
bool blocking,
time_t* secs,
double* frac_secs);
int (*srsran_rf_send_timed)(void* h,
void* data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);
int (*srsran_rf_send_timed_multi)(void* h,
void** data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);
} rf_dev_t;
/* Define implementation for UHD */ /* Define implementation for UHD */
#ifdef ENABLE_UHD #ifdef ENABLE_UHD
#ifdef ENABLE_RF_PLUGINS
static srsran_rf_plugin_t plugin_uhd = {"libsrsran_rf_uhd.so", NULL, NULL};
#else
#include "rf_uhd_imp.h" #include "rf_uhd_imp.h"
static srsran_rf_plugin_t plugin_uhd = {"", NULL, &srsran_rf_dev_uhd};
static rf_dev_t dev_uhd = {"UHD", #endif
rf_uhd_devname,
rf_uhd_start_rx_stream,
rf_uhd_stop_rx_stream,
rf_uhd_flush_buffer,
rf_uhd_has_rssi,
rf_uhd_get_rssi,
rf_uhd_suppress_stdout,
rf_uhd_register_error_handler,
rf_uhd_open,
.srsran_rf_open_multi = rf_uhd_open_multi,
rf_uhd_close,
rf_uhd_set_rx_srate,
rf_uhd_set_rx_gain,
rf_uhd_set_rx_gain_ch,
rf_uhd_set_tx_gain,
rf_uhd_set_tx_gain_ch,
rf_uhd_get_rx_gain,
rf_uhd_get_tx_gain,
rf_uhd_get_info,
rf_uhd_set_rx_freq,
rf_uhd_set_tx_srate,
rf_uhd_set_tx_freq,
rf_uhd_get_time,
rf_uhd_sync_pps,
rf_uhd_recv_with_time,
rf_uhd_recv_with_time_multi,
rf_uhd_send_timed,
.srsran_rf_send_timed_multi = rf_uhd_send_timed_multi};
#endif #endif
/* Define implementation for bladeRF */ /* Define implementation for bladeRF */
#ifdef ENABLE_BLADERF #ifdef ENABLE_BLADERF
#ifdef ENABLE_RF_PLUGINS
static srsran_rf_plugin_t plugin_blade = {"libsrsran_rf_blade.so", NULL, NULL};
#else
#include "rf_blade_imp.h" #include "rf_blade_imp.h"
static srsran_rf_plugin_t plugin_blade = {"", NULL, &srsran_rf_dev_blade};
static rf_dev_t dev_blade = {"bladeRF", #endif
rf_blade_devname,
rf_blade_start_rx_stream,
rf_blade_stop_rx_stream,
rf_blade_flush_buffer,
rf_blade_has_rssi,
rf_blade_get_rssi,
rf_blade_suppress_stdout,
rf_blade_register_error_handler,
rf_blade_open,
.srsran_rf_open_multi = rf_blade_open_multi,
rf_blade_close,
rf_blade_set_rx_srate,
rf_blade_set_rx_gain,
rf_blade_set_rx_gain_ch,
rf_blade_set_tx_gain,
rf_blade_set_tx_gain_ch,
rf_blade_get_rx_gain,
rf_blade_get_tx_gain,
rf_blade_get_info,
rf_blade_set_rx_freq,
rf_blade_set_tx_srate,
rf_blade_set_tx_freq,
rf_blade_get_time,
NULL,
rf_blade_recv_with_time,
rf_blade_recv_with_time_multi,
rf_blade_send_timed,
.srsran_rf_send_timed_multi = rf_blade_send_timed_multi};
#endif #endif
/* Define implementation for SoapySDR */
#ifdef ENABLE_SOAPYSDR #ifdef ENABLE_SOAPYSDR
#ifdef ENABLE_RF_PLUGINS
static srsran_rf_plugin_t plugin_soapy = {"libsrsran_rf_soapy.so", NULL, NULL};
#else
#include "rf_soapy_imp.h" #include "rf_soapy_imp.h"
static srsran_rf_plugin_t plugin_soapy = {"", NULL, &srsran_rf_dev_soapy};
static rf_dev_t dev_soapy = {"soapy", #endif
rf_soapy_devname,
rf_soapy_start_rx_stream,
rf_soapy_stop_rx_stream,
rf_soapy_flush_buffer,
rf_soapy_has_rssi,
rf_soapy_get_rssi,
rf_soapy_suppress_stdout,
rf_soapy_register_error_handler,
rf_soapy_open,
rf_soapy_open_multi,
rf_soapy_close,
rf_soapy_set_rx_srate,
rf_soapy_set_rx_gain,
rf_soapy_set_rx_gain_ch,
rf_soapy_set_tx_gain,
rf_soapy_set_tx_gain_ch,
rf_soapy_get_rx_gain,
rf_soapy_get_tx_gain,
rf_soapy_get_info,
rf_soapy_set_rx_freq,
rf_soapy_set_tx_srate,
rf_soapy_set_tx_freq,
rf_soapy_get_time,
NULL,
rf_soapy_recv_with_time,
rf_soapy_recv_with_time_multi,
rf_soapy_send_timed,
.srsran_rf_send_timed_multi = rf_soapy_send_timed_multi};
#endif #endif
/* Define implementation for UHD */ /* Define implementation for ZeroMQ */
#ifdef ENABLE_ZEROMQ #ifdef ENABLE_ZEROMQ
#ifdef ENABLE_RF_PLUGINS
static srsran_rf_plugin_t plugin_zmq = {"libsrsran_rf_zmq.so", NULL, NULL};
#else
#include "rf_zmq_imp.h" #include "rf_zmq_imp.h"
static srsran_rf_plugin_t plugin_zmq = {"", NULL, &srsran_rf_dev_zmq};
static rf_dev_t dev_zmq = {"zmq", #endif
rf_zmq_devname,
rf_zmq_start_rx_stream,
rf_zmq_stop_rx_stream,
rf_zmq_flush_buffer,
rf_zmq_has_rssi,
rf_zmq_get_rssi,
rf_zmq_suppress_stdout,
rf_zmq_register_error_handler,
rf_zmq_open,
.srsran_rf_open_multi = rf_zmq_open_multi,
rf_zmq_close,
rf_zmq_set_rx_srate,
rf_zmq_set_rx_gain,
rf_zmq_set_rx_gain_ch,
rf_zmq_set_tx_gain,
rf_zmq_set_tx_gain_ch,
rf_zmq_get_rx_gain,
rf_zmq_get_tx_gain,
rf_zmq_get_info,
rf_zmq_set_rx_freq,
rf_zmq_set_tx_srate,
rf_zmq_set_tx_freq,
rf_zmq_get_time,
NULL,
rf_zmq_recv_with_time,
rf_zmq_recv_with_time_multi,
rf_zmq_send_timed,
.srsran_rf_send_timed_multi = rf_zmq_send_timed_multi};
#endif #endif
/* Define implementation for file-based RF */ /* Define implementation for file-based RF */
#include "rf_file_imp.h" #include "rf_file_imp.h"
static srsran_rf_plugin_t plugin_file = {"", NULL, &srsran_rf_dev_file};
static rf_dev_t dev_file = {"file",
rf_file_devname,
rf_file_start_rx_stream,
rf_file_stop_rx_stream,
rf_file_flush_buffer,
rf_file_has_rssi,
rf_file_get_rssi,
rf_file_suppress_stdout,
rf_file_register_error_handler,
rf_file_open,
.srsran_rf_open_multi = rf_file_open_multi,
rf_file_close,
rf_file_set_rx_srate,
rf_file_set_rx_gain,
rf_file_set_rx_gain_ch,
rf_file_set_tx_gain,
rf_file_set_tx_gain_ch,
rf_file_get_rx_gain,
rf_file_get_tx_gain,
rf_file_get_info,
rf_file_set_rx_freq,
rf_file_set_tx_srate,
rf_file_set_tx_freq,
rf_file_get_time,
NULL,
rf_file_recv_with_time,
rf_file_recv_with_time_multi,
rf_file_send_timed,
.srsran_rf_send_timed_multi = rf_file_send_timed_multi};
/* Define implementation for Sidekiq */ /* Define implementation for Sidekiq */
#ifdef ENABLE_SIDEKIQ #ifdef ENABLE_SIDEKIQ
#ifdef ENABLE_RF_PLUGINS
static srsran_rf_plugin_t plugin_skiq = {"libsrsran_rf_skiq.so", NULL, NULL};
#else
#include "rf_skiq_imp.h" #include "rf_skiq_imp.h"
static srsran_rf_plugin_t plugin_skiq = {"", NULL, &srsran_rf_dev_skiq};
static rf_dev_t dev_skiq = {.name = "Sidekiq", #endif
.srsran_rf_devname = rf_skiq_devname,
.srsran_rf_start_rx_stream = rf_skiq_start_rx_stream,
.srsran_rf_stop_rx_stream = rf_skiq_stop_rx_stream,
.srsran_rf_flush_buffer = rf_skiq_flush_buffer,
.srsran_rf_has_rssi = rf_skiq_has_rssi,
.srsran_rf_get_rssi = rf_skiq_get_rssi,
.srsran_rf_suppress_stdout = rf_skiq_suppress_stdout,
.srsran_rf_register_error_handler = rf_skiq_register_error_handler,
.srsran_rf_open = rf_skiq_open,
.srsran_rf_open_multi = rf_skiq_open_multi,
.srsran_rf_close = rf_skiq_close,
.srsran_rf_set_rx_srate = rf_skiq_set_rx_srate,
.srsran_rf_set_tx_srate = rf_skiq_set_tx_srate,
.srsran_rf_set_rx_gain = rf_skiq_set_rx_gain,
.srsran_rf_set_tx_gain = rf_skiq_set_tx_gain,
.srsran_rf_set_tx_gain_ch = rf_skiq_set_tx_gain_ch,
.srsran_rf_set_rx_gain_ch = rf_skiq_set_rx_gain_ch,
.srsran_rf_get_rx_gain = rf_skiq_get_rx_gain,
.srsran_rf_get_tx_gain = rf_skiq_get_tx_gain,
.srsran_rf_get_info = rf_skiq_get_info,
.srsran_rf_set_rx_freq = rf_skiq_set_rx_freq,
.srsran_rf_set_tx_freq = rf_skiq_set_tx_freq,
.srsran_rf_get_time = rf_skiq_get_time,
.srsran_rf_recv_with_time = rf_skiq_recv_with_time,
.srsran_rf_recv_with_time_multi = rf_skiq_recv_with_time_multi,
.srsran_rf_send_timed = rf_skiq_send_timed,
.srsran_rf_send_timed_multi = rf_skiq_send_timed_multi};
#endif #endif
//#define ENABLE_DUMMY_DEV //#define ENABLE_DUMMY_DEV
@ -295,34 +77,37 @@ int dummy_rcv()
} }
void dummy_fnc() {} void dummy_fnc() {}
static rf_dev_t dev_dummy = {"dummy", dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, static rf_dev_t srsran_rf_dev_dummy = {
dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, "dummy", dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc,
dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_rcv, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc,
dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc}; dummy_fnc, dummy_fnc, dummy_fnc, dummy_rcv, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc};
static srsran_rf_plugin_t plugin_dummy = {"", NULL, &srsran_rf_dev_dummy};
#endif #endif
/** /**
* Collection of all currently supported RF devices * Collection of all currently available RF plugins
*/ */
static rf_dev_t* available_devices[] = { static srsran_rf_plugin_t* rf_plugins[] = {
#ifdef ENABLE_UHD #ifdef ENABLE_UHD
&dev_uhd, &plugin_uhd,
#endif #endif
#ifdef ENABLE_SOAPYSDR #ifdef ENABLE_SOAPYSDR
&dev_soapy, &plugin_soapy,
#endif #endif
#ifdef ENABLE_BLADERF #ifdef ENABLE_BLADERF
&dev_blade, &plugin_blade,
#endif #endif
#ifdef ENABLE_ZEROMQ #ifdef ENABLE_ZEROMQ
&dev_zmq, &plugin_zmq,
#endif #endif
#ifdef ENABLE_SIDEKIQ #ifdef ENABLE_SIDEKIQ
&dev_skiq, &plugin_skiq,
#endif #endif
#ifdef ENABLE_DUMMY_DEV #ifdef ENABLE_DUMMY_DEV
&dev_dummy, &plugin_dummy,
#endif #endif
&dev_file, &plugin_file,
NULL}; NULL};

@ -10,9 +10,6 @@
* *
*/ */
#ifndef SRSRAN_RF_IMP_TRX_H
#define SRSRAN_RF_IMP_TRX_H
#include "rf_file_imp.h" #include "rf_file_imp.h"
#include "rf_file_imp_trx.h" #include "rf_file_imp_trx.h"
#include "rf_helper.h" #include "rf_helper.h"
@ -856,4 +853,32 @@ clean_exit:
return ret; return ret;
} }
#endif rf_dev_t srsran_rf_dev_file = {"file",
rf_file_devname,
rf_file_start_rx_stream,
rf_file_stop_rx_stream,
rf_file_flush_buffer,
rf_file_has_rssi,
rf_file_get_rssi,
rf_file_suppress_stdout,
rf_file_register_error_handler,
rf_file_open,
.srsran_rf_open_multi = rf_file_open_multi,
rf_file_close,
rf_file_set_rx_srate,
rf_file_set_rx_gain,
rf_file_set_rx_gain_ch,
rf_file_set_tx_gain,
rf_file_set_tx_gain_ch,
rf_file_get_rx_gain,
rf_file_get_tx_gain,
rf_file_get_info,
rf_file_set_rx_freq,
rf_file_set_tx_srate,
rf_file_set_tx_freq,
rf_file_get_time,
NULL,
rf_file_recv_with_time,
rf_file_recv_with_time_multi,
rf_file_send_timed,
.srsran_rf_send_timed_multi = rf_file_send_timed_multi};

@ -23,6 +23,8 @@
#define PARAM_LEN (128) #define PARAM_LEN (128)
#define PARAM_LEN_SHORT (PARAM_LEN / 2) #define PARAM_LEN_SHORT (PARAM_LEN / 2)
extern rf_dev_t srsran_rf_dev_file;
SRSRAN_API const char* rf_file_devname(void* h); SRSRAN_API const char* rf_file_devname(void* h);
SRSRAN_API int rf_file_start_rx_stream(void* h, bool now); SRSRAN_API int rf_file_start_rx_stream(void* h, bool now);

@ -10,17 +10,19 @@
* *
*/ */
#include <string.h>
#include "rf_dev.h" #include "rf_dev.h"
#include "srsran/phy/rf/rf.h" #include "srsran/phy/rf/rf.h"
#include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/debug.h"
#include <dlfcn.h>
#include <string.h>
int rf_get_available_devices(char** devnames, int max_strlen) int rf_get_available_devices(char** devnames, int max_strlen)
{ {
int i = 0; int i = 0;
while (available_devices[i]->name) { while (rf_plugins[i] != NULL) {
strncpy(devnames[i], available_devices[i]->name, max_strlen); if (rf_plugins[i]->rf_api != NULL) {
strncpy(devnames[i], rf_plugins[i]->rf_api->name, max_strlen);
}
i++; i++;
} }
return i; return i;
@ -92,23 +94,30 @@ const char* srsran_rf_get_devname(srsran_rf_t* rf)
int srsran_rf_open_devname(srsran_rf_t* rf, const char* devname, char* args, uint32_t nof_channels) int srsran_rf_open_devname(srsran_rf_t* rf, const char* devname, char* args, uint32_t nof_channels)
{ {
if (srsran_rf_load_plugins() != SRSRAN_SUCCESS) {
ERROR("Failed to load RF plugins");
return SRSRAN_ERROR;
}
rf->thread_gain_run = false; rf->thread_gain_run = false;
bool no_rf_devs_detected = true; bool no_rf_devs_detected = true;
printf("Available RF device list:"); printf("Supported RF device list:");
for (unsigned int i = 0; available_devices[i]; i++) { for (unsigned int i = 0; rf_plugins[i] && rf_plugins[i]->rf_api; i++) {
no_rf_devs_detected = false; no_rf_devs_detected = false;
printf(" %s ", available_devices[i]->name); printf(" %s", rf_plugins[i]->rf_api->name);
} }
printf("%s\n", no_rf_devs_detected ? " <none>" : ""); printf("%s\n", no_rf_devs_detected ? " <none>" : "");
// Try to open the device if name is provided // Try to open the device if name is provided
if (devname && devname[0] != '\0') { if (devname && devname[0] != '\0') {
int i = 0; int i = 0;
while (available_devices[i] != NULL) { while (rf_plugins[i] != NULL) {
if (!strcasecmp(available_devices[i]->name, devname)) { if (rf_plugins[i]->rf_api) {
rf->dev = available_devices[i]; if (!strcasecmp(rf_plugins[i]->rf_api->name, devname)) {
return available_devices[i]->srsran_rf_open_multi(args, &rf->handler, nof_channels); rf->dev = rf_plugins[i]->rf_api;
return rf_plugins[i]->rf_api->srsran_rf_open_multi(args, &rf->handler, nof_channels);
}
} }
i++; i++;
} }
@ -120,16 +129,16 @@ int srsran_rf_open_devname(srsran_rf_t* rf, const char* devname, char* args, uin
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
// auto-mode, try to open in order of apperance in available_devices[] array // auto-mode, try to open in order of apperance in rf_plugins[] array
int i = 0; int i = 0;
while (available_devices[i] != NULL) { while (rf_plugins[i] != NULL && rf_plugins[i]->rf_api != NULL) {
printf("Trying to open RF device '%s'\n", available_devices[i]->name); printf("Trying to open RF device '%s'\n", rf_plugins[i]->rf_api->name);
if (!available_devices[i]->srsran_rf_open_multi(args, &rf->handler, nof_channels)) { if (!rf_plugins[i]->rf_api->srsran_rf_open_multi(args, &rf->handler, nof_channels)) {
rf->dev = available_devices[i]; rf->dev = rf_plugins[i]->rf_api;
printf("RF device '%s' successfully opened\n", available_devices[i]->name); printf("RF device '%s' successfully opened\n", rf_plugins[i]->rf_api->name);
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
printf("Unable to open RF device '%s'\n", available_devices[i]->name); printf("Unable to open RF device '%s'\n", rf_plugins[i]->rf_api->name);
i++; i++;
} }
@ -141,7 +150,7 @@ int srsran_rf_open_devname(srsran_rf_t* rf, const char* devname, char* args, uin
int srsran_rf_open_file(srsran_rf_t* rf, FILE** rx_files, FILE** tx_files, uint32_t nof_channels, uint32_t base_srate) int srsran_rf_open_file(srsran_rf_t* rf, FILE** rx_files, FILE** tx_files, uint32_t nof_channels, uint32_t base_srate)
{ {
rf->dev = &dev_file; rf->dev = &srsran_rf_dev_file;
// file abstraction has custom "open" function with file-related args // file abstraction has custom "open" function with file-related args
return rf_file_open_file(&rf->handler, rx_files, tx_files, nof_channels, base_srate); return rf_file_open_file(&rf->handler, rx_files, tx_files, nof_channels, base_srate);
@ -391,3 +400,85 @@ int srsran_rf_send_timed2(srsran_rf_t* rf,
{ {
return srsran_rf_send_timed3(rf, data, nsamples, secs, frac_secs, true, true, is_start_of_burst, is_end_of_burst); return srsran_rf_send_timed3(rf, data, nsamples, secs, frac_secs, true, true, is_start_of_burst, is_end_of_burst);
} }
#ifdef ENABLE_RF_PLUGINS
static void unload_plugin(srsran_rf_plugin_t* rf_plugin)
{
if (rf_plugin == NULL) {
return;
}
if (rf_plugin->dl_handle != NULL) {
rf_plugin->rf_api = NULL;
dlclose(rf_plugin->dl_handle);
rf_plugin->dl_handle = NULL;
}
}
static int load_plugin(srsran_rf_plugin_t* rf_plugin)
{
if (rf_plugin->rf_api != NULL) {
// already loaded
return SRSRAN_SUCCESS;
}
rf_plugin->dl_handle = dlopen(rf_plugin->plugin_name, RTLD_NOW);
if (rf_plugin->dl_handle == NULL) {
// Not an error, if loading failed due to missing dependencies.
// Mark this plugin as not available and return SUCCESS.
INFO("Failed to load RF plugin %s: %s", rf_plugin->plugin_name, dlerror());
rf_plugin->rf_api = NULL;
return SRSRAN_SUCCESS;
}
// clear errors
dlerror();
char* err = NULL;
// load symbols
int (*register_plugin)(rf_dev_t * *rf_api) = dlsym(rf_plugin->dl_handle, "register_plugin");
if ((err = dlerror()) != NULL) {
ERROR("Error loading symbol '%s': %s", "register_plugin", err);
goto clean_exit;
}
// register plugin
int ret = register_plugin(&rf_plugin->rf_api);
if (ret != SRSRAN_SUCCESS) {
ERROR("Failed to register RF API for plugin %s", rf_plugin->plugin_name);
goto clean_exit;
}
return SRSRAN_SUCCESS;
clean_exit:
unload_plugin(rf_plugin);
return SRSRAN_ERROR;
}
#endif /* ENABLE_RF_PLUGINS */
int srsran_rf_load_plugins()
{
#ifdef ENABLE_RF_PLUGINS
for (unsigned int i = 0; rf_plugins[i]; i++) {
if (load_plugin(rf_plugins[i]) != SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
}
printf("Active RF plugins:");
for (unsigned int i = 0; rf_plugins[i]; i++) {
if (rf_plugins[i]->dl_handle != NULL) {
printf(" %s", rf_plugins[i]->plugin_name);
}
}
printf("\n");
printf("Inactive RF plugins:");
for (unsigned int i = 0; rf_plugins[i]; i++) {
if (rf_plugins[i]->dl_handle == NULL) {
printf(" %s", rf_plugins[i]->plugin_name);
}
}
printf("\n");
#endif /* ENABLE_RF_PLUGINS */
return SRSRAN_SUCCESS;
}

@ -0,0 +1,28 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2022 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_RF_PLUGIN_H
#define SRSRAN_RF_PLUGIN_H
#include "srsran/phy/rf/rf.h"
#ifdef __cplusplus
extern "C" {
#endif
SRSRAN_API int register_plugin(rf_dev_t **rf_api);
#ifdef __cplusplus
}
#endif
#endif /* SRSRAN_RF_PLUGIN_H */

@ -15,6 +15,7 @@
#include <sidekiq_api.h> #include <sidekiq_api.h>
#include "rf_helper.h" #include "rf_helper.h"
#include "rf_plugin.h"
#include "rf_skiq_imp.h" #include "rf_skiq_imp.h"
#include "rf_skiq_imp_card.h" #include "rf_skiq_imp_card.h"
@ -939,3 +940,43 @@ int rf_skiq_send_timed_multi(void* h_,
return (int)rpm; return (int)rpm;
} }
rf_dev_t srsran_rf_dev_skiq = {.name = "Sidekiq",
.srsran_rf_devname = rf_skiq_devname,
.srsran_rf_start_rx_stream = rf_skiq_start_rx_stream,
.srsran_rf_stop_rx_stream = rf_skiq_stop_rx_stream,
.srsran_rf_flush_buffer = rf_skiq_flush_buffer,
.srsran_rf_has_rssi = rf_skiq_has_rssi,
.srsran_rf_get_rssi = rf_skiq_get_rssi,
.srsran_rf_suppress_stdout = rf_skiq_suppress_stdout,
.srsran_rf_register_error_handler = rf_skiq_register_error_handler,
.srsran_rf_open = rf_skiq_open,
.srsran_rf_open_multi = rf_skiq_open_multi,
.srsran_rf_close = rf_skiq_close,
.srsran_rf_set_rx_srate = rf_skiq_set_rx_srate,
.srsran_rf_set_tx_srate = rf_skiq_set_tx_srate,
.srsran_rf_set_rx_gain = rf_skiq_set_rx_gain,
.srsran_rf_set_tx_gain = rf_skiq_set_tx_gain,
.srsran_rf_set_tx_gain_ch = rf_skiq_set_tx_gain_ch,
.srsran_rf_set_rx_gain_ch = rf_skiq_set_rx_gain_ch,
.srsran_rf_get_rx_gain = rf_skiq_get_rx_gain,
.srsran_rf_get_tx_gain = rf_skiq_get_tx_gain,
.srsran_rf_get_info = rf_skiq_get_info,
.srsran_rf_set_rx_freq = rf_skiq_set_rx_freq,
.srsran_rf_set_tx_freq = rf_skiq_set_tx_freq,
.srsran_rf_get_time = rf_skiq_get_time,
.srsran_rf_recv_with_time = rf_skiq_recv_with_time,
.srsran_rf_recv_with_time_multi = rf_skiq_recv_with_time_multi,
.srsran_rf_send_timed = rf_skiq_send_timed,
.srsran_rf_send_timed_multi = rf_skiq_send_timed_multi};
#ifdef ENABLE_RF_PLUGINS
int register_plugin(rf_dev_t** rf_api)
{
if (rf_api == NULL) {
return SRSRAN_ERROR;
}
*rf_api = &srsran_rf_dev_skiq;
return SRSRAN_SUCCESS;
}
#endif /* ENABLE_RF_PLUGINS */

@ -16,6 +16,8 @@
#include "srsran/config.h" #include "srsran/config.h"
#include "srsran/phy/rf/rf.h" #include "srsran/phy/rf/rf.h"
extern rf_dev_t srsran_rf_dev_skiq;
SRSRAN_API int rf_skiq_open(char* args, void** handler); SRSRAN_API int rf_skiq_open(char* args, void** handler);
SRSRAN_API int rf_skiq_open_multi(char* args, void** handler, uint32_t nof_rx_antennas); SRSRAN_API int rf_skiq_open_multi(char* args, void** handler, uint32_t nof_rx_antennas);

@ -16,6 +16,7 @@
#include <unistd.h> #include <unistd.h>
#include "rf_helper.h" #include "rf_helper.h"
#include "rf_plugin.h"
#include "rf_soapy_imp.h" #include "rf_soapy_imp.h"
#include "srsran/phy/common/phy_common.h" #include "srsran/phy/common/phy_common.h"
#include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/debug.h"
@ -994,3 +995,44 @@ int rf_soapy_send_timed_multi(void* h,
return n; return n;
} }
rf_dev_t srsran_rf_dev_soapy = {"soapy",
rf_soapy_devname,
rf_soapy_start_rx_stream,
rf_soapy_stop_rx_stream,
rf_soapy_flush_buffer,
rf_soapy_has_rssi,
rf_soapy_get_rssi,
rf_soapy_suppress_stdout,
rf_soapy_register_error_handler,
rf_soapy_open,
rf_soapy_open_multi,
rf_soapy_close,
rf_soapy_set_rx_srate,
rf_soapy_set_rx_gain,
rf_soapy_set_rx_gain_ch,
rf_soapy_set_tx_gain,
rf_soapy_set_tx_gain_ch,
rf_soapy_get_rx_gain,
rf_soapy_get_tx_gain,
rf_soapy_get_info,
rf_soapy_set_rx_freq,
rf_soapy_set_tx_srate,
rf_soapy_set_tx_freq,
rf_soapy_get_time,
NULL,
rf_soapy_recv_with_time,
rf_soapy_recv_with_time_multi,
rf_soapy_send_timed,
.srsran_rf_send_timed_multi = rf_soapy_send_timed_multi};
#ifdef ENABLE_RF_PLUGINS
int register_plugin(rf_dev_t** rf_api)
{
if (rf_api == NULL) {
return SRSRAN_ERROR;
}
*rf_api = &srsran_rf_dev_soapy;
return SRSRAN_SUCCESS;
}
#endif /* ENABLE_RF_PLUGINS */

@ -20,6 +20,8 @@
#include <stdint.h> #include <stdint.h>
#define DEVNAME_SOAPY "soapy" #define DEVNAME_SOAPY "soapy"
extern rf_dev_t srsran_rf_dev_soapy;
SRSRAN_API int rf_soapy_open(char* args, void** handler); SRSRAN_API int rf_soapy_open(char* args, void** handler);
SRSRAN_API int rf_soapy_open_multi(char* args, void** handler, uint32_t num_requested_channels); SRSRAN_API int rf_soapy_open_multi(char* args, void** handler, uint32_t num_requested_channels);

@ -20,6 +20,7 @@
#include <uhd/usrp/multi_usrp.hpp> #include <uhd/usrp/multi_usrp.hpp>
#include "rf_helper.h" #include "rf_helper.h"
#include "rf_plugin.h"
#include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/vector.h" #include "srsran/phy/utils/vector.h"
@ -1535,3 +1536,44 @@ int rf_uhd_send_timed_multi(void* h,
return nsamples; return nsamples;
} }
rf_dev_t srsran_rf_dev_uhd = {"UHD",
rf_uhd_devname,
rf_uhd_start_rx_stream,
rf_uhd_stop_rx_stream,
rf_uhd_flush_buffer,
rf_uhd_has_rssi,
rf_uhd_get_rssi,
rf_uhd_suppress_stdout,
rf_uhd_register_error_handler,
rf_uhd_open,
rf_uhd_open_multi,
rf_uhd_close,
rf_uhd_set_rx_srate,
rf_uhd_set_rx_gain,
rf_uhd_set_rx_gain_ch,
rf_uhd_set_tx_gain,
rf_uhd_set_tx_gain_ch,
rf_uhd_get_rx_gain,
rf_uhd_get_tx_gain,
rf_uhd_get_info,
rf_uhd_set_rx_freq,
rf_uhd_set_tx_srate,
rf_uhd_set_tx_freq,
rf_uhd_get_time,
rf_uhd_sync_pps,
rf_uhd_recv_with_time,
rf_uhd_recv_with_time_multi,
rf_uhd_send_timed,
rf_uhd_send_timed_multi};
#ifdef ENABLE_RF_PLUGINS
int register_plugin(rf_dev_t** rf_api)
{
if (rf_api == NULL) {
return SRSRAN_ERROR;
}
*rf_api = &srsran_rf_dev_uhd;
return SRSRAN_SUCCESS;
}
#endif /* ENABLE_RF_PLUGINS */

@ -29,6 +29,8 @@ extern "C" {
#define DEVNAME_E3X0 "uhd_e3x0" #define DEVNAME_E3X0 "uhd_e3x0"
#define DEVNAME_UNKNOWN "uhd_unknown" #define DEVNAME_UNKNOWN "uhd_unknown"
extern rf_dev_t srsran_rf_dev_uhd;
SRSRAN_API int rf_uhd_open(char* args, void** handler); SRSRAN_API int rf_uhd_open(char* args, void** handler);
SRSRAN_API int rf_uhd_open_multi(char* args, void** handler, uint32_t nof_channels); SRSRAN_API int rf_uhd_open_multi(char* args, void** handler, uint32_t nof_channels);

@ -12,6 +12,7 @@
#include "rf_zmq_imp.h" #include "rf_zmq_imp.h"
#include "rf_helper.h" #include "rf_helper.h"
#include "rf_plugin.h"
#include "rf_zmq_imp_trx.h" #include "rf_zmq_imp_trx.h"
#include <math.h> #include <math.h>
#include <srsran/phy/common/phy_common.h> #include <srsran/phy/common/phy_common.h>
@ -983,3 +984,44 @@ clean_exit:
return ret; return ret;
} }
rf_dev_t srsran_rf_dev_zmq = {"zmq",
rf_zmq_devname,
rf_zmq_start_rx_stream,
rf_zmq_stop_rx_stream,
rf_zmq_flush_buffer,
rf_zmq_has_rssi,
rf_zmq_get_rssi,
rf_zmq_suppress_stdout,
rf_zmq_register_error_handler,
rf_zmq_open,
.srsran_rf_open_multi = rf_zmq_open_multi,
rf_zmq_close,
rf_zmq_set_rx_srate,
rf_zmq_set_rx_gain,
rf_zmq_set_rx_gain_ch,
rf_zmq_set_tx_gain,
rf_zmq_set_tx_gain_ch,
rf_zmq_get_rx_gain,
rf_zmq_get_tx_gain,
rf_zmq_get_info,
rf_zmq_set_rx_freq,
rf_zmq_set_tx_srate,
rf_zmq_set_tx_freq,
rf_zmq_get_time,
NULL,
rf_zmq_recv_with_time,
rf_zmq_recv_with_time_multi,
rf_zmq_send_timed,
.srsran_rf_send_timed_multi = rf_zmq_send_timed_multi};
#ifdef ENABLE_RF_PLUGINS
int register_plugin(rf_dev_t** rf_api)
{
if (rf_api == NULL) {
return SRSRAN_ERROR;
}
*rf_api = &srsran_rf_dev_zmq;
return SRSRAN_SUCCESS;
}
#endif /* ENABLE_RF_PLUGINS */

@ -21,6 +21,8 @@
#define DEVNAME_ZMQ "ZeroMQ" #define DEVNAME_ZMQ "ZeroMQ"
extern rf_dev_t srsran_rf_dev_zmq;
SRSRAN_API int rf_zmq_open(char* args, void** handler); SRSRAN_API int rf_zmq_open(char* args, void** handler);
SRSRAN_API int rf_zmq_open_multi(char* args, void** handler, uint32_t nof_channels); SRSRAN_API int rf_zmq_open_multi(char* args, void** handler, uint32_t nof_channels);

@ -234,6 +234,7 @@ int param_test(const char* args_param, const int num_channels)
int main() int main()
{ {
srsran_rf_load_plugins();
// // two Rx ports // // two Rx ports
// if (param_test("rx_port=ipc://dl0,rx_port1=ipc://dl1", 2)) { // if (param_test("rx_port=ipc://dl0,rx_port1=ipc://dl1", 2)) {
// fprintf(stderr, "Param test failed!\n"); // fprintf(stderr, "Param test failed!\n");

Loading…
Cancel
Save