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.
This commit is contained in:
Robert Falkenberg 2022-02-14 14:08:36 +01:00
parent acecb1c303
commit 3a73d84294
20 changed files with 594 additions and 323 deletions

View File

@ -57,6 +57,7 @@ option(DISABLE_SIMD "Disable SIMD instructions" OFF)
option(AUTO_DETECT_ISA "Autodetect supported ISA extensions" 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_BLADERF "Enable BladeRF" ON)
option(ENABLE_SOAPYSDR "Enable SoapySDR" ON)

View File

@ -54,7 +54,7 @@ endif(SRSGUI_FOUND)
if (ZEROMQ_FOUND)
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)
#################################################################

View File

@ -63,6 +63,73 @@ typedef struct {
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_multi(srsran_rf_t* h, char* args, uint32_t nof_channels);

View File

@ -11,13 +11,32 @@ if(RF_FOUND)
add_library(srsran_rf_utils STATIC rf_utils.c)
target_link_libraries(srsran_rf_utils srsran_phy)
# Include common RF files
# Top-level RF library sources
set(SOURCES_RF "")
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)
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 (UHD_ENABLE_X300_FW_RESET)
@ -31,70 +50,100 @@ if(RF_FOUND)
endif(UHD_ENABLE_CUSTOM_RFNOC)
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)
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)
if (SOAPYSDR_FOUND AND ENABLE_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)
if(SKIQ_FOUND)
add_executable(skiq_pps_test skiq_pps_test.c)
target_link_libraries(skiq_pps_test ${SKIQ_LIBRARIES} rt pthread m)
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)
if (ZEROMQ_FOUND)
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)
# 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)
# Top-level RF library
add_library(srsran_rf_object OBJECT ${SOURCES_RF})
set_property(TARGET srsran_rf_object PROPERTY POSITION_INDEPENDENT_CODE 1)
add_library(srsran_rf STATIC $<TARGET_OBJECTS:srsran_rf_object>)
add_library(srsran_rf_shared SHARED $<TARGET_OBJECTS:srsran_rf_object>)
if (ENABLE_RF_PLUGINS)
add_dependencies(srsran_rf_object ${DYNAMIC_PLUGINS})
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)
set_target_properties(srsran_rf PROPERTIES VERSION ${SRSRAN_VERSION_STRING} SOVERSION ${SRSRAN_SOVERSION})
target_link_libraries(srsran_rf_shared srsran_rf_utils srsran_phy)
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)
install(TARGETS srsran_rf DESTINATION ${LIBRARY_DIR})
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)
target_link_libraries(srsran_rf ${SOAPYSDR_LIBRARIES})
target_link_libraries(srsran_rf_shared ${SOAPYSDR_LIBRARIES})
endif (SOAPYSDR_FOUND AND ENABLE_SOAPYSDR)
if(SKIQ_FOUND)
target_link_libraries(srsran_rf ${SKIQ_LIBRARIES} rt)
target_link_libraries(srsran_rf_shared ${SKIQ_LIBRARIES} rt)
endif(SKIQ_FOUND)
# Tests
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 (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)
target_link_libraries(rf_zmq_test srsran_rf)
#add_test(rf_zmq_test rf_zmq_test)
@ -103,6 +152,4 @@ if(RF_FOUND)
add_executable(rf_file_test rf_file_test.c)
target_link_libraries(rf_file_test srsran_rf)
add_test(rf_file_test rf_file_test)
INSTALL(TARGETS srsran_rf DESTINATION ${LIBRARY_DIR})
endif(RF_FOUND)

View File

