diff --git a/lib/bladerf/CMakeLists.txt b/lib/bladerf/CMakeLists.txt index 23f7e3f..922dbe1 100644 --- a/lib/bladerf/CMakeLists.txt +++ b/lib/bladerf/CMakeLists.txt @@ -37,4 +37,3 @@ set(bladerf_srcs ######################################################################## list(APPEND gr_osmosdr_srcs ${bladerf_srcs}) list(APPEND gr_osmosdr_libs ${LIBBLADERF_LIBRARIES}) - diff --git a/lib/bladerf/bladerf_common.cc b/lib/bladerf/bladerf_common.cc index 10884dd..4f919a1 100644 --- a/lib/bladerf/bladerf_common.cc +++ b/lib/bladerf/bladerf_common.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include "bladerf_common.h" @@ -43,6 +44,9 @@ using namespace boost::assign; +boost::mutex bladerf_common::_devs_mutex; +std::list > bladerf_common::_devs; + bladerf_common::bladerf_common() : _is_running(false) { @@ -80,6 +84,68 @@ bladerf_common::~bladerf_common() delete _fifo; } +bladerf_sptr bladerf_common:: get_cached_device(struct bladerf_devinfo devinfo) +{ + /* Lock to _devs must be aquired by caller */ + BOOST_FOREACH( boost::weak_ptr dev, _devs ) + { + struct bladerf_devinfo other_devinfo; + + int rv = bladerf_get_devinfo(bladerf_sptr(dev).get(), &other_devinfo); + if (rv < 0) + throw std::runtime_error(std::string(__FUNCTION__) + " " + + "Failed to get devinfo for cached device."); + + if (bladerf_devinfo_matches(&devinfo, &other_devinfo)) { + return bladerf_sptr(dev); + } + } + + return bladerf_sptr(); +} + +void bladerf_common::close(void* dev) +{ + boost::unique_lock lock(_devs_mutex); + + std::list >::iterator it; + for (it = _devs.begin(); it != _devs.end(); ++it) + if ( (*it).expired() == 0 ) + _devs.erase(it); + + bladerf_close((struct bladerf *)dev); +} + +bladerf_sptr bladerf_common::open(const std::string &device_name) +{ + int rv; + struct bladerf *raw_dev; + struct bladerf_devinfo devinfo; + + boost::unique_lock lock(_devs_mutex); + + rv = bladerf_get_devinfo_from_str(device_name.c_str(), &devinfo); + if (rv < 0) + throw std::runtime_error(std::string(__FUNCTION__) + " " + + "Failed to get devinfo for '" + device_name + "'"); + + bladerf_sptr cached_dev = get_cached_device(devinfo); + + if (cached_dev) + return cached_dev; + + rv = bladerf_open_with_devinfo(&raw_dev, &devinfo); + if (rv < 0) + throw std::runtime_error(std::string(__FUNCTION__) + " " + + "Failed to open device for '" + device_name + "'"); + + bladerf_sptr dev = bladerf_sptr(raw_dev, bladerf_common::close); + + _devs.push_back(boost::weak_ptr(dev)); + + return dev; +} + osmosdr::freq_range_t bladerf_common::freq_range() { /* assuming the same for RX & TX */ diff --git a/lib/bladerf/bladerf_common.h b/lib/bladerf/bladerf_common.h index ca95850..e5152f5 100644 --- a/lib/bladerf/bladerf_common.h +++ b/lib/bladerf/bladerf_common.h @@ -49,6 +49,8 @@ #define BLADERF_SAMPLE_FIFO_MIN_SIZE (3 * BLADERF_SAMPLE_BLOCK_SIZE) +typedef boost::shared_ptr bladerf_sptr; + class bladerf_common { public: @@ -56,6 +58,8 @@ public: virtual ~bladerf_common(); protected: + bladerf_sptr open(const std::string &device_name); + osmosdr::freq_range_t freq_range(); osmosdr::meta_range_t sample_rates(); osmosdr::freq_range_t filter_bandwidths(); @@ -65,7 +69,7 @@ protected: bool is_running(); void set_running(bool is_running); - bladerf *_dev; + bladerf_sptr _dev; void **_buffers; struct bladerf_stream *_stream; @@ -83,6 +87,12 @@ protected: private: bool _is_running; boost::shared_mutex _state_lock; + + static boost::mutex _devs_mutex; + static std::list > _devs; + + static bladerf_sptr get_cached_device(struct bladerf_devinfo devinfo); + static void close(void *dev); /* called by shared_ptr */ }; #endif diff --git a/lib/bladerf/bladerf_sink_c.cc b/lib/bladerf/bladerf_sink_c.cc index 9e57a84..14d7931 100644 --- a/lib/bladerf/bladerf_sink_c.cc +++ b/lib/bladerf/bladerf_sink_c.cc @@ -97,9 +97,9 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number); - /* Open a handle to the device */ - ret = bladerf_open( &_dev, device_name.c_str() ); - if ( ret != 0 ) { + try { + _dev = bladerf_common::open(device_name); + } catch(...) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "failed to open bladeRF device " + device_name ); } @@ -110,7 +110,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!" << std::endl; - ret = bladerf_flash_firmware( _dev, fw.c_str() ); + ret = bladerf_flash_firmware( _dev.get(), fw.c_str() ); if ( ret != 0 ) std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl; else @@ -122,7 +122,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) std::string fpga = dict["fpga"]; std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl; - ret = bladerf_load_fpga( _dev, fpga.c_str() ); + ret = bladerf_load_fpga( _dev.get(), fpga.c_str() ); if ( ret != 0 && ret != 1 ) std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl; else @@ -132,19 +132,19 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) std::cerr << "Using nuand LLC bladeRF #" << device_number; char serial[BLADERF_SERIAL_LENGTH]; - if ( bladerf_get_serial( _dev, serial ) == 0 ) + if ( bladerf_get_serial( _dev.get(), serial ) == 0 ) std::cerr << " SN " << serial; struct bladerf_version ver; - if ( bladerf_fw_version( _dev, &ver ) == 0 ) + if ( bladerf_fw_version( _dev.get(), &ver ) == 0 ) std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch; - if ( bladerf_fpga_version( _dev, &ver ) == 0 ) + if ( bladerf_fpga_version( _dev.get(), &ver ) == 0 ) std::cerr << " FPGA v" << ver.major << "." << ver.minor << "." << ver.patch; std::cerr << std::endl; - if ( bladerf_is_fpga_configured( _dev ) != 1 ) + if ( bladerf_is_fpga_configured( _dev.get() ) != 1 ) { std::ostringstream oss; oss << "The FPGA is not configured! " @@ -199,7 +199,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) } /* Initialize the stream */ - ret = bladerf_init_stream( &_stream, _dev, stream_callback, + ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback, &_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12, _samples_per_buffer, transfers, this ); if ( ret != 0 ) @@ -220,7 +220,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) _filled[i] = false; } - ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, true ); + ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, true ); if ( ret != 0 ) std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; @@ -245,16 +245,13 @@ bladerf_sink_c::~bladerf_sink_c () _thread.join(); - ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, false ); + ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, false ); if ( ret != 0 ) std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; /* Release stream resources */ bladerf_deinit_stream(_stream); - /* Close the device */ - bladerf_close( _dev ); - delete[] _filled; } @@ -406,7 +403,7 @@ double bladerf_sink_c::set_sample_rate(double rate) /* Check to see if the sample rate is an integer */ if( (uint32_t)round(rate) == (uint32_t)rate ) { - ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual ); + ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_TX, (uint32_t)rate, &actual ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "has failed to set integer rate, error " + @@ -414,7 +411,7 @@ double bladerf_sink_c::set_sample_rate(double rate) } } else { /* TODO: Fractional sample rate */ - ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual ); + ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_TX, (uint32_t)rate, &actual ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "has failed to set fractional rate, error " + @@ -430,7 +427,7 @@ double bladerf_sink_c::get_sample_rate() int ret; unsigned int rate = 0; - ret = bladerf_get_sample_rate( _dev, BLADERF_MODULE_TX, &rate ); + ret = bladerf_get_sample_rate( _dev.get(), BLADERF_MODULE_TX, &rate ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "has failed to get sample rate, error " + @@ -454,7 +451,7 @@ double bladerf_sink_c::set_center_freq( double freq, size_t chan ) freq > get_freq_range( chan ).stop() ) { std::cerr << "Failed to set out of bound frequency: " << freq << std::endl; } else { - ret = bladerf_set_frequency( _dev, BLADERF_MODULE_TX, (uint32_t)freq ); + ret = bladerf_set_frequency( _dev.get(), BLADERF_MODULE_TX, (uint32_t)freq ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "failed to set center frequency " + @@ -472,7 +469,7 @@ double bladerf_sink_c::get_center_freq( size_t chan ) uint32_t freq; int ret; - ret = bladerf_get_frequency( _dev, BLADERF_MODULE_TX, &freq ); + ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_TX, &freq ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "failed to get center frequency, error " + @@ -546,9 +543,9 @@ double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t c int ret = 0; if( name == "VGA1" ) { - ret = bladerf_set_txvga1( _dev, (int)gain ); + ret = bladerf_set_txvga1( _dev.get(), (int)gain ); } else if( name == "VGA2" ) { - ret = bladerf_set_txvga2( _dev, (int)gain ); + ret = bladerf_set_txvga2( _dev.get(), (int)gain ); } else { throw std::runtime_error( std::string(__FUNCTION__) + " " + "requested to set the gain " @@ -576,9 +573,9 @@ double bladerf_sink_c::get_gain( const std::string & name, size_t chan ) int ret = 0; if( name == "VGA1" ) { - ret = bladerf_get_txvga1( _dev, &g ); + ret = bladerf_get_txvga1( _dev.get(), &g ); } else if( name == "VGA2" ) { - ret = bladerf_get_txvga2( _dev, &g ); + ret = bladerf_get_txvga2( _dev.get(), &g ); } else { throw std::runtime_error( std::string(__FUNCTION__) + " " + "requested to get the gain " @@ -634,7 +631,7 @@ double bladerf_sink_c::set_bandwidth( double bandwidth, size_t chan ) if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */ bandwidth = get_sample_rate() * 0.75; /* select narrower filters to prevent aliasing */ - ret = bladerf_set_bandwidth( _dev, BLADERF_MODULE_TX, (uint32_t)bandwidth, &actual ); + ret = bladerf_set_bandwidth( _dev.get(), BLADERF_MODULE_TX, (uint32_t)bandwidth, &actual ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "could not set bandwidth, error " + @@ -649,7 +646,7 @@ double bladerf_sink_c::get_bandwidth( size_t chan ) uint32_t bandwidth; int ret; - ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_TX, &bandwidth ); + ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_TX, &bandwidth ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "could not get bandwidth, error " + diff --git a/lib/bladerf/bladerf_source_c.cc b/lib/bladerf/bladerf_source_c.cc index e0f84b0..31b41fb 100644 --- a/lib/bladerf/bladerf_source_c.cc +++ b/lib/bladerf/bladerf_source_c.cc @@ -94,9 +94,9 @@ bladerf_source_c::bladerf_source_c (const std::string &args) device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number); - /* Open a handle to the device */ - ret = bladerf_open( &_dev, device_name.c_str() ); - if ( ret != 0 ) { + try { + _dev = bladerf_common::open(device_name); + } catch(...) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "failed to open bladeRF device " + device_name ); } @@ -107,7 +107,7 @@ bladerf_source_c::bladerf_source_c (const std::string &args) std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!" << std::endl; - ret = bladerf_flash_firmware( _dev, fw.c_str() ); + ret = bladerf_flash_firmware( _dev.get(), fw.c_str() ); if ( ret != 0 ) std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl; else @@ -119,7 +119,7 @@ bladerf_source_c::bladerf_source_c (const std::string &args) std::string fpga = dict["fpga"]; std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl; - ret = bladerf_load_fpga( _dev, fpga.c_str() ); + ret = bladerf_load_fpga( _dev.get(), fpga.c_str() ); if ( ret != 0 && ret != 1 ) std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl; else @@ -129,19 +129,19 @@ bladerf_source_c::bladerf_source_c (const std::string &args) std::cerr << "Using nuand LLC bladeRF #" << device_number; char serial[BLADERF_SERIAL_LENGTH]; - if ( bladerf_get_serial( _dev, serial ) == 0 ) + if ( bladerf_get_serial( _dev.get(), serial ) == 0 ) std::cerr << " SN " << serial; struct bladerf_version ver; - if ( bladerf_fw_version( _dev, &ver ) == 0 ) + if ( bladerf_fw_version( _dev.get(), &ver ) == 0 ) std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch; - if ( bladerf_fpga_version( _dev, &ver ) == 0 ) + if ( bladerf_fpga_version( _dev.get(), &ver ) == 0 ) std::cerr << " FPGA v" << ver.major << "." << ver.minor << "." << ver.patch; std::cerr << std::endl; - if ( bladerf_is_fpga_configured( _dev ) != 1 ) + if ( bladerf_is_fpga_configured( _dev.get() ) != 1 ) { std::ostringstream oss; oss << "The FPGA is not configured! " @@ -156,11 +156,11 @@ bladerf_source_c::bladerf_source_c (const std::string &args) std::cerr << "Setting bladerf sampling to " << sampling << std::endl; if( sampling == "internal") { - ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_INTERNAL ); + ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_INTERNAL ); if ( ret != 0 ) std::cerr << "Problem while setting sampling mode " << ret << std::endl; } else if( sampling == "external" ) { - ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_EXTERNAL ); + ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_EXTERNAL ); if ( ret != 0 ) std::cerr << "Problem while setting sampling mode " << ret << std::endl; } else { @@ -182,13 +182,13 @@ bladerf_source_c::bladerf_source_c (const std::string &args) const size_t samp_per_buf = 1024 * 10; /* TODO: make it an argument */ /* Initialize the stream */ - ret = bladerf_init_stream( &_stream, _dev, stream_callback, + ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback, &_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12, samp_per_buf, _num_buffers, this ); if ( ret != 0 ) std::cerr << "bladerf_init_stream has failed with " << ret << std::endl; - ret = bladerf_enable_module( _dev, BLADERF_MODULE_RX, true ); + ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, true ); if ( ret != 0 ) std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; @@ -205,15 +205,12 @@ bladerf_source_c::~bladerf_source_c () set_running(false); _thread.join(); - ret = bladerf_enable_module( _dev, BLADERF_MODULE_RX, false ); + ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, false ); if ( ret != 0 ) std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; /* Release stream resources */ bladerf_deinit_stream(_stream); - - /* Close the device */ - bladerf_close( _dev ); } void *bladerf_source_c::stream_callback( struct bladerf *dev, @@ -350,7 +347,7 @@ double bladerf_source_c::set_sample_rate( double rate ) /* Check to see if the sample rate is an integer */ if( (uint32_t)round(rate) == (uint32_t)rate ) { - ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual ); + ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_RX, (uint32_t)rate, &actual ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "has failed to set integer rate, error " + @@ -358,7 +355,7 @@ double bladerf_source_c::set_sample_rate( double rate ) } } else { /* TODO: Fractional sample rate */ - ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual ); + ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_RX, (uint32_t)rate, &actual ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "has failed to set fractional rate, error " + @@ -374,7 +371,7 @@ double bladerf_source_c::get_sample_rate() int ret; unsigned int rate = 0; - ret = bladerf_get_sample_rate( _dev, BLADERF_MODULE_RX, &rate ); + ret = bladerf_get_sample_rate( _dev.get(), BLADERF_MODULE_RX, &rate ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "has failed to get sample rate, error " + @@ -398,7 +395,7 @@ double bladerf_source_c::set_center_freq( double freq, size_t chan ) freq > get_freq_range( chan ).stop() ) { std::cerr << "Failed to set out of bound frequency: " << freq << std::endl; } else { - ret = bladerf_set_frequency( _dev, BLADERF_MODULE_RX, (uint32_t)freq ); + ret = bladerf_set_frequency( _dev.get(), BLADERF_MODULE_RX, (uint32_t)freq ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "failed to set center frequency " + @@ -416,7 +413,7 @@ double bladerf_source_c::get_center_freq( size_t chan ) uint32_t freq; int ret; - ret = bladerf_get_frequency( _dev, BLADERF_MODULE_RX, &freq ); + ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_RX, &freq ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "failed to get center frequency, error " + @@ -504,11 +501,11 @@ double bladerf_source_c::set_gain( double gain, const std::string & name, size_t else /* gain < 3.0f */ g = BLADERF_LNA_GAIN_BYPASS; - ret = bladerf_set_lna_gain( _dev, g ); + ret = bladerf_set_lna_gain( _dev.get(), g ); } else if( name == "VGA1" ) { - ret = bladerf_set_rxvga1( _dev, (int)gain ); + ret = bladerf_set_rxvga1( _dev.get(), (int)gain ); } else if( name == "VGA2" ) { - ret = bladerf_set_rxvga2( _dev, (int)gain ); + ret = bladerf_set_rxvga2( _dev.get(), (int)gain ); } else { throw std::runtime_error( std::string(__FUNCTION__) + " " + "requested to set the gain " @@ -538,12 +535,12 @@ double bladerf_source_c::get_gain( const std::string & name, size_t chan ) if( name == "LNA" ) { bladerf_lna_gain lna_g; - ret = bladerf_get_lna_gain( _dev, &lna_g ); + ret = bladerf_get_lna_gain( _dev.get(), &lna_g ); g = lna_g == BLADERF_LNA_GAIN_BYPASS ? 0 : lna_g == BLADERF_LNA_GAIN_MID ? 3 : 6; } else if( name == "VGA1" ) { - ret = bladerf_get_rxvga1( _dev, &g ); + ret = bladerf_get_rxvga1( _dev.get(), &g ); } else if( name == "VGA2" ) { - ret = bladerf_get_rxvga2( _dev, &g ); + ret = bladerf_get_rxvga2( _dev.get(), &g ); } else { throw std::runtime_error( std::string(__FUNCTION__) + " " + "requested to get the gain " @@ -599,7 +596,7 @@ double bladerf_source_c::set_bandwidth( double bandwidth, size_t chan ) if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */ bandwidth = get_sample_rate() * 0.75; /* select narrower filters to prevent aliasing */ - ret = bladerf_set_bandwidth( _dev, BLADERF_MODULE_RX, (uint32_t)bandwidth, &actual ); + ret = bladerf_set_bandwidth( _dev.get(), BLADERF_MODULE_RX, (uint32_t)bandwidth, &actual ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "could not set bandwidth, error " + @@ -614,7 +611,7 @@ double bladerf_source_c::get_bandwidth( size_t chan ) uint32_t bandwidth; int ret; - ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_RX, &bandwidth ); + ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_RX, &bandwidth ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "could not get bandwidth, error " +