diff --git a/CMakeLists.txt b/CMakeLists.txt index 018b3e9e2..7764f3c50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/lib/examples/CMakeLists.txt b/lib/examples/CMakeLists.txt index c6439be03..6d74b435c 100644 --- a/lib/examples/CMakeLists.txt +++ b/lib/examples/CMakeLists.txt @@ -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) ################################################################# diff --git a/lib/include/srsran/phy/rf/rf.h b/lib/include/srsran/phy/rf/rf.h index f21bfe717..ce8a12a5c 100644 --- a/lib/include/srsran/phy/rf/rf.h +++ b/lib/include/srsran/phy/rf/rf.h @@ -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); diff --git a/lib/src/phy/rf/CMakeLists.txt b/lib/src/phy/rf/CMakeLists.txt index 77d60bfff..3581d5ab0 100644 --- a/lib/src/phy/rf/CMakeLists.txt +++ b/lib/src/phy/rf/CMakeLists.txt @@ -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 $) - add_library(srsran_rf_shared SHARED $) + if (ENABLE_RF_PLUGINS) + add_dependencies(srsran_rf_object ${DYNAMIC_PLUGINS}) + add_library(srsran_rf SHARED $) + 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_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) diff --git a/lib/src/phy/rf/rf_blade_imp.c b/lib/src/phy/rf/rf_blade_imp.c index 888f8a421..d0c0dc815 100644 --- a/lib/src/phy/rf/rf_blade_imp.c +++ b/lib/src/phy/rf/rf_blade_imp.c @@ -15,6 +15,7 @@ #include #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 */ diff --git a/lib/src/phy/rf/rf_blade_imp.h b/lib/src/phy/rf/rf_blade_imp.h index f86e1e570..668892842 100644 --- a/lib/src/phy/rf/rf_blade_imp.h +++ b/lib/src/phy/rf/rf_blade_imp.h @@ -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_ */ diff --git a/lib/src/phy/rf/rf_dev.h b/lib/src/phy/rf/rf_dev.h index b31e9d65d..2e2a1c099 100644 --- a/lib/src/phy/rf/rf_dev.h +++ b/lib/src/phy/rf/rf_dev.h @@ -13,276 +13,58 @@ #include "srsran/phy/rf/rf.h" #include -/* 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}; diff --git a/lib/src/phy/rf/rf_file_imp.c b/lib/src/phy/rf/rf_file_imp.c index 16e98a5a8..f558af363 100644 --- a/lib/src/phy/rf/rf_file_imp.c +++ b/lib/src/phy/rf/rf_file_imp.c @@ -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}; diff --git a/lib/src/phy/rf/rf_file_imp.h b/lib/src/phy/rf/rf_file_imp.h index 5db7e697f..439ec6ec3 100644 --- a/lib/src/phy/rf/rf_file_imp.h +++ b/lib/src/phy/rf/rf_file_imp.h @@ -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); diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index 2b58e595e..30ff775f0 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -10,17 +10,19 @@ * */ -#include - #include "rf_dev.h" #include "srsran/phy/rf/rf.h" #include "srsran/phy/utils/debug.h" +#include +#include 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 ? " " : ""); // 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; +} diff --git a/lib/src/phy/rf/rf_plugin.h b/lib/src/phy/rf/rf_plugin.h new file mode 100644 index 000000000..6e0f83106 --- /dev/null +++ b/lib/src/phy/rf/rf_plugin.h @@ -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 */ diff --git a/lib/src/phy/rf/rf_skiq_imp.c b/lib/src/phy/rf/rf_skiq_imp.c index 483241496..55bd08651 100644 --- a/lib/src/phy/rf/rf_skiq_imp.c +++ b/lib/src/phy/rf/rf_skiq_imp.c @@ -15,6 +15,7 @@ #include #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 */ diff --git a/lib/src/phy/rf/rf_skiq_imp.h b/lib/src/phy/rf/rf_skiq_imp.h index 54a33dcbe..9d014b61b 100644 --- a/lib/src/phy/rf/rf_skiq_imp.h +++ b/lib/src/phy/rf/rf_skiq_imp.h @@ -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); diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index 8110126d3..cb0148081 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -16,6 +16,7 @@ #include #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 */ diff --git a/lib/src/phy/rf/rf_soapy_imp.h b/lib/src/phy/rf/rf_soapy_imp.h index ff7facf34..c9f7869a9 100644 --- a/lib/src/phy/rf/rf_soapy_imp.h +++ b/lib/src/phy/rf/rf_soapy_imp.h @@ -20,6 +20,8 @@ #include #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); diff --git a/lib/src/phy/rf/rf_uhd_imp.cc b/lib/src/phy/rf/rf_uhd_imp.cc index ac82113b1..d4bf609bc 100644 --- a/lib/src/phy/rf/rf_uhd_imp.cc +++ b/lib/src/phy/rf/rf_uhd_imp.cc @@ -20,6 +20,7 @@ #include #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 */ diff --git a/lib/src/phy/rf/rf_uhd_imp.h b/lib/src/phy/rf/rf_uhd_imp.h index c668c770e..6b961653a 100644 --- a/lib/src/phy/rf/rf_uhd_imp.h +++ b/lib/src/phy/rf/rf_uhd_imp.h @@ -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); diff --git a/lib/src/phy/rf/rf_zmq_imp.c b/lib/src/phy/rf/rf_zmq_imp.c index 0bc822667..048ec9f0d 100644 --- a/lib/src/phy/rf/rf_zmq_imp.c +++ b/lib/src/phy/rf/rf_zmq_imp.c @@ -12,6 +12,7 @@ #include "rf_zmq_imp.h" #include "rf_helper.h" +#include "rf_plugin.h" #include "rf_zmq_imp_trx.h" #include #include @@ -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 */ diff --git a/lib/src/phy/rf/rf_zmq_imp.h b/lib/src/phy/rf/rf_zmq_imp.h index df409a9c2..0f484bc5e 100644 --- a/lib/src/phy/rf/rf_zmq_imp.h +++ b/lib/src/phy/rf/rf_zmq_imp.h @@ -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); diff --git a/lib/src/phy/rf/rf_zmq_test.c b/lib/src/phy/rf/rf_zmq_test.c index 19c7c50c1..261acbf4f 100644 --- a/lib/src/phy/rf/rf_zmq_test.c +++ b/lib/src/phy/rf/rf_zmq_test.c @@ -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");