mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-30 20:40:20 -04:00 
			
		
		
		
	Experimental Kernel swradio driver.
This commit is contained in:
		
							parent
							
								
									62656fc45b
								
							
						
					
					
						commit
						86f256dbc4
					
				| @ -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. | ||||
| 
 | ||||
|  | ||||
| @ -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}) | ||||
|  | ||||
| @ -19,6 +19,7 @@ | ||||
| #include <errno.h> | ||||
| #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; | ||||
|  | ||||
| @ -19,8 +19,8 @@ | ||||
| #define INCLUDE_V4LINPUT_H | ||||
| 
 | ||||
| #include "dsp/samplesource/samplesource.h" | ||||
| #include <rtl-sdr.h> | ||||
| #include <QString> | ||||
| #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<int> m_gains; | ||||
|  | ||||
| @ -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 */ | ||||
| 
 | ||||
|  | ||||
| @ -30,45 +30,11 @@ | ||||
| #include "fcntl.h" | ||||
| #include <sys/mman.h> | ||||
| 
 | ||||
| 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 */ | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -21,7 +21,6 @@ | ||||
| #include <QThread> | ||||
| #include <QMutex> | ||||
| #include <QWaitCondition> | ||||
| #include <rtl-sdr.h> | ||||
| #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
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user