@ -15,6 +15,7 @@
#include <unistd.h>
#include "rf_blade_imp.h"
#include "rf_plugin.h"
#include "srsran/phy/common/timestamp.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/vector.h"
@ -535,3 +536,44 @@ int rf_blade_send_timed(void* h,
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 */

View File

@ -10,11 +10,16 @@
*
*/
#ifndef SRSRAN_RF_BLADE_IMP_H_
#define SRSRAN_RF_BLADE_IMP_H_
#include "srsran/config.h"
#include "srsran/phy/rf/rf.h"
#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_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 is_start_of_burst,
bool is_end_of_burst);
#endif /* SRSRAN_RF_BLADE_IMP_H_ */

View File

@ -13,276 +13,58 @@
#include "srsran/phy/rf/rf.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 */
#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"
static rf_dev_t 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,
.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};
static srsran_rf_plugin_t plugin_uhd = {"", NULL, &srsran_rf_dev_uhd};
#endif
#endif
/* Define implementation for 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"
static rf_dev_t 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};
static srsran_rf_plugin_t plugin_blade = {"", NULL, &srsran_rf_dev_blade};
#endif
#endif
/* Define implementation for 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"
static rf_dev_t 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};
static srsran_rf_plugin_t plugin_soapy = {"", NULL, &srsran_rf_dev_soapy};
#endif
#endif
/* Define implementation for UHD */
/* Define implementation for 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"
static rf_dev_t 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};
static srsran_rf_plugin_t plugin_zmq = {"", NULL, &srsran_rf_dev_zmq};
#endif
#endif
/* Define implementation for file-based RF */
#include "rf_file_imp.h"
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};
static srsran_rf_plugin_t plugin_file = {"", NULL, &srsran_rf_dev_file};
/* Define implementation for 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"
static rf_dev_t 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};
static srsran_rf_plugin_t plugin_skiq = {"", NULL, &srsran_rf_dev_skiq};
#endif
#endif
//#define ENABLE_DUMMY_DEV
@ -295,34 +77,37 @@ int dummy_rcv()
}
void dummy_fnc() {}
static rf_dev_t dev_dummy = {"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_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_rcv,
dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc};
static rf_dev_t srsran_rf_dev_dummy = {
"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_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
/**
* 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
&dev_uhd,
&plugin_uhd,
#endif
#ifdef ENABLE_SOAPYSDR
&dev_soapy,
&plugin_soapy,
#endif
#ifdef ENABLE_BLADERF
&dev_blade,
&plugin_blade,
#endif
#ifdef ENABLE_ZEROMQ
&dev_zmq,
&plugin_zmq,
#endif
#ifdef ENABLE_SIDEKIQ
&dev_skiq,
&plugin_skiq,
#endif
#ifdef ENABLE_DUMMY_DEV
&dev_dummy,
&plugin_dummy,
#endif
&dev_file,
&plugin_file,
NULL};

View File

@ -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_trx.h"
#include "rf_helper.h"
@ -856,4 +853,32 @@ clean_exit:
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};

View File

@ -23,6 +23,8 @@
#define PARAM_LEN (128)
#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 int rf_file_start_rx_stream(void* h, bool now);

View File

@ -10,17 +10,19 @@
*
*/
#include <string.h>
#include "rf_dev.h"
#include "srsran/phy/rf/rf.h"
#include "srsran/phy/utils/debug.h"
#include <dlfcn.h>
#include <string.h>
int rf_get_available_devices(char** devnames, int max_strlen)
{
int i = 0;
while (available_devices[i]->name) {
strncpy(devnames[i], available_devices[i]->name, max_strlen);
while (rf_plugins[i] != NULL) {
if (rf_plugins[i]->rf_api != NULL) {
strncpy(devnames[i], rf_plugins[i]->rf_api->name, max_strlen);
}
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)
{
if (srsran_rf_load_plugins() != SRSRAN_SUCCESS) {
ERROR("Failed to load RF plugins");
return SRSRAN_ERROR;
}
rf->thread_gain_run = false;
bool no_rf_devs_detected = true;
printf("Available RF device list:");
for (unsigned int i = 0; available_devices[i]; i++) {
printf("Supported RF device list:");
for (unsigned int i = 0; rf_plugins[i] && rf_plugins[i]->rf_api; i++) {
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>" : "");
// Try to open the device if name is provided
if (devname && devname[0] != '\0') {
int i = 0;
while (available_devices[i] != NULL) {
if (!strcasecmp(available_devices[i]->name, devname)) {
rf->dev = available_devices[i];
return available_devices[i]->srsran_rf_open_multi(args, &rf->handler, nof_channels);
while (rf_plugins[i] != NULL) {
if (rf_plugins[i]->rf_api) {
if (!strcasecmp(rf_plugins[i]->rf_api->name, devname)) {
rf->dev = rf_plugins[i]->rf_api;
return rf_plugins[i]->rf_api->srsran_rf_open_multi(args, &rf->handler, nof_channels);
}
}
i++;
}
@ -120,16 +129,16 @@ int srsran_rf_open_devname(srsran_rf_t* rf, const char* devname, char* args, uin
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;
while (available_devices[i] != NULL) {
printf("Trying to open RF device '%s'\n", available_devices[i]->name);
if (!available_devices[i]->srsran_rf_open_multi(args, &rf->handler, nof_channels)) {
rf->dev = available_devices[i];
printf("RF device '%s' successfully opened\n", available_devices[i]->name);
while (rf_plugins[i] != NULL && rf_plugins[i]->rf_api != NULL) {
printf("Trying to open RF device '%s'\n", rf_plugins[i]->rf_api->name);
if (!rf_plugins[i]->rf_api->srsran_rf_open_multi(args, &rf->handler, nof_channels)) {
rf->dev = rf_plugins[i]->rf_api;
printf("RF device '%s' successfully opened\n", rf_plugins[i]->rf_api->name);
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++;
}
@ -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)
{
rf->dev = &dev_file;
rf->dev = &srsran_rf_dev_file;
// 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);
@ -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);
}
#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;
}

View File

@ -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 */

View File

@ -15,6 +15,7 @@
#include <sidekiq_api.h>
#include "rf_helper.h"
#include "rf_plugin.h"
#include "rf_skiq_imp.h"
#include "rf_skiq_imp_card.h"
@ -939,3 +940,43 @@ int rf_skiq_send_timed_multi(void* h_,
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 */

View File

@ -16,6 +16,8 @@
#include "srsran/config.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_multi(char* args, void** handler, uint32_t nof_rx_antennas);

View File

@ -16,6 +16,7 @@
#include <unistd.h>
#include "rf_helper.h"
#include "rf_plugin.h"
#include "rf_soapy_imp.h"
#include "srsran/phy/common/phy_common.h"
#include "srsran/phy/utils/debug.h"
@ -994,3 +995,44 @@ int rf_soapy_send_timed_multi(void* h,
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 */

View File

@ -20,6 +20,8 @@
#include <stdint.h>
#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_multi(char* args, void** handler, uint32_t num_requested_channels);

View File

@ -20,6 +20,7 @@
#include <uhd/usrp/multi_usrp.hpp>
#include "rf_helper.h"
#include "rf_plugin.h"
#include "srsran/phy/utils/debug.h"
#include "srsran/phy/utils/vector.h"
@ -1535,3 +1536,44 @@ int rf_uhd_send_timed_multi(void* h,
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 */

View File

@ -29,6 +29,8 @@ extern "C" {
#define DEVNAME_E3X0 "uhd_e3x0"
#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_multi(char* args, void** handler, uint32_t nof_channels);

View File

@ -12,6 +12,7 @@
#include "rf_zmq_imp.h"
#include "rf_helper.h"
#include "rf_plugin.h"
#include "rf_zmq_imp_trx.h"
#include <math.h>
#include <srsran/phy/common/phy_common.h>
@ -983,3 +984,44 @@ clean_exit:
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 */

View File

@ -21,6 +21,8 @@
#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_multi(char* args, void** handler, uint32_t nof_channels);

View File

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