From 86f256dbc4b27ae3d51a6dc07884b5a6493dbbc9 Mon Sep 17 00:00:00 2001 From: John Greb Date: Wed, 5 Nov 2014 21:19:25 +0000 Subject: [PATCH] Experimental Kernel swradio driver. --- Readme.md | 2 +- plugins/samplesource/v4l/CMakeLists.txt | 2 +- plugins/samplesource/v4l/v4linput.cpp | 51 +++++++++++++------------ plugins/samplesource/v4l/v4linput.h | 22 +++++++++-- plugins/samplesource/v4l/v4lsource.cpp | 40 +++++++++---------- plugins/samplesource/v4l/v4lsource.h | 42 ++------------------ plugins/samplesource/v4l/v4lthread.cpp | 13 ++++--- plugins/samplesource/v4l/v4lthread.h | 7 ++-- 8 files changed, 79 insertions(+), 100 deletions(-) diff --git a/Readme.md b/Readme.md index 9725c296d..c977e269a 100644 --- a/Readme.md +++ b/Readme.md @@ -5,5 +5,5 @@ For Ubuntu: "librtlsdr-dev" is in the "universe" repo. (utopic 14.10 amd64.) -Use "cmake ../ -DKERNEL=ON" to build the Linux kernel driver. May support Airspy and Hackrf. +Use "cmake ../ -DKERNEL=ON" to build the Linux kernel driver (Experimental). Needs a recent kernel and libv4l2. Will need extra work to support Airspy and Hackrf. diff --git a/plugins/samplesource/v4l/CMakeLists.txt b/plugins/samplesource/v4l/CMakeLists.txt index ba6f6c4de..c98a97bc0 100644 --- a/plugins/samplesource/v4l/CMakeLists.txt +++ b/plugins/samplesource/v4l/CMakeLists.txt @@ -25,7 +25,7 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include-gpl - ${LIBRTLSDR_INCLUDE_DIR} +# ${LIBRTLSDR_INCLUDE_DIR} ) #include(${QT_USE_FILE}) diff --git a/plugins/samplesource/v4l/v4linput.cpp b/plugins/samplesource/v4l/v4linput.cpp index e10b5419a..28495f39c 100644 --- a/plugins/samplesource/v4l/v4linput.cpp +++ b/plugins/samplesource/v4l/v4linput.cpp @@ -19,6 +19,7 @@ #include #include "v4linput.h" #include "v4lthread.h" +#include "v4lsource.h" #include "v4lgui.h" #include "util/simpleserializer.h" @@ -67,7 +68,7 @@ bool V4LInput::Settings::deserialize(const QByteArray& data) V4LInput::V4LInput(MessageQueue* msgQueueToGUI) : SampleSource(msgQueueToGUI), m_settings(), - m_dev(NULL), + m_dev(0), m_V4LThread(NULL), m_deviceDescription() { @@ -82,7 +83,7 @@ bool V4LInput::startInput(int device) { QMutexLocker mutexLocker(&m_mutex); - if(m_dev != NULL) + if(m_dev > 0) stopInput(); char vendor[256]; @@ -91,19 +92,23 @@ bool V4LInput::startInput(int device) int res; int numberOfGains; - if(!m_sampleFifo.setSize(524288)) { + vendor[0] = '\0'; + product[0] = '\0'; + serial[0] = '\0'; + + + if(!m_sampleFifo.setSize(524288)) { // fraction of samplerate qCritical("Could not allocate SampleFifo"); return false; } - if((res = rtlsdr_open(&m_dev, device)) < 0) { - qCritical("could not open RTLSDR #%d: %s", device, strerror(errno)); + OpenSource("/dev/swradio0"); + if (m_dev == 0) { + qCritical("could not open SDR"); return false; } - - vendor[0] = '\0'; - product[0] = '\0'; - serial[0] = '\0'; + m_dev = device; +/* if((res = rtlsdr_get_usb_strings(m_dev, vendor, product, serial)) < 0) { qCritical("error accessing USB device"); goto failed; @@ -139,8 +144,8 @@ bool V4LInput::startInput(int device) qCritical("could not reset USB EP buffers: %s", strerror(errno)); goto failed; } - - if((m_V4LThread = new V4LThread(m_dev, &m_sampleFifo)) == NULL) { +*/ + if((m_V4LThread = new V4LThread(&m_sampleFifo)) == NULL) { qFatal("out of memory"); goto failed; } @@ -149,7 +154,7 @@ bool V4LInput::startInput(int device) mutexLocker.unlock(); applySettings(m_generalSettings, m_settings, true); - qDebug("RTLSDRInput: start"); + qDebug("V4LInput: start"); MsgReportV4L::create(m_gains)->submit(m_guiMessageQueue); return true; @@ -168,9 +173,9 @@ void V4LInput::stopInput() delete m_V4LThread; m_V4LThread = NULL; } - if(m_dev != NULL) { - rtlsdr_close(m_dev); - m_dev = NULL; + if(m_dev > 0) { + CloseSource(); + m_dev = 0; } m_deviceDescription.clear(); } @@ -209,22 +214,18 @@ bool V4LInput::applySettings(const GeneralSettings& generalSettings, const Setti if((m_generalSettings.m_centerFrequency != generalSettings.m_centerFrequency) || force) { m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency; - if(m_dev != NULL) { - if(rtlsdr_set_center_freq(m_dev, m_generalSettings.m_centerFrequency - + 384000) != 0) - qDebug("osmosdr_set_center_freq(%lld) failed", m_generalSettings.m_centerFrequency); - } + if(m_dev > 0) + V4LInput::set_center_freq( (double)(m_generalSettings.m_centerFrequency + + 384000) ); // samplerate/4 } if((m_settings.m_gain != settings.m_gain) || force) { m_settings.m_gain = settings.m_gain; - if(m_dev != NULL) { - if(rtlsdr_set_tuner_gain(m_dev, m_settings.m_gain) != 0) - qDebug("rtlsdr_set_tuner_gain() failed"); - } + if(m_dev > 0) + V4LInput::set_tuner_gain((double)m_settings.m_gain); } if((m_settings.m_decimation != settings.m_decimation) || force) { m_settings.m_decimation = settings.m_decimation; - if(m_dev != NULL) + if(m_dev > 0) m_V4LThread->setDecimation(m_settings.m_decimation); } return true; diff --git a/plugins/samplesource/v4l/v4linput.h b/plugins/samplesource/v4l/v4linput.h index a22db6cbd..12d8613c0 100644 --- a/plugins/samplesource/v4l/v4linput.h +++ b/plugins/samplesource/v4l/v4linput.h @@ -19,8 +19,8 @@ #define INCLUDE_V4LINPUT_H #include "dsp/samplesource/samplesource.h" -#include #include +#include "v4lsource.h" class V4LThread; @@ -88,13 +88,29 @@ public: const QString& getDeviceDescription() const; int getSampleRate() const; quint64 getCenterFrequency() const; - bool handleMessage(Message* message); + void OpenSource(const char *filename); + void CloseSource(); + void set_sample_rate(double samp_rate); + void set_center_freq(double freq); + void set_bandwidth(double bandwidth); + void set_tuner_gain(double gain); + int work(int noutput_items, + void* input_items, + void* output_items); private: + int fd; + quint32 pixelformat; + struct v4l_buffer *buffers; + unsigned int n_buffers; + void *recebuf_ptr; + unsigned int recebuf_len; + unsigned int recebuf_mmap_index; + QMutex m_mutex; Settings m_settings; - rtlsdr_dev_t* m_dev; + int m_dev; V4LThread* m_V4LThread; QString m_deviceDescription; std::vector m_gains; diff --git a/plugins/samplesource/v4l/v4lsource.cpp b/plugins/samplesource/v4l/v4lsource.cpp index 7c809f897..dddaa4219 100644 --- a/plugins/samplesource/v4l/v4lsource.cpp +++ b/plugins/samplesource/v4l/v4lsource.cpp @@ -18,6 +18,7 @@ */ #include "v4lsource.h" +#include "v4linput.h" /* Control classes */ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ @@ -33,8 +34,8 @@ #define CID_TUNER_IF ((V4L2_CID_USER_BASE | 0xf000) + 12) #define CID_TUNER_GAIN ((V4L2_CID_USER_BASE | 0xf000) + 13) -#define V4L2_PIX_FMT_SDR_U8 v4l2_fourcc('D', 'U', '0', '8') /* unsigned 8-bit */ -#define V4L2_PIX_FMT_SDR_U16LE v4l2_fourcc('D', 'U', '1', '6') /* unsigned 16-bit LE */ +#define V4L2_PIX_FMT_SDR_U8 v4l2_fourcc('C', 'U', '0', '8') /* unsigned 8-bit Complex*/ +#define V4L2_PIX_FMT_SDR_U16LE v4l2_fourcc('C', 'U', '1', '6') /* unsigned 16-bit Complex*/ #define CLEAR(x) memset(&(x), 0, sizeof(x)) @@ -50,9 +51,8 @@ static void xioctl(int fh, unsigned long int request, void *arg) } } -namespace kernel{ - - v4l::v4l(const char *filename) +void +V4LInput::OpenSource(const char *filename) { struct v4l2_format fmt; struct v4l2_buffer buf; @@ -89,7 +89,7 @@ namespace kernel{ req.memory = V4L2_MEMORY_MMAP; xioctl(fd, VIDIOC_REQBUFS, &req); - buffers = (struct buffer*) calloc(req.count, sizeof(*buffers)); + buffers = (struct v4l_buffer*) calloc(req.count, sizeof(*buffers)); for (n_buffers = 0; n_buffers < req.count; n_buffers++) { CLEAR(buf); buf.type = V4L2_BUF_TYPE_SDR_CAPTURE; @@ -120,10 +120,8 @@ namespace kernel{ xioctl(fd, VIDIOC_STREAMON, &type); } - /* - * Our virtual destructor. - */ - v4l::~v4l() +void +V4LInput::CloseSource() { unsigned int i; enum v4l2_buf_type type; @@ -138,8 +136,8 @@ namespace kernel{ v4l2_close(fd); } - void - v4l::set_samp_rate(double samp_rate) +void +V4LInput::set_sample_rate(double samp_rate) { struct v4l2_frequency frequency; @@ -154,8 +152,8 @@ namespace kernel{ return; } - void - v4l::set_center_freq(double freq) +void +V4LInput::set_center_freq(double freq) { struct v4l2_frequency frequency; @@ -170,8 +168,8 @@ namespace kernel{ return; } - void - v4l::set_bandwidth(double bandwidth) +void +V4LInput::set_bandwidth(double bandwidth) { struct v4l2_ext_controls ext_ctrls; struct v4l2_ext_control ext_ctrl; @@ -191,8 +189,8 @@ namespace kernel{ return; } - void - v4l::set_tuner_gain(double gain) +void +V4LInput::set_tuner_gain(double gain) { struct v4l2_ext_controls ext_ctrls; struct v4l2_ext_control ext_ctrl; @@ -212,8 +210,8 @@ namespace kernel{ return; } - int - v4l::work(int noutput_items, +int +V4LInput::work(int noutput_items, void* input_items, void* output_items) { @@ -297,5 +295,3 @@ process_buf: return 0; } -} /* namespace kernel */ - diff --git a/plugins/samplesource/v4l/v4lsource.h b/plugins/samplesource/v4l/v4lsource.h index 7550010e0..5f691def7 100644 --- a/plugins/samplesource/v4l/v4lsource.h +++ b/plugins/samplesource/v4l/v4lsource.h @@ -30,45 +30,11 @@ #include "fcntl.h" #include -namespace kernel { - // v4l2_mmap - struct buffer { - void *start; - size_t length; - }; +struct v4l_buffer { + void *start; + size_t length; +}; - class v4l //: public v4l - { - private: - // v4l2 device file handle - int fd; - - // stream / sample format - uint32_t pixelformat; - - struct buffer *buffers; - unsigned int n_buffers; - - // for processing mmap buffer - void *recebuf_ptr; - unsigned int recebuf_len; - unsigned int recebuf_mmap_index; - - public: - v4l(const char *filename); - ~v4l(); - - void set_samp_rate(double samp_rate); - void set_center_freq(double freq); - void set_bandwidth(double bandwidth); - void set_tuner_gain(double gain); - - // Where all the action really happens - int work(int noutput_items, - void* input_items, - void* output_items); - }; -} // namespace kernel #endif /* INCLUDED_KERNEL_LIBV4L2_X_IMPL_H */ diff --git a/plugins/samplesource/v4l/v4lthread.cpp b/plugins/samplesource/v4l/v4lthread.cpp index 259addcef..c15c6faeb 100644 --- a/plugins/samplesource/v4l/v4lthread.cpp +++ b/plugins/samplesource/v4l/v4lthread.cpp @@ -22,10 +22,10 @@ #define BLOCKSIZE 16384 -V4LThread::V4LThread(rtlsdr_dev_t* dev, SampleFifo* sampleFifo, QObject* parent) : +V4LThread::V4LThread(SampleFifo* sampleFifo, QObject* parent) : QThread(parent), m_running(false), - m_dev(dev), + m_dev(1), m_convertBuffer(BLOCKSIZE), m_sampleFifo(sampleFifo), m_decimation(2) @@ -64,14 +64,14 @@ void V4LThread::run() m_running = true; m_startWaiter.wakeAll(); - +/* while(m_running) { if((res = rtlsdr_read_async(m_dev, &V4LThread::callbackHelper, this, 32, BLOCKSIZE)) < 0) { qCritical("V4LThread: async error: %s", strerror(errno)); break; } } - +*/ m_running = false; } @@ -178,12 +178,13 @@ void V4LThread::callback(const quint8* buf, qint32 len) } m_sampleFifo->write(m_convertBuffer.begin(), it); - +/* if(!m_running) rtlsdr_cancel_async(m_dev); +*/ } -void V4LThread::callbackHelper(unsigned char* buf, uint32_t len, void* ctx) +void V4LThread::callbackHelper(unsigned char* buf, quint32 len, void* ctx) { V4LThread* thread = (V4LThread*)ctx; thread->callback(buf, len); diff --git a/plugins/samplesource/v4l/v4lthread.h b/plugins/samplesource/v4l/v4lthread.h index 36225d268..773f400e0 100644 --- a/plugins/samplesource/v4l/v4lthread.h +++ b/plugins/samplesource/v4l/v4lthread.h @@ -21,7 +21,6 @@ #include #include #include -#include #include "dsp/samplefifo.h" #include "dsp/inthalfbandfilter.h" @@ -29,7 +28,7 @@ class V4LThread : public QThread { Q_OBJECT public: - V4LThread(rtlsdr_dev_t* dev, SampleFifo* sampleFifo, QObject* parent = NULL); + V4LThread(SampleFifo* sampleFifo, QObject* parent = NULL); ~V4LThread(); void startWork(); @@ -42,7 +41,7 @@ private: QWaitCondition m_startWaiter; bool m_running; - rtlsdr_dev_t* m_dev; + int m_dev; SampleVector m_convertBuffer; SampleFifo* m_sampleFifo; @@ -57,7 +56,7 @@ private: void decimate16(SampleVector::iterator* it, const quint8* buf, qint32 len); void callback(const quint8* buf, qint32 len); - static void callbackHelper(unsigned char* buf, uint32_t len, void* ctx); + static void callbackHelper(unsigned char* buf, quint32 len, void* ctx); }; #endif // INCLUDE_V4LTHREAD_H