summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Solano Gómez <gentoo@sattvik.com>2019-10-18 22:19:40 -0500
committerDaniel Solano Gómez <gentoo@sattvik.com>2019-10-18 22:19:40 -0500
commitc63f28c0ed67aa0bdd9f9fb309e6e48e2ee80b24 (patch)
tree745f32ab7f64442f88f4b19ffdca10306ad9ca20 /net-wireless
parentAdd net-wireless/airspyhf (diff)
downloadsattvik-c63f28c0ed67aa0bdd9f9fb309e6e48e2ee80b24.tar.gz
sattvik-c63f28c0ed67aa0bdd9f9fb309e6e48e2ee80b24.tar.bz2
sattvik-c63f28c0ed67aa0bdd9f9fb309e6e48e2ee80b24.zip
Add airspyhf support to gr-osmosdr
Signed-off-by: Daniel Solano <gentoo@sattvik.com>
Diffstat (limited to 'net-wireless')
-rw-r--r--net-wireless/gr-osmosdr/Manifest4
-rw-r--r--net-wireless/gr-osmosdr/files/airspyhf.patch781
-rw-r--r--net-wireless/gr-osmosdr/gr-osmosdr-0.1.4_p20180626-r4.ebuild80
-rw-r--r--net-wireless/gr-osmosdr/metadata.xml20
4 files changed, 885 insertions, 0 deletions
diff --git a/net-wireless/gr-osmosdr/Manifest b/net-wireless/gr-osmosdr/Manifest
new file mode 100644
index 0000000..3927394
--- /dev/null
+++ b/net-wireless/gr-osmosdr/Manifest
@@ -0,0 +1,4 @@
+AUX airspyhf.patch 22601 BLAKE2B 42b8f24e24845fc4b90854d0c41521da7289335f9aba10ebc1da42d432a6f2c21669d34b7cc11adf03f57b9f21879b9817a8f67628c4e5e2d80f379aab659b07 SHA512 7717debe00c812b357c14a0ae2c464cd18f5953f5e428afa2f754f38b16cdf18435e082b7aacb265ed69f68ae419fc316b70cc65ea32411493ecf2a441b5fa7b
+DIST gr-osmosdr-0.1.4_p20180626.tar.xz 179568 BLAKE2B 223d23bd17edd5f4ee78237e509c79e5e7e49bbfb516009c3b5a715f386fcd138beea48e417d4576a7749cdb440736b6d92c8766b614bf617ef6b2bb4a293fda SHA512 8540da1f4d6936e0a97fa2f3e24af1866d44620fd7e7bc65b323364f67f1527fe8e0efd7bf0349be5e3d61f2ed24fa736c924ea0038e44fa3ab72848fe254a28
+EBUILD gr-osmosdr-0.1.4_p20180626-r4.ebuild 2248 BLAKE2B d76075f86a0426f9385a8d49a8999a56c7af9342b778bd97cdc7adf35dc42f9e3b2c9f39708b5c6f5d63843fd74957d676ff46abb571a00c2a3587560a8f13c2 SHA512 ba16d6331fa2465dffbab4d762fb6f7aef7d2d0d0d0add754b252f61365c3a55a91739033cd5ed226d804592e0452b2b686c72731c4aa2cb12f93b7a57aac639
+MISC metadata.xml 1010 BLAKE2B e4f3fbd3eb67c98876fb8df6db5d809011a8cf120134cb34ed63254b328e15914e696c80c848313c296c43cca71d0c61feb6788effacce30862d982ff6cf8975 SHA512 7144c3e40a28dc0e684f236ec7c70269a7734b3ca55df89f159e803904a43883563b8efb3b1bbc8f3f6eb96bf1c18040df4b1528f5bf1a674f8e8d875dbd69d3
diff --git a/net-wireless/gr-osmosdr/files/airspyhf.patch b/net-wireless/gr-osmosdr/files/airspyhf.patch
new file mode 100644
index 0000000..1f90c2c
--- /dev/null
+++ b/net-wireless/gr-osmosdr/files/airspyhf.patch
@@ -0,0 +1,781 @@
+From 5e1a58f7900a4af26c5d2863bdabafaabccc4673 Mon Sep 17 00:00:00 2001
+From: Alexandru Csete <oz9aec@gmail.com>
+Date: Sun, 16 Jul 2017 00:04:10 +0200
+Subject: [PATCH] airspyhf: Add initial support for Airspy HF+
+
+Info: http://airspy.com/airspy-hf-plus/
+---
+ CMakeLists.txt | 1 +
+ cmake/Modules/FindLibAIRSPYHF.cmake | 24 ++
+ lib/CMakeLists.txt | 8 +
+ lib/airspyhf/CMakeLists.txt | 37 +++
+ lib/airspyhf/airspyhf_source_c.cc | 438 ++++++++++++++++++++++++++++
+ lib/airspyhf/airspyhf_source_c.h | 117 ++++++++
+ lib/config.h.in | 1 +
+ lib/device.cc | 8 +
+ lib/source_impl.cc | 18 ++
+ 9 files changed, 652 insertions(+)
+ create mode 100644 cmake/Modules/FindLibAIRSPYHF.cmake
+ create mode 100644 lib/airspyhf/CMakeLists.txt
+ create mode 100644 lib/airspyhf/airspyhf_source_c.cc
+ create mode 100644 lib/airspyhf/airspyhf_source_c.h
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index af21291..3602ba1 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -169,6 +169,7 @@ find_package(LibSDRplay)
+ endif(ENABLE_NONFREE)
+ find_package(LibHackRF)
+ find_package(LibAIRSPY)
++find_package(LibAIRSPYHF)
+ find_package(Volk)
+ find_package(LibbladeRF)
+ find_package(SoapySDR NO_MODULE)
+diff --git a/cmake/Modules/FindLibAIRSPYHF.cmake b/cmake/Modules/FindLibAIRSPYHF.cmake
+new file mode 100644
+index 0000000..edb0dda
+--- /dev/null
++++ b/cmake/Modules/FindLibAIRSPYHF.cmake
+@@ -0,0 +1,24 @@
++INCLUDE(FindPkgConfig)
++PKG_CHECK_MODULES(PC_LIBAIRSPYHF libairspyhf)
++
++FIND_PATH(
++ LIBAIRSPYHF_INCLUDE_DIRS
++ NAMES libairspyhf/airspyhf.h
++ HINTS $ENV{LIBAIRSPYHF_DIR}/include
++ ${PC_LIBAIRSPYHF_INCLUDEDIR}
++ PATHS /usr/local/include
++ /usr/include
++)
++
++FIND_LIBRARY(
++ LIBAIRSPYHF_LIBRARIES
++ NAMES airspyhf
++ HINTS $ENV{LIBAIRSPYHF_DIR}/lib
++ ${PC_LIBAIRSPYHF_LIBDIR}
++ PATHS /usr/local/lib
++ /usr/lib
++)
++
++INCLUDE(FindPackageHandleStandardArgs)
++FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBAIRSPYHF DEFAULT_MSG LIBAIRSPYHF_LIBRARIES LIBAIRSPYHF_INCLUDE_DIRS)
++MARK_AS_ADVANCED(LIBAIRSPYHF_LIBRARIES LIBAIRSPYHF_INCLUDE_DIRS)
+diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
+index dbb175a..0889ea5 100644
+--- a/lib/CMakeLists.txt
++++ b/lib/CMakeLists.txt
+@@ -230,6 +230,14 @@ if(ENABLE_AIRSPY)
+ GR_INCLUDE_SUBDIRECTORY(airspy)
+ endif(ENABLE_AIRSPY)
+
++########################################################################
++# Setup AIRSPYHF component
++########################################################################
++GR_REGISTER_COMPONENT("AIRSPY HF+ Receiver" ENABLE_AIRSPYHF LIBAIRSPYHF_FOUND)
++if(ENABLE_AIRSPYHF)
++GR_INCLUDE_SUBDIRECTORY(airspyhf)
++endif(ENABLE_AIRSPYHF)
++
+ ########################################################################
+ # Setup SoapySDR component
+ ########################################################################
+diff --git a/lib/airspyhf/CMakeLists.txt b/lib/airspyhf/CMakeLists.txt
+new file mode 100644
+index 0000000..6b29f37
+--- /dev/null
++++ b/lib/airspyhf/CMakeLists.txt
+@@ -0,0 +1,37 @@
++# Copyright 2017 Free Software Foundation, Inc.
++#
++# This file is part of GNU Radio
++#
++# GNU Radio is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3, or (at your option)
++# any later version.
++#
++# GNU Radio is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with GNU Radio; see the file COPYING. If not, write to
++# the Free Software Foundation, Inc., 51 Franklin Street,
++# Boston, MA 02110-1301, USA.
++
++########################################################################
++# This file included, use CMake directory variables
++########################################################################
++
++include_directories(
++ ${CMAKE_CURRENT_SOURCE_DIR}
++ ${LIBAIRSPYHF_INCLUDE_DIRS}
++)
++
++set(airspyhf_srcs
++ ${CMAKE_CURRENT_SOURCE_DIR}/airspyhf_source_c.cc
++)
++
++########################################################################
++# Append gnuradio-osmosdr library sources
++########################################################################
++list(APPEND gr_osmosdr_srcs ${airspyhf_srcs})
++list(APPEND gr_osmosdr_libs ${LIBAIRSPYHF_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES})
+diff --git a/lib/airspyhf/airspyhf_source_c.cc b/lib/airspyhf/airspyhf_source_c.cc
+new file mode 100644
+index 0000000..f4b3533
+--- /dev/null
++++ b/lib/airspyhf/airspyhf_source_c.cc
+@@ -0,0 +1,438 @@
++/* -*- c++ -*- */
++/*
++ * Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
++ *
++ * GNU Radio is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3, or (at your option)
++ * any later version.
++ *
++ * GNU Radio is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GNU Radio; see the file COPYING. If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street,
++ * Boston, MA 02110-1301, USA.
++ */
++
++/*
++ * config.h is generated by configure. It contains the results
++ * of probing for features, options etc. It should be the first
++ * file included in your .cc file.
++ */
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <stdexcept>
++#include <iostream>
++#include <algorithm>
++
++#include <boost/assign.hpp>
++#include <boost/format.hpp>
++#include <boost/detail/endian.hpp>
++#include <boost/algorithm/string.hpp>
++#include <boost/thread/thread.hpp>
++
++#include <gnuradio/io_signature.h>
++
++#include "airspyhf_source_c.h"
++#include "arg_helpers.h"
++
++using namespace boost::assign;
++
++#define AIRSPYHF_FORMAT_ERROR(ret, msg) \
++ boost::str( boost::format(msg " (%1%)") % ret )
++
++#define AIRSPYHF_THROW_ON_ERROR(ret, msg) \
++ if ( ret != AIRSPYHF_SUCCESS ) \
++ { \
++ throw std::runtime_error( AIRSPYHF_FORMAT_ERROR(ret, msg) ); \
++ }
++
++#define AIRSPYHF_FUNC_STR(func, arg) \
++ boost::str(boost::format(func "(%1%)") % arg) + " has failed"
++
++airspyhf_source_c_sptr make_airspyhf_source_c (const std::string & args)
++{
++ return gnuradio::get_initial_sptr(new airspyhf_source_c (args));
++}
++
++/*
++ * Specify constraints on number of input and output streams.
++ * This info is used to construct the input and output signatures
++ * (2nd & 3rd args to gr::block's constructor). The input and
++ * output signatures are used by the runtime system to
++ * check that a valid number and type of inputs and outputs
++ * are connected to this block. In this case, we accept
++ * only 0 input and 1 output.
++ */
++static const int MIN_IN = 0; // mininum number of input streams
++static const int MAX_IN = 0; // maximum number of input streams
++static const int MIN_OUT = 1; // minimum number of output streams
++static const int MAX_OUT = 1; // maximum number of output streams
++
++/*
++ * The private constructor
++ */
++airspyhf_source_c::airspyhf_source_c (const std::string &args)
++ : gr::sync_block ("airspyhf_source_c",
++ gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
++ gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
++ _dev(NULL),
++ _sample_rate(0),
++ _center_freq(0),
++ _freq_corr(0)
++{
++ int ret;
++
++ dict_t dict = params_to_dict(args);
++
++ _dev = NULL;
++ ret = airspyhf_open( &_dev );
++ AIRSPYHF_THROW_ON_ERROR(ret, "Failed to open Airspy HF+ device")
++
++ uint32_t num_rates;
++ airspyhf_get_samplerates(_dev, &num_rates, 0);
++ uint32_t *samplerates = (uint32_t *) malloc(num_rates * sizeof(uint32_t));
++ airspyhf_get_samplerates(_dev, samplerates, num_rates);
++ for (size_t i = 0; i < num_rates; i++)
++ _sample_rates.push_back( std::pair<double, uint32_t>( samplerates[i], i ) );
++ free(samplerates);
++
++ /* since they may (and will) give us an unsorted array we have to sort it here
++ * to play nice with the monotonic requirement of meta-range later on */
++ std::sort(_sample_rates.begin(), _sample_rates.end());
++
++ std::cerr << "Using libairspyhf" << AIRSPYHF_VERSION << ", samplerates: ";
++
++ for (size_t i = 0; i < _sample_rates.size(); i++)
++ std::cerr << boost::format("%gM ") % (_sample_rates[i].first / 1e6);
++
++ std::cerr << std::endl;
++
++ set_center_freq( (get_freq_range().start() + get_freq_range().stop()) / 2.0 );
++ set_sample_rate( get_sample_rates().start() );
++
++ _fifo = new boost::circular_buffer<gr_complex>(5000000);
++ if (!_fifo) {
++ throw std::runtime_error( std::string(__FUNCTION__) + " " +
++ "Failed to allocate a sample FIFO!" );
++ }
++}
++
++/*
++ * Our virtual destructor.
++ */
++airspyhf_source_c::~airspyhf_source_c ()
++{
++ int ret;
++
++ if (_dev) {
++ if ( airspyhf_is_streaming( _dev ) )
++ {
++ ret = airspyhf_stop( _dev );
++ if ( ret != AIRSPYHF_SUCCESS )
++ {
++ std::cerr << AIRSPYHF_FORMAT_ERROR(ret, "Failed to stop RX streaming") << std::endl;
++ }
++ }
++
++ ret = airspyhf_close( _dev );
++ if ( ret != AIRSPYHF_SUCCESS )
++ {
++ std::cerr << AIRSPYHF_FORMAT_ERROR(ret, "Failed to close AirSpy") << std::endl;
++ }
++ _dev = NULL;
++ }
++
++ if (_fifo)
++ {
++ delete _fifo;
++ _fifo = NULL;
++ }
++}
++
++int airspyhf_source_c::_airspyhf_rx_callback(airspyhf_transfer_t *transfer)
++{
++ airspyhf_source_c *obj = (airspyhf_source_c *)transfer->ctx;
++
++ return obj->airspyhf_rx_callback((float *)transfer->samples, transfer->sample_count);
++}
++
++int airspyhf_source_c::airspyhf_rx_callback(void *samples, int sample_count)
++{
++ size_t i, n_avail, to_copy, num_samples = sample_count;
++ float *sample = (float *)samples;
++
++ _fifo_lock.lock();
++
++ n_avail = _fifo->capacity() - _fifo->size();
++ to_copy = (n_avail < num_samples ? n_avail : num_samples);
++
++ for (i = 0; i < to_copy; i++ )
++ {
++ /* Push sample to the fifo */
++ _fifo->push_back( gr_complex( *sample, *(sample+1) ) );
++
++ /* offset to the next I+Q sample */
++ sample += 2;
++ }
++
++ _fifo_lock.unlock();
++
++ /* We have made some new samples available to the consumer in work() */
++ if (to_copy) {
++ //std::cerr << "+" << std::flush;
++ _samp_avail.notify_one();
++ }
++
++ /* Indicate overrun, if neccesary */
++ if (to_copy < num_samples)
++ std::cerr << "O" << std::flush;
++
++ return 0; // TODO: return -1 on error/stop
++}
++
++bool airspyhf_source_c::start()
++{
++ if ( ! _dev )
++ return false;
++
++ int ret = airspyhf_start( _dev, _airspyhf_rx_callback, (void *)this );
++ if ( ret != AIRSPYHF_SUCCESS ) {
++ std::cerr << "Failed to start RX streaming (" << ret << ")" << std::endl;
++ return false;
++ }
++
++ return true;
++}
++
++bool airspyhf_source_c::stop()
++{
++ if ( ! _dev )
++ return false;
++
++ int ret = airspyhf_stop( _dev );
++ if ( ret != AIRSPYHF_SUCCESS ) {
++ std::cerr << "Failed to stop RX streaming (" << ret << ")" << std::endl;
++ return false;
++ }
++
++ return true;
++}
++
++int airspyhf_source_c::work( int noutput_items,
++ gr_vector_const_void_star &input_items,
++ gr_vector_void_star &output_items )
++{
++ gr_complex *out = (gr_complex *)output_items[0];
++
++ bool running = false;
++
++ if ( _dev )
++ running = airspyhf_is_streaming( _dev );
++
++ if ( ! running )
++ return WORK_DONE;
++
++ boost::unique_lock<boost::mutex> lock(_fifo_lock);
++
++ /* Wait until we have the requested number of samples */
++ int n_samples_avail = _fifo->size();
++
++ while (n_samples_avail < noutput_items) {
++ _samp_avail.wait(lock);
++ n_samples_avail = _fifo->size();
++ }
++
++ for(int i = 0; i < noutput_items; ++i) {
++ out[i] = _fifo->at(0);
++ _fifo->pop_front();
++ }
++
++ return noutput_items;
++}
++
++std::vector<std::string> airspyhf_source_c::get_devices()
++{
++ std::vector<std::string> devices;
++ std::string label;
++
++ int ret;
++ airspyhf_device *dev = NULL;
++ ret = airspyhf_open(&dev);
++ if ( AIRSPYHF_SUCCESS == ret )
++ {
++ std::string args = "airspyhf=0,label='AirspyHF'";
++ devices.push_back( args );
++ ret = airspyhf_close(dev);
++ }
++
++ return devices;
++}
++
++size_t airspyhf_source_c::get_num_channels()
++{
++ return 1;
++}
++
++osmosdr::meta_range_t airspyhf_source_c::get_sample_rates()
++{
++ osmosdr::meta_range_t range;
++
++ for (size_t i = 0; i < _sample_rates.size(); i++)
++ range += osmosdr::range_t( _sample_rates[i].first );
++
++ return range;
++}
++
++double airspyhf_source_c::set_sample_rate( double rate )
++{
++ int ret = AIRSPYHF_SUCCESS;
++
++ if (_dev) {
++ bool found_supported_rate = false;
++ uint32_t samp_rate_index = 0;
++
++ for( unsigned int i = 0; i < _sample_rates.size(); i++ )
++ {
++ if( _sample_rates[i].first == rate )
++ {
++ samp_rate_index = _sample_rates[i].second;
++
++ found_supported_rate = true;
++ }
++ }
++
++ if ( ! found_supported_rate )
++ {
++ throw std::runtime_error(
++ boost::str( boost::format("Unsupported samplerate: %gM") % (rate/1e6) ) );
++ }
++
++ ret = airspyhf_set_samplerate( _dev, samp_rate_index );
++ if ( AIRSPYHF_SUCCESS == ret ) {
++ _sample_rate = rate;
++ } else {
++ AIRSPYHF_THROW_ON_ERROR( ret, AIRSPYHF_FUNC_STR( "airspyhf_set_samplerate", rate ) )
++ }
++ }
++
++ return get_sample_rate();
++}
++
++double airspyhf_source_c::get_sample_rate()
++{
++ return _sample_rate;
++}
++
++osmosdr::freq_range_t airspyhf_source_c::get_freq_range( size_t chan )
++{
++ osmosdr::freq_range_t range;
++
++ range += osmosdr::range_t( 0.0, 260.0e6 );
++
++ return range;
++}
++
++double airspyhf_source_c::set_center_freq( double freq, size_t chan )
++{
++ int ret;
++
++ if (_dev) {
++ ret = airspyhf_set_freq( _dev, freq );
++ if ( AIRSPYHF_SUCCESS == ret ) {
++ _center_freq = freq;
++ } else {
++ AIRSPYHF_THROW_ON_ERROR( ret, AIRSPYHF_FUNC_STR( "airspyhf_set_freq", freq ) )
++ }
++ }
++
++ return get_center_freq( chan );
++}
++
++double airspyhf_source_c::get_center_freq( size_t chan )
++{
++ return _center_freq;
++}
++
++double airspyhf_source_c::set_freq_corr( double ppm, size_t chan )
++{
++ int ret;
++ int32_t ppb = (int32_t) (ppm * 1.0e3);
++
++ if (_dev) {
++ ret = airspyhf_set_calibration( _dev, ppb );
++ if ( AIRSPYHF_SUCCESS == ret ) {
++ _freq_corr = ppm;
++ } else {
++ AIRSPYHF_THROW_ON_ERROR( ret, AIRSPYHF_FUNC_STR( "airspyhf_set_calibration", ppm ) )
++ }
++ }
++
++ return ppm;
++}
++
++double airspyhf_source_c::get_freq_corr( size_t chan )
++{
++ return _freq_corr;
++}
++
++std::vector<std::string> airspyhf_source_c::get_gain_names( size_t chan )
++{
++ return std::vector<std::string>();
++}
++
++osmosdr::gain_range_t airspyhf_source_c::get_gain_range( size_t chan )
++{
++ return osmosdr::gain_range_t();
++}
++
++osmosdr::gain_range_t airspyhf_source_c::get_gain_range( const std::string & name, size_t chan )
++{
++ return osmosdr::gain_range_t();
++}
++
++
++double airspyhf_source_c::set_gain( double gain, size_t chan )
++{
++ return gain;
++}
++
++double airspyhf_source_c::set_gain( double gain, const std::string & name, size_t chan)
++{
++ return gain;
++}
++
++double airspyhf_source_c::get_gain( size_t chan )
++{
++ return 0.0;
++}
++
++double airspyhf_source_c::get_gain( const std::string & name, size_t chan )
++{
++ return 0.0;
++}
++
++std::vector< std::string > airspyhf_source_c::get_antennas( size_t chan )
++{
++ std::vector< std::string > antennas;
++
++ antennas += get_antenna( chan );
++
++ return antennas;
++}
++
++std::string airspyhf_source_c::set_antenna( const std::string & antenna, size_t chan )
++{
++ return get_antenna( chan );
++}
++
++std::string airspyhf_source_c::get_antenna( size_t chan )
++{
++ return "RX";
++}
+diff --git a/lib/airspyhf/airspyhf_source_c.h b/lib/airspyhf/airspyhf_source_c.h
+new file mode 100644
+index 0000000..cfb8c89
+--- /dev/null
++++ b/lib/airspyhf/airspyhf_source_c.h
+@@ -0,0 +1,117 @@
++/* -*- c++ -*- */
++/*
++ * Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
++ *
++ * This file is part of GNU Radio
++ *
++ * GNU Radio is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3, or (at your option)
++ * any later version.
++ *
++ * GNU Radio is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GNU Radio; see the file COPYING. If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street,
++ * Boston, MA 02110-1301, USA.
++ */
++#ifndef INCLUDED_AIRSPYHF_SOURCE_C_H
++#define INCLUDED_AIRSPYHF_SOURCE_C_H
++
++#include <boost/circular_buffer.hpp>
++#include <boost/thread/mutex.hpp>
++#include <boost/thread/condition_variable.hpp>
++
++#include <gnuradio/sync_block.h>
++
++#include <libairspyhf/airspyhf.h>
++
++#include "source_iface.h"
++
++class airspyhf_source_c;
++
++typedef boost::shared_ptr<airspyhf_source_c> airspyhf_source_c_sptr;
++
++/*!
++ * \brief Return a shared_ptr to a new instance of airspyhf_source_c.
++ *
++ * To avoid accidental use of raw pointers, airspyhf_source_c's
++ * constructor is private. make_airspyhf_source_c is the public
++ * interface for creating new instances.
++ */
++airspyhf_source_c_sptr make_airspyhf_source_c (const std::string & args = "");
++
++/*!
++ * \brief Provides a stream of complex samples.
++ * \ingroup block
++ */
++class airspyhf_source_c :
++ public gr::sync_block,
++ public source_iface
++{
++private:
++ // The friend declaration allows make_airspyhf_source_c to
++ // access the private constructor.
++
++ friend airspyhf_source_c_sptr make_airspyhf_source_c (const std::string & args);
++
++ airspyhf_source_c (const std::string & args);
++
++public:
++ ~airspyhf_source_c ();
++
++ bool start();
++ bool stop();
++
++ int work( int noutput_items,
++ gr_vector_const_void_star &input_items,
++ gr_vector_void_star &output_items );
++
++ static std::vector< std::string > get_devices();
++
++ size_t get_num_channels( void );
++
++ osmosdr::meta_range_t get_sample_rates( void );
++ double set_sample_rate( double rate );
++ double get_sample_rate( void );
++
++ osmosdr::freq_range_t get_freq_range( size_t chan = 0 );
++ double set_center_freq( double freq, size_t chan = 0 );
++ double get_center_freq( size_t chan = 0 );
++ double set_freq_corr( double ppm, size_t chan = 0 );
++ double get_freq_corr( size_t chan = 0 );
++
++ std::vector<std::string> get_gain_names( size_t chan = 0 );
++ osmosdr::gain_range_t get_gain_range( size_t chan = 0 );
++ osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 );
++ double set_gain( double gain, size_t chan = 0 );
++ double set_gain( double gain, const std::string & name, size_t chan = 0 );
++ double get_gain( size_t chan = 0 );
++ double get_gain( const std::string & name, size_t chan = 0 );
++
++ std::vector< std::string > get_antennas( size_t chan = 0 );
++ std::string set_antenna( const std::string & antenna, size_t chan = 0 );
++ std::string get_antenna( size_t chan = 0 );
++
++
++private:
++ static int _airspyhf_rx_callback(airspyhf_transfer_t* transfer);
++ int airspyhf_rx_callback(void *samples, int sample_count);
++
++ airspyhf_device *_dev;
++
++ boost::circular_buffer<gr_complex> *_fifo;
++ boost::mutex _fifo_lock;
++ boost::condition_variable _samp_avail;
++
++ std::vector< std::pair<double, uint32_t> > _sample_rates;
++ double _sample_rate;
++ double _center_freq;
++ double _freq_corr;
++};
++
++#endif /* INCLUDED_AIRSPY_SOURCE_C_H */
+diff --git a/lib/config.h.in b/lib/config.h.in
+index 42e72f1..5303d7d 100644
+--- a/lib/config.h.in
++++ b/lib/config.h.in
+@@ -16,6 +16,7 @@
+ #cmakedefine ENABLE_BLADERF
+ #cmakedefine ENABLE_RFSPACE
+ #cmakedefine ENABLE_AIRSPY
++#cmakedefine ENABLE_AIRSPYHF
+ #cmakedefine ENABLE_SOAPY
+ #cmakedefine ENABLE_REDPITAYA
+ #cmakedefine ENABLE_FREESRP
+diff --git a/lib/device.cc b/lib/device.cc
+index 025a22b..586062f 100644
+--- a/lib/device.cc
++++ b/lib/device.cc
+@@ -78,6 +78,10 @@
+ #include <airspy_source_c.h>
+ #endif
+
++#ifdef ENABLE_AIRSPYHF
++#include <airspyhf_source_c.h>
++#endif
++
+ #ifdef ENABLE_SOAPY
+ #include <soapy_source_c.h>
+ #endif
+@@ -186,6 +190,10 @@ devices_t device::find(const device_t &hint)
+ BOOST_FOREACH( std::string dev, airspy_source_c::get_devices() )
+ devices.push_back( device_t(dev) );
+ #endif
++#ifdef ENABLE_AIRSPYHF
++ BOOST_FOREACH( std::string dev, airspyhf_source_c::get_devices() )
++ devices.push_back( device_t(dev) );
++#endif
+ #ifdef ENABLE_FREESRP
+ BOOST_FOREACH( std::string dev, freesrp_source_c::get_devices() )
+ devices.push_back( device_t(dev) );
+diff --git a/lib/source_impl.cc b/lib/source_impl.cc
+index a8a3cec..af2e3c2 100644
+--- a/lib/source_impl.cc
++++ b/lib/source_impl.cc
+@@ -80,6 +80,10 @@
+ #include <airspy_source_c.h>
+ #endif
+
++#ifdef ENABLE_AIRSPYHF
++#include <airspyhf_source_c.h>
++#endif
++
+ #ifdef ENABLE_SOAPY
+ #include <soapy_source_c.h>
+ #endif
+@@ -157,6 +161,9 @@ source_impl::source_impl( const std::string &args )
+ #ifdef ENABLE_AIRSPY
+ dev_types.push_back("airspy");
+ #endif
++#ifdef ENABLE_AIRSPYHF
++ dev_types.push_back("airspyhf");
++#endif
+ #ifdef ENABLE_SOAPY
+ dev_types.push_back("soapy");
+ #endif
+@@ -233,6 +240,10 @@ source_impl::source_impl( const std::string &args )
+ BOOST_FOREACH( std::string dev, airspy_source_c::get_devices() )
+ dev_list.push_back( dev );
+ #endif
++#ifdef ENABLE_AIRSPYHF
++ BOOST_FOREACH( std::string dev, airspyhf_source_c::get_devices() )
++ dev_list.push_back( dev );
++#endif
+ #ifdef ENABLE_SOAPY
+ BOOST_FOREACH( std::string dev, soapy_source_c::get_devices() )
+ dev_list.push_back( dev );
+@@ -355,6 +366,13 @@ source_impl::source_impl( const std::string &args )
+ }
+ #endif
+
++#ifdef ENABLE_AIRSPYHF
++ if ( dict.count("airspyhf") ) {
++ airspyhf_source_c_sptr src = make_airspyhf_source_c( arg );
++ block = src; iface = src.get();
++ }
++#endif
++
+ #ifdef ENABLE_SOAPY
+ if ( dict.count("soapy") ) {
+ soapy_source_c_sptr src = make_soapy_source_c( arg );
diff --git a/net-wireless/gr-osmosdr/gr-osmosdr-0.1.4_p20180626-r4.ebuild b/net-wireless/gr-osmosdr/gr-osmosdr-0.1.4_p20180626-r4.ebuild
new file mode 100644
index 0000000..b603e5e
--- /dev/null
+++ b/net-wireless/gr-osmosdr/gr-osmosdr-0.1.4_p20180626-r4.ebuild
@@ -0,0 +1,80 @@
+# Copyright 1999-2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+PYTHON_COMPAT=( python2_7 )
+
+inherit cmake-utils python-single-r1
+
+DESCRIPTION="GNU Radio source block for OsmoSDR and rtlsdr and hackrf"
+HOMEPAGE="http://sdr.osmocom.org/trac/wiki/GrOsmoSDR"
+
+if [[ ${PV} == 9999* ]]; then
+ inherit git-r3
+ SRC_URI=""
+ EGIT_REPO_URI="git://git.osmocom.org/${PN}.git"
+ KEYWORDS=""
+else
+ #SRC_URI="http://cgit.osmocom.org/gr-osmosdr/snapshot/gr-osmosdr-${PV}.tar.xz"
+ #git clone git://git.osmocom.org/gr-osmosdr.git
+ #cd gr-osmosdr
+ #git archive --format=tar --prefix=gr-osmosdr-${PV}/ v${PV} | xz > ../gr-osmosdr-${PV}.tar.xz
+ SRC_URI="https://dev.gentoo.org/~zerochaos/distfiles/gr-osmosdr-${PV}.tar.xz"
+ KEYWORDS="~amd64 ~arm ~x86"
+fi
+
+LICENSE="GPL-3"
+SLOT="0/${PV}"
+IUSE="airspyhf bladerf fcd hackrf iqbalance mirisdr python rtlsdr sdrplay soapy uhd"
+
+RDEPEND="${PYTHON_DEPS}
+ dev-libs/boost:=
+ >=net-wireless/gnuradio-3.7_rc:0=[fcd?,${PYTHON_USEDEP}]
+ airspyhf? ( net-wireless/airspyhf )
+ bladerf? ( >=net-wireless/bladerf-2018.08_rc1:= )
+ hackrf? ( net-libs/libhackrf:= )
+ iqbalance? ( net-wireless/gr-iqbal:=[${PYTHON_USEDEP}] )
+ mirisdr? ( net-libs/libmirisdr:= )
+ rtlsdr? ( >=net-wireless/rtl-sdr-0.5.4:= )
+ sdrplay? ( net-wireless/sdrplay )
+ soapy? ( net-wireless/soapysdr:= )
+ uhd? ( net-wireless/uhd:=[${PYTHON_USEDEP}] )"
+DEPEND="${RDEPEND}
+ dev-python/cheetah"
+
+REQUIRED_USE="${PYTHON_REQUIRED_USE}"
+
+src_prepare() {
+ eapply "${FILESDIR}/airspyhf.patch"
+ cmake-utils_src_prepare
+}
+
+src_configure() {
+ local mycmakeargs=(
+ -DENABLE_DEFAULT=OFF
+ -DPYTHON_EXECUTABLE="${PYTHON}"
+ -DENABLE_FILE=ON
+ -DENABLE_AIRSPYHFF="$(usex airspyhf)"
+ -DENABLE_BLADERF="$(usex bladerf)"
+ -DENABLE_FCD="$(usex fcd)"
+ -DENABLE_HACKRF="$(usex hackrf)"
+ -DENABLE_IQBALANCE="$(usex iqbalance)"
+ -DENABLE_MIRI="$(usex mirisdr)"
+ -DENABLE_PYTHON="$(usex python)"
+ -DENABLE_RTL="$(usex rtlsdr)"
+ -DENABLE_RTL_TCP="$(usex rtlsdr)"
+ -DENABLE_SOAPY="$(usex soapy)"
+ -DENABLE_UHD="$(usex uhd)"
+ -DENABLE_SDRPLAY="$(usex sdrplay)"
+ -DENABLE_NONFREE="$(usex sdrplay)"
+ )
+
+ cmake-utils_src_configure
+}
+
+src_install() {
+ cmake-utils_src_install
+ if use python; then
+ python_fix_shebang "${ED}"/usr/bin
+ fi
+}
diff --git a/net-wireless/gr-osmosdr/metadata.xml b/net-wireless/gr-osmosdr/metadata.xml
new file mode 100644
index 0000000..b55e17a
--- /dev/null
+++ b/net-wireless/gr-osmosdr/metadata.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="project">
+ <email>radio@gentoo.org</email>
+ <name>Radio</name>
+ </maintainer>
+<use>
+ <flag name="bladerf">Build with Nuand BladeRF support</flag>
+ <flag name="fcd">Build with Funcube Dongle support</flag>
+ <flag name="hackrf">Build with Great Scott Gadgets HackRF support</flag>
+ <flag name="iio">Build with Industrial IO support for devices such as Analog Devices Pluto</flag>
+ <flag name="iqbalance">Enable support for I/Q balancing using gr-iqbal</flag>
+ <flag name="mirisdr">Build with Mirics MSi2500 + MSi001 SDR support</flag>
+ <flag name="rtlsdr">Build with Realtek RTL2832U (rtlsdr) support</flag>
+ <flag name="sdrplay">Enable support for SDRplay devices through <pkg>net-wireless/sdrplay</pkg></flag>
+ <flag name="soapy">Build with SoapySDR support</flag>
+ <flag name="uhd">Build with Ettus Research USRP Hardware Driver support</flag>
+</use>
+</pkgmetadata>