History

[media] airspy: AirSpy SDR driver

AirSpy SDR driver. Thanks to Youssef Touil and Benjamin Vernoux for support, help and hardware! http://airspy.com/

Antti Palosaari committed 12 years ago

Commit 634fe501 parent dd6b66d5 files · +1128 −0Browse files

Unified · Split

5 files
  1. drivers/staging/media/Kconfig +1 −0
  2. drivers/staging/media/Makefile +1 −0
  3. drivers/staging/media/airspy/Kconfig +5 −0
  4. drivers/staging/media/airspy/Makefile +1 −0
  5. drivers/staging/media/airspy/airspy.c +1120 −0
drivers/staging/media/Kconfig+1−0
@@ -19,6 +19,7 @@ menuconfig STAGING_MEDIA · 18 unmodified lines
1919 if STAGING_MEDIA
2020
2121 # Please keep them in alphabetic order
22+source "drivers/staging/media/airspy/Kconfig"
2223 source "drivers/staging/media/as102/Kconfig"
2324
2425 source "drivers/staging/media/bcm2048/Kconfig"
drivers/staging/media/Makefile+1−0
@@ -1,3 +1,4 @@
1+obj-$(CONFIG_USB_AIRSPY) += airspy/
12 obj-$(CONFIG_DVB_AS102) += as102/
23 obj-$(CONFIG_I2C_BCM2048) += bcm2048/
34 obj-$(CONFIG_DVB_CXD2099) += cxd2099/
drivers/staging/media/airspy/Kconfig+5−0
@@ -0,0 +1,5 @@
1+config USB_AIRSPY
2+ tristate "AirSpy"
3+ depends on USB && VIDEO_DEV && VIDEO_V4L2 && I2C
4+ select VIDEOBUF2_VMALLOC
5+ default m if !MEDIA_SUBDRV_AUTOSELECT
drivers/staging/media/airspy/Makefile+1−0
@@ -0,0 +1 @@
1+obj-$(CONFIG_USB_AIRSPY) += airspy.o
drivers/staging/media/airspy/airspy.c+1120−0
@@ -0,0 +1,1120 @@
1+/*
2+ * AirSpy SDR driver
3+ *
4+ * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
5+ *
6+ * This program is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 2 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ */
16+
17+#include <linux/module.h>
18+#include <linux/slab.h>
19+#include <linux/usb.h>
20+#include <media/v4l2-device.h>
21+#include <media/v4l2-ioctl.h>
22+#include <media/v4l2-ctrls.h>
23+#include <media/v4l2-event.h>
24+#include <media/videobuf2-vmalloc.h>
25+
26+/* AirSpy USB API commands (from AirSpy Library) */
27+enum {
28+ CMD_INVALID = 0x00,
29+ CMD_RECEIVER_MODE = 0x01,
30+ CMD_SI5351C_WRITE = 0x02,
31+ CMD_SI5351C_READ = 0x03,
32+ CMD_R820T_WRITE = 0x04,
33+ CMD_R820T_READ = 0x05,
34+ CMD_SPIFLASH_ERASE = 0x06,
35+ CMD_SPIFLASH_WRITE = 0x07,
36+ CMD_SPIFLASH_READ = 0x08,
37+ CMD_BOARD_ID_READ = 0x09,
38+ CMD_VERSION_STRING_READ = 0x0a,
39+ CMD_BOARD_PARTID_SERIALNO_READ = 0x0b,
40+ CMD_SET_SAMPLE_RATE = 0x0c,
41+ CMD_SET_FREQ = 0x0d,
42+ CMD_SET_LNA_GAIN = 0x0e,
43+ CMD_SET_MIXER_GAIN = 0x0f,
44+ CMD_SET_VGA_GAIN = 0x10,
45+ CMD_SET_LNA_AGC = 0x11,
46+ CMD_SET_MIXER_AGC = 0x12,
47+ CMD_SET_PACKING = 0x13,
48+};
49+
50+/*
51+ * bEndpointAddress 0x81 EP 1 IN
52+ * Transfer Type Bulk
53+ * wMaxPacketSize 0x0200 1x 512 bytes
54+ */
55+#define MAX_BULK_BUFS (6)
56+#define BULK_BUFFER_SIZE (128 * 512)
57+
58+static const struct v4l2_frequency_band bands[] = {
59+ {
60+ .tuner = 0,
61+ .type = V4L2_TUNER_ADC,
62+ .index = 0,
63+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
64+ .rangelow = 20000000,
65+ .rangehigh = 20000001, /* FIXME: make v4l2-compliance happy */
66+ },
67+};
68+
69+static const struct v4l2_frequency_band bands_rf[] = {
70+ {
71+ .tuner = 1,
72+ .type = V4L2_TUNER_RF,
73+ .index = 0,
74+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
75+ .rangelow = 24000000,
76+ .rangehigh = 1750000000,
77+ },
78+};
79+
80+/* stream formats */
81+struct airspy_format {
82+ char *name;
83+ u32 pixelformat;
84+};
85+
86+/* format descriptions for capture and preview */
87+static struct airspy_format formats[] = {
88+ {
89+ .name = "Real U12LE",
90+ .pixelformat = V4L2_SDR_FMT_RU12LE,
91+ },
92+};
93+
94+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
95+
96+/* intermediate buffers with raw data from the USB device */
97+struct airspy_frame_buf {
98+ struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
99+ struct list_head list;
100+};
101+
102+struct airspy {
103+#define POWER_ON (1 << 1)
104+#define URB_BUF (1 << 2)
105+#define USB_STATE_URB_BUF (1 << 3)
106+ unsigned long flags;
107+
108+ struct usb_device *udev;
109+ struct video_device vdev;
110+ struct v4l2_device v4l2_dev;
111+
112+ /* videobuf2 queue and queued buffers list */
113+ struct vb2_queue vb_queue;
114+ struct list_head queued_bufs;
115+ spinlock_t queued_bufs_lock; /* Protects queued_bufs */
116+ unsigned sequence; /* Buffer sequence counter */
117+ unsigned int vb_full; /* vb is full and packets dropped */
118+
119+ /* Note if taking both locks v4l2_lock must always be locked first! */
120+ struct mutex v4l2_lock; /* Protects everything else */
121+ struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */
122+
123+ struct urb *urb_list[MAX_BULK_BUFS];
124+ int buf_num;
125+ unsigned long buf_size;
126+ u8 *buf_list[MAX_BULK_BUFS];
127+ dma_addr_t dma_addr[MAX_BULK_BUFS];
128+ int urbs_initialized;
129+ int urbs_submitted;
130+
131+ /* USB control message buffer */
132+ #define BUF_SIZE 24
133+ u8 buf[BUF_SIZE];
134+
135+ /* Current configuration */
136+ unsigned int f_adc;
137+ unsigned int f_rf;
138+ u32 pixelformat;
139+
140+ /* Controls */
141+ struct v4l2_ctrl_handler hdl;
142+ struct v4l2_ctrl *lna_gain_auto;
143+ struct v4l2_ctrl *lna_gain;
144+ struct v4l2_ctrl *mixer_gain_auto;
145+ struct v4l2_ctrl *mixer_gain;
146+ struct v4l2_ctrl *if_gain;
147+
148+ /* Sample rate calc */
149+ unsigned long jiffies_next;
150+ unsigned int sample;
151+ unsigned int sample_measured;
152+};
153+
154+#define airspy_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
155+ char *_direction; \
156+ if (_t & USB_DIR_IN) \
157+ _direction = "<<<"; \
158+ else \
159+ _direction = ">>>"; \
160+ dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
161+ "%s %*ph\n", __func__, _t, _r, _v & 0xff, _v >> 8, \
162+ _i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
163+ _l, _b); \
164+}
165+
166+/* execute firmware command */
167+static int airspy_ctrl_msg(struct airspy *s, u8 request, u16 value, u16 index,
168+ u8 *data, u16 size)
169+{
170+ int ret;
171+ unsigned int pipe;
172+ u8 requesttype;
173+
174+ switch (request) {
175+ case CMD_RECEIVER_MODE:
176+ case CMD_SET_FREQ:
177+ pipe = usb_sndctrlpipe(s->udev, 0);
178+ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
179+ break;
180+ case CMD_BOARD_ID_READ:
181+ case CMD_VERSION_STRING_READ:
182+ case CMD_BOARD_PARTID_SERIALNO_READ:
183+ case CMD_SET_LNA_GAIN:
184+ case CMD_SET_MIXER_GAIN:
185+ case CMD_SET_VGA_GAIN:
186+ case CMD_SET_LNA_AGC:
187+ case CMD_SET_MIXER_AGC:
188+ pipe = usb_rcvctrlpipe(s->udev, 0);
189+ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
190+ break;
191+ default:
192+ dev_err(&s->udev->dev, "Unknown command %02x\n", request);
193+ ret = -EINVAL;
194+ goto err;
195+ }
196+
197+ /* write request */
198+ if (!(requesttype & USB_DIR_IN))
199+ memcpy(s->buf, data, size);
200+
201+ ret = usb_control_msg(s->udev, pipe, request, requesttype, value,
202+ index, s->buf, size, 1000);
203+ airspy_dbg_usb_control_msg(s->udev, request, requesttype, value,
204+ index, s->buf, size);
205+ if (ret < 0) {
206+ dev_err(&s->udev->dev,
207+ "usb_control_msg() failed %d request %02x\n",
208+ ret, request);
209+ goto err;
210+ }
211+
212+ /* read request */
213+ if (requesttype & USB_DIR_IN)
214+ memcpy(data, s->buf, size);
215+
216+ return 0;
217+err:
218+ return ret;
219+}
220+
221+/* Private functions */
222+static struct airspy_frame_buf *airspy_get_next_fill_buf(struct airspy *s)
223+{
224+ unsigned long flags = 0;
225+ struct airspy_frame_buf *buf = NULL;
226+
227+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
228+ if (list_empty(&s->queued_bufs))
229+ goto leave;
230+
231+ buf = list_entry(s->queued_bufs.next,
232+ struct airspy_frame_buf, list);
233+ list_del(&buf->list);
234+leave:
235+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
236+ return buf;
237+}
238+
239+static unsigned int airspy_convert_stream(struct airspy *s,
240+ void *dst, void *src, unsigned int src_len)
241+{
242+ unsigned int dst_len;
243+
244+ if (s->pixelformat == V4L2_SDR_FMT_RU12LE) {
245+ memcpy(dst, src, src_len);
246+ dst_len = src_len;
247+ } else {
248+ dst_len = 0;
249+ }
250+
251+ /* calculate samping rate and output it in 10 seconds intervals */
252+ if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
253+ #define MSECS 10000UL
254+ unsigned int samples = s->sample - s->sample_measured;
255+ s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
256+ s->sample_measured = s->sample;
257+ dev_dbg(&s->udev->dev,
258+ "slen=%d samples=%u msecs=%lu sample rate=%lu\n",
259+ src_len, samples, MSECS,
260+ samples * 1000UL / MSECS);
261+ }
262+
263+ /* total number of samples */
264+ s->sample += src_len / 2;
265+
266+ return dst_len;
267+}
268+
269+/*
270+ * This gets called for the bulk stream pipe. This is done in interrupt
271+ * time, so it has to be fast, not crash, and not stall. Neat.
272+ */
273+static void airspy_urb_complete(struct urb *urb)
274+{
275+ struct airspy *s = urb->context;
276+ struct airspy_frame_buf *fbuf;
277+
278+ dev_dbg_ratelimited(&s->udev->dev,
279+ "%s: status=%d length=%d/%d errors=%d\n",
280+ __func__, urb->status, urb->actual_length,
281+ urb->transfer_buffer_length, urb->error_count);
282+
283+ switch (urb->status) {
284+ case 0: /* success */
285+ case -ETIMEDOUT: /* NAK */
286+ break;
287+ case -ECONNRESET: /* kill */
288+ case -ENOENT:
289+ case -ESHUTDOWN:
290+ return;
291+ default: /* error */
292+ dev_err_ratelimited(&s->udev->dev, "URB failed %d\n",
293+ urb->status);
294+ break;
295+ }
296+
297+ if (likely(urb->actual_length > 0)) {
298+ void *ptr;
299+ unsigned int len;
300+ /* get free framebuffer */
301+ fbuf = airspy_get_next_fill_buf(s);
302+ if (unlikely(fbuf == NULL)) {
303+ s->vb_full++;
304+ dev_notice_ratelimited(&s->udev->dev,
305+ "videobuf is full, %d packets dropped\n",
306+ s->vb_full);
307+ goto skip;
308+ }
309+
310+ /* fill framebuffer */
311+ ptr = vb2_plane_vaddr(&fbuf->vb, 0);
312+ len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
313+ urb->actual_length);
314+ vb2_set_plane_payload(&fbuf->vb, 0, len);
315+ v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
316+ fbuf->vb.v4l2_buf.sequence = s->sequence++;
317+ vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
318+ }
319+skip:
320+ usb_submit_urb(urb, GFP_ATOMIC);
321+}
322+
323+static int airspy_kill_urbs(struct airspy *s)
324+{
325+ int i;
326+
327+ for (i = s->urbs_submitted - 1; i >= 0; i--) {
328+ dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
329+ /* stop the URB */
330+ usb_kill_urb(s->urb_list[i]);
331+ }
332+ s->urbs_submitted = 0;
333+
334+ return 0;
335+}
336+
337+static int airspy_submit_urbs(struct airspy *s)
338+{
339+ int i, ret;
340+
341+ for (i = 0; i < s->urbs_initialized; i++) {
342+ dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
343+ ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
344+ if (ret) {
345+ dev_err(&s->udev->dev,
346+ "Could not submit URB no. %d - get them all back\n",
347+ i);
348+ airspy_kill_urbs(s);
349+ return ret;
350+ }
351+ s->urbs_submitted++;
352+ }
353+
354+ return 0;
355+}
356+
357+static int airspy_free_stream_bufs(struct airspy *s)
358+{
359+ if (s->flags & USB_STATE_URB_BUF) {
360+ while (s->buf_num) {
361+ s->buf_num--;
362+ dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
363+ __func__, s->buf_num);
364+ usb_free_coherent(s->udev, s->buf_size,
365+ s->buf_list[s->buf_num],
366+ s->dma_addr[s->buf_num]);
367+ }
368+ }
369+ s->flags &= ~USB_STATE_URB_BUF;
370+
371+ return 0;
372+}
373+
374+static int airspy_alloc_stream_bufs(struct airspy *s)
375+{
376+ s->buf_num = 0;
377+ s->buf_size = BULK_BUFFER_SIZE;
378+
379+ dev_dbg(&s->udev->dev,
380+ "%s: all in all I will use %u bytes for streaming\n",
381+ __func__, MAX_BULK_BUFS * BULK_BUFFER_SIZE);
382+
383+ for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
384+ s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
385+ BULK_BUFFER_SIZE, GFP_ATOMIC,
386+ &s->dma_addr[s->buf_num]);
387+ if (!s->buf_list[s->buf_num]) {
388+ dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
389+ __func__, s->buf_num);
390+ airspy_free_stream_bufs(s);
391+ return -ENOMEM;
392+ }
393+
394+ dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
395+ __func__, s->buf_num,
396+ s->buf_list[s->buf_num],
397+ (long long)s->dma_addr[s->buf_num]);
398+ s->flags |= USB_STATE_URB_BUF;
399+ }
400+
401+ return 0;
402+}
403+
404+static int airspy_free_urbs(struct airspy *s)
405+{
406+ int i;
407+
408+ airspy_kill_urbs(s);
409+
410+ for (i = s->urbs_initialized - 1; i >= 0; i--) {
411+ if (s->urb_list[i]) {
412+ dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
413+ __func__, i);
414+ /* free the URBs */
415+ usb_free_urb(s->urb_list[i]);
416+ }
417+ }
418+ s->urbs_initialized = 0;
419+
420+ return 0;
421+}
422+
423+static int airspy_alloc_urbs(struct airspy *s)
424+{
425+ int i, j;
426+
427+ /* allocate the URBs */
428+ for (i = 0; i < MAX_BULK_BUFS; i++) {
429+ dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
430+ s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
431+ if (!s->urb_list[i]) {
432+ dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
433+ for (j = 0; j < i; j++)
434+ usb_free_urb(s->urb_list[j]);
435+ return -ENOMEM;
436+ }
437+ usb_fill_bulk_urb(s->urb_list[i],
438+ s->udev,
439+ usb_rcvbulkpipe(s->udev, 0x81),
440+ s->buf_list[i],
441+ BULK_BUFFER_SIZE,
442+ airspy_urb_complete, s);
443+
444+ s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
445+ s->urb_list[i]->transfer_dma = s->dma_addr[i];
446+ s->urbs_initialized++;
447+ }
448+
449+ return 0;
450+}
451+
452+/* Must be called with vb_queue_lock hold */
453+static void airspy_cleanup_queued_bufs(struct airspy *s)
454+{
455+ unsigned long flags = 0;
456+
457+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
458+
459+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
460+ while (!list_empty(&s->queued_bufs)) {
461+ struct airspy_frame_buf *buf;
462+ buf = list_entry(s->queued_bufs.next,
463+ struct airspy_frame_buf, list);
464+ list_del(&buf->list);
465+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
466+ }
467+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
468+}
469+
470+/* The user yanked out the cable... */
471+static void airspy_disconnect(struct usb_interface *intf)
472+{
473+ struct v4l2_device *v = usb_get_intfdata(intf);
474+ struct airspy *s = container_of(v, struct airspy, v4l2_dev);
475+
476+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
477+
478+ mutex_lock(&s->vb_queue_lock);
479+ mutex_lock(&s->v4l2_lock);
480+ /* No need to keep the urbs around after disconnection */
481+ s->udev = NULL;
482+ v4l2_device_disconnect(&s->v4l2_dev);
483+ video_unregister_device(&s->vdev);
484+ mutex_unlock(&s->v4l2_lock);
485+ mutex_unlock(&s->vb_queue_lock);
486+
487+ v4l2_device_put(&s->v4l2_dev);
488+}
489+
490+/* Videobuf2 operations */
491+static int airspy_queue_setup(struct vb2_queue *vq,
492+ const struct v4l2_format *fmt, unsigned int *nbuffers,
493+ unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
494+{
495+ struct airspy *s = vb2_get_drv_priv(vq);
496+
497+ dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
498+
499+ /* Need at least 8 buffers */
500+ if (vq->num_buffers + *nbuffers < 8)
501+ *nbuffers = 8 - vq->num_buffers;
502+ *nplanes = 1;
503+ sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE);
504+
505+ dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
506+ __func__, *nbuffers, sizes[0]);
507+ return 0;
508+}
509+
510+static void airspy_buf_queue(struct vb2_buffer *vb)
511+{
512+ struct airspy *s = vb2_get_drv_priv(vb->vb2_queue);
513+ struct airspy_frame_buf *buf =
514+ container_of(vb, struct airspy_frame_buf, vb);
515+ unsigned long flags = 0;
516+
517+ /* Check the device has not disconnected between prep and queuing */
518+ if (unlikely(!s->udev)) {
519+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
520+ return;
521+ }
522+
523+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
524+ list_add_tail(&buf->list, &s->queued_bufs);
525+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
526+}
527+
528+static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count)
529+{
530+ struct airspy *s = vb2_get_drv_priv(vq);
531+ int ret;
532+
533+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
534+
535+ if (!s->udev)
536+ return -ENODEV;
537+
538+ mutex_lock(&s->v4l2_lock);
539+
540+ set_bit(POWER_ON, &s->flags);
541+
542+ s->sequence = 0;
543+
544+ ret = airspy_alloc_stream_bufs(s);
545+ if (ret)
546+ goto err;
547+
548+ ret = airspy_alloc_urbs(s);
549+ if (ret)
550+ goto err;
551+
552+ ret = airspy_submit_urbs(s);
553+ if (ret)
554+ goto err;
555+
556+ /* start hardware streaming */
557+ ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 1, 0, NULL, 0);
558+ if (ret)
559+ goto err;
560+err:
561+ mutex_unlock(&s->v4l2_lock);
562+
563+ return ret;
564+}
565+
566+static void airspy_stop_streaming(struct vb2_queue *vq)
567+{
568+ struct airspy *s = vb2_get_drv_priv(vq);
569+ int ret;
570+
571+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
572+
573+ mutex_lock(&s->v4l2_lock);
574+
575+ /* stop hardware streaming */
576+ ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0);
577+
578+ airspy_kill_urbs(s);
579+ airspy_free_urbs(s);
580+ airspy_free_stream_bufs(s);
581+
582+ airspy_cleanup_queued_bufs(s);
583+
584+ clear_bit(POWER_ON, &s->flags);
585+
586+ mutex_unlock(&s->v4l2_lock);
587+}
588+
589+static struct vb2_ops airspy_vb2_ops = {
590+ .queue_setup = airspy_queue_setup,
591+ .buf_queue = airspy_buf_queue,
592+ .start_streaming = airspy_start_streaming,
593+ .stop_streaming = airspy_stop_streaming,
594+ .wait_prepare = vb2_ops_wait_prepare,
595+ .wait_finish = vb2_ops_wait_finish,
596+};
597+
598+static int airspy_querycap(struct file *file, void *fh,
599+ struct v4l2_capability *cap)
600+{
601+ struct airspy *s = video_drvdata(file);
602+
603+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
604+
605+ strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
606+ strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
607+ usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
608+ cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
609+ V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
610+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
611+
612+ return 0;
613+}
614+
615+static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv,
616+ struct v4l2_fmtdesc *f)
617+{
618+ struct airspy *s = video_drvdata(file);
619+
620+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
621+
622+ if (f->index >= NUM_FORMATS)
623+ return -EINVAL;
624+
625+ strlcpy(f->description, formats[f->index].name, sizeof(f->description));
626+ f->pixelformat = formats[f->index].pixelformat;
627+
628+ return 0;
629+}
630+
631+static int airspy_g_fmt_sdr_cap(struct file *file, void *priv,
632+ struct v4l2_format *f)
633+{
634+ struct airspy *s = video_drvdata(file);
635+
636+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
637+ (char *)&s->pixelformat);
638+
639+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
640+ f->fmt.sdr.pixelformat = s->pixelformat;
641+
642+ return 0;
643+}
644+
645+static int airspy_s_fmt_sdr_cap(struct file *file, void *priv,
646+ struct v4l2_format *f)
647+{
648+ struct airspy *s = video_drvdata(file);
649+ struct vb2_queue *q = &s->vb_queue;
650+ int i;
651+
652+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
653+ (char *)&f->fmt.sdr.pixelformat);
654+
655+ if (vb2_is_busy(q))
656+ return -EBUSY;
657+
658+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
659+ for (i = 0; i < NUM_FORMATS; i++) {
660+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
661+ s->pixelformat = f->fmt.sdr.pixelformat;
662+ return 0;
663+ }
664+ }
665+
666+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
667+ s->pixelformat = formats[0].pixelformat;
668+
669+ return 0;
670+}
671+
672+static int airspy_try_fmt_sdr_cap(struct file *file, void *priv,
673+ struct v4l2_format *f)
674+{
675+ struct airspy *s = video_drvdata(file);
676+ int i;
677+
678+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
679+ (char *)&f->fmt.sdr.pixelformat);
680+
681+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
682+ for (i = 0; i < NUM_FORMATS; i++) {
683+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
684+ return 0;
685+ }
686+
687+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
688+
689+ return 0;
690+}
691+
692+static int airspy_s_tuner(struct file *file, void *priv,
693+ const struct v4l2_tuner *v)
694+{
695+ struct airspy *s = video_drvdata(file);
696+ int ret;
697+
698+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
699+
700+ if (v->index == 0)
701+ ret = 0;
702+ else if (v->index == 1)
703+ ret = 0;
704+ else
705+ ret = -EINVAL;
706+
707+ return ret;
708+}
709+
710+static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
711+{
712+ struct airspy *s = video_drvdata(file);
713+ int ret;
714+
715+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
716+
717+ if (v->index == 0) {
718+ strlcpy(v->name, "AirSpy ADC", sizeof(v->name));
719+ v->type = V4L2_TUNER_ADC;
720+ v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
721+ v->rangelow = bands[0].rangelow;
722+ v->rangehigh = bands[0].rangehigh;
723+ ret = 0;
724+ } else if (v->index == 1) {
725+ strlcpy(v->name, "AirSpy RF", sizeof(v->name));
726+ v->type = V4L2_TUNER_RF;
727+ v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
728+ v->rangelow = bands_rf[0].rangelow;
729+ v->rangehigh = bands_rf[0].rangehigh;
730+ ret = 0;
731+ } else {
732+ ret = -EINVAL;
733+ }
734+
735+ return ret;
736+}
737+
738+static int airspy_g_frequency(struct file *file, void *priv,
739+ struct v4l2_frequency *f)
740+{
741+ struct airspy *s = video_drvdata(file);
742+ int ret = 0;
743+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
744+ __func__, f->tuner, f->type);
745+
746+ if (f->tuner == 0) {
747+ f->type = V4L2_TUNER_ADC;
748+ f->frequency = s->f_adc;
749+ ret = 0;
750+ } else if (f->tuner == 1) {
751+ f->type = V4L2_TUNER_RF;
752+ f->frequency = s->f_rf;
753+ } else {
754+ ret = -EINVAL;
755+ }
756+
757+ return ret;
758+}
759+
760+static int airspy_s_frequency(struct file *file, void *priv,
761+ const struct v4l2_frequency *f)
762+{
763+ struct airspy *s = video_drvdata(file);
764+ int ret;
765+ u8 buf[4];
766+
767+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
768+ __func__, f->tuner, f->type, f->frequency);
769+
770+ if (f->tuner == 0) {
771+ s->f_adc = clamp_t(unsigned int, f->frequency,
772+ bands[0].rangelow,
773+ bands[0].rangehigh);
774+ dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
775+ __func__, s->f_adc);
776+ ret = 0;
777+ } else if (f->tuner == 1) {
778+ s->f_rf = clamp_t(unsigned int, f->frequency,
779+ bands_rf[0].rangelow,
780+ bands_rf[0].rangehigh);
781+ dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
782+ __func__, s->f_rf);
783+ buf[0] = (s->f_rf >> 0) & 0xff;
784+ buf[1] = (s->f_rf >> 8) & 0xff;
785+ buf[2] = (s->f_rf >> 16) & 0xff;
786+ buf[3] = (s->f_rf >> 24) & 0xff;
787+ ret = airspy_ctrl_msg(s, CMD_SET_FREQ, 0, 0, buf, 4);
788+ } else {
789+ ret = -EINVAL;
790+ }
791+
792+ return ret;
793+}
794+
795+static int airspy_enum_freq_bands(struct file *file, void *priv,
796+ struct v4l2_frequency_band *band)
797+{
798+ struct airspy *s = video_drvdata(file);
799+ int ret;
800+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
801+ __func__, band->tuner, band->type, band->index);
802+
803+ if (band->tuner == 0) {
804+ if (band->index >= ARRAY_SIZE(bands)) {
805+ ret = -EINVAL;
806+ } else {
807+ *band = bands[band->index];
808+ ret = 0;
809+ }
810+ } else if (band->tuner == 1) {
811+ if (band->index >= ARRAY_SIZE(bands_rf)) {
812+ ret = -EINVAL;
813+ } else {
814+ *band = bands_rf[band->index];
815+ ret = 0;
816+ }
817+ } else {
818+ ret = -EINVAL;
819+ }
820+
821+ return ret;
822+}
823+
824+static const struct v4l2_ioctl_ops airspy_ioctl_ops = {
825+ .vidioc_querycap = airspy_querycap,
826+
827+ .vidioc_enum_fmt_sdr_cap = airspy_enum_fmt_sdr_cap,
828+ .vidioc_g_fmt_sdr_cap = airspy_g_fmt_sdr_cap,
829+ .vidioc_s_fmt_sdr_cap = airspy_s_fmt_sdr_cap,
830+ .vidioc_try_fmt_sdr_cap = airspy_try_fmt_sdr_cap,
831+
832+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
833+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
834+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
835+ .vidioc_querybuf = vb2_ioctl_querybuf,
836+ .vidioc_qbuf = vb2_ioctl_qbuf,
837+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
838+
839+ .vidioc_streamon = vb2_ioctl_streamon,
840+ .vidioc_streamoff = vb2_ioctl_streamoff,
841+
842+ .vidioc_g_tuner = airspy_g_tuner,
843+ .vidioc_s_tuner = airspy_s_tuner,
844+
845+ .vidioc_g_frequency = airspy_g_frequency,
846+ .vidioc_s_frequency = airspy_s_frequency,
847+ .vidioc_enum_freq_bands = airspy_enum_freq_bands,
848+
849+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
850+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
851+ .vidioc_log_status = v4l2_ctrl_log_status,
852+};
853+
854+static const struct v4l2_file_operations airspy_fops = {
855+ .owner = THIS_MODULE,
856+ .open = v4l2_fh_open,
857+ .release = vb2_fop_release,
858+ .read = vb2_fop_read,
859+ .poll = vb2_fop_poll,
860+ .mmap = vb2_fop_mmap,
861+ .unlocked_ioctl = video_ioctl2,
862+};
863+
864+static struct video_device airspy_template = {
865+ .name = "AirSpy SDR",
866+ .release = video_device_release_empty,
867+ .fops = &airspy_fops,
868+ .ioctl_ops = &airspy_ioctl_ops,
869+};
870+
871+static void airspy_video_release(struct v4l2_device *v)
872+{
873+ struct airspy *s = container_of(v, struct airspy, v4l2_dev);
874+
875+ v4l2_ctrl_handler_free(&s->hdl);
876+ v4l2_device_unregister(&s->v4l2_dev);
877+ kfree(s);
878+}
879+
880+static int airspy_set_lna_gain(struct airspy *s)
881+{
882+ int ret;
883+ u8 u8tmp;
884+
885+ dev_dbg(&s->udev->dev, "%s: lna auto=%d->%d val=%d->%d\n",
886+ __func__, s->lna_gain_auto->cur.val,
887+ s->lna_gain_auto->val, s->lna_gain->cur.val,
888+ s->lna_gain->val);
889+
890+ ret = airspy_ctrl_msg(s, CMD_SET_LNA_AGC, 0, s->lna_gain_auto->val,
891+ &u8tmp, 1);
892+ if (ret)
893+ goto err;
894+
895+ if (s->lna_gain_auto->val == false) {
896+ ret = airspy_ctrl_msg(s, CMD_SET_LNA_GAIN, 0, s->lna_gain->val,
897+ &u8tmp, 1);
898+ if (ret)
899+ goto err;
900+ }
901+err:
902+ if (ret)
903+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
904+
905+ return ret;
906+}
907+
908+static int airspy_set_mixer_gain(struct airspy *s)
909+{
910+ int ret;
911+ u8 u8tmp;
912+
913+ dev_dbg(&s->udev->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
914+ __func__, s->mixer_gain_auto->cur.val,
915+ s->mixer_gain_auto->val, s->mixer_gain->cur.val,
916+ s->mixer_gain->val);
917+
918+ ret = airspy_ctrl_msg(s, CMD_SET_MIXER_AGC, 0, s->mixer_gain_auto->val,
919+ &u8tmp, 1);
920+ if (ret)
921+ goto err;
922+
923+ if (s->mixer_gain_auto->val == false) {
924+ ret = airspy_ctrl_msg(s, CMD_SET_MIXER_GAIN, 0,
925+ s->mixer_gain->val, &u8tmp, 1);
926+ if (ret)
927+ goto err;
928+ }
929+err:
930+ if (ret)
931+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
932+
933+ return ret;
934+}
935+
936+static int airspy_set_if_gain(struct airspy *s)
937+{
938+ int ret;
939+ u8 u8tmp;
940+
941+ dev_dbg(&s->udev->dev, "%s: val=%d->%d\n",
942+ __func__, s->if_gain->cur.val, s->if_gain->val);
943+
944+ ret = airspy_ctrl_msg(s, CMD_SET_VGA_GAIN, 0, s->if_gain->val,
945+ &u8tmp, 1);
946+ if (ret)
947+ goto err;
948+err:
949+ if (ret)
950+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
951+
952+ return ret;
953+}
954+
955+static int airspy_s_ctrl(struct v4l2_ctrl *ctrl)
956+{
957+ struct airspy *s = container_of(ctrl->handler, struct airspy, hdl);
958+ int ret;
959+
960+ switch (ctrl->id) {
961+ case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:
962+ case V4L2_CID_RF_TUNER_LNA_GAIN:
963+ ret = airspy_set_lna_gain(s);
964+ break;
965+ case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:
966+ case V4L2_CID_RF_TUNER_MIXER_GAIN:
967+ ret = airspy_set_mixer_gain(s);
968+ break;
969+ case V4L2_CID_RF_TUNER_IF_GAIN:
970+ ret = airspy_set_if_gain(s);
971+ break;
972+ default:
973+ dev_dbg(&s->udev->dev, "%s: unknown ctrl: id=%d name=%s\n",
974+ __func__, ctrl->id, ctrl->name);
975+ ret = -EINVAL;
976+ }
977+
978+ return ret;
979+}
980+
981+static const struct v4l2_ctrl_ops airspy_ctrl_ops = {
982+ .s_ctrl = airspy_s_ctrl,
983+};
984+
985+static int airspy_probe(struct usb_interface *intf,
986+ const struct usb_device_id *id)
987+{
988+ struct usb_device *udev = interface_to_usbdev(intf);
989+ struct airspy *s = NULL;
990+ int ret;
991+ u8 u8tmp, buf[BUF_SIZE];
992+
993+ s = kzalloc(sizeof(struct airspy), GFP_KERNEL);
994+ if (s == NULL) {
995+ dev_err(&udev->dev,
996+ "Could not allocate memory for airspy state\n");
997+ return -ENOMEM;
998+ }
999+
1000+ mutex_init(&s->v4l2_lock);
1001+ mutex_init(&s->vb_queue_lock);
1002+ spin_lock_init(&s->queued_bufs_lock);
1003+ INIT_LIST_HEAD(&s->queued_bufs);
1004+ s->udev = udev;
1005+ s->f_adc = bands[0].rangelow;
1006+ s->f_rf = bands_rf[0].rangelow;
1007+ s->pixelformat = V4L2_SDR_FMT_RU12LE;
1008+
1009+ /* Detect device */
1010+ ret = airspy_ctrl_msg(s, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
1011+ if (ret == 0)
1012+ ret = airspy_ctrl_msg(s, CMD_VERSION_STRING_READ, 0, 0,
1013+ buf, BUF_SIZE);
1014+ if (ret) {
1015+ dev_err(&s->udev->dev, "Could not detect board\n");
1016+ goto err_free_mem;
1017+ }
1018+
1019+ buf[BUF_SIZE - 1] = '\0';
1020+
1021+ dev_info(&s->udev->dev, "Board ID: %02x\n", u8tmp);
1022+ dev_info(&s->udev->dev, "Firmware version: %s\n", buf);
1023+
1024+ /* Init videobuf2 queue structure */
1025+ s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
1026+ s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1027+ s->vb_queue.drv_priv = s;
1028+ s->vb_queue.buf_struct_size = sizeof(struct airspy_frame_buf);
1029+ s->vb_queue.ops = &airspy_vb2_ops;
1030+ s->vb_queue.mem_ops = &vb2_vmalloc_memops;
1031+ s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1032+ ret = vb2_queue_init(&s->vb_queue);
1033+ if (ret) {
1034+ dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
1035+ goto err_free_mem;
1036+ }
1037+
1038+ /* Init video_device structure */
1039+ s->vdev = airspy_template;
1040+ s->vdev.queue = &s->vb_queue;
1041+ s->vdev.queue->lock = &s->vb_queue_lock;
1042+ set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
1043+ video_set_drvdata(&s->vdev, s);
1044+
1045+ /* Register the v4l2_device structure */
1046+ s->v4l2_dev.release = airspy_video_release;
1047+ ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
1048+ if (ret) {
1049+ dev_err(&s->udev->dev,
1050+ "Failed to register v4l2-device (%d)\n", ret);
1051+ goto err_free_mem;
1052+ }
1053+
1054+ /* Register controls */
1055+ v4l2_ctrl_handler_init(&s->hdl, 5);
1056+ s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
1057+ V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, 0, 1, 1, 0);
1058+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
1059+ V4L2_CID_RF_TUNER_LNA_GAIN, 0, 14, 1, 8);
1060+ v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
1061+ s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
1062+ V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, 0, 1, 1, 0);
1063+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
1064+ V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 15, 1, 8);
1065+ v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
1066+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
1067+ V4L2_CID_RF_TUNER_IF_GAIN, 0, 15, 1, 0);
1068+ if (s->hdl.error) {
1069+ ret = s->hdl.error;
1070+ dev_err(&s->udev->dev, "Could not initialize controls\n");
1071+ goto err_free_controls;
1072+ }
1073+
1074+ v4l2_ctrl_handler_setup(&s->hdl);
1075+
1076+ s->v4l2_dev.ctrl_handler = &s->hdl;
1077+ s->vdev.v4l2_dev = &s->v4l2_dev;
1078+ s->vdev.lock = &s->v4l2_lock;
1079+
1080+ ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
1081+ if (ret) {
1082+ dev_err(&s->udev->dev,
1083+ "Failed to register as video device (%d)\n",
1084+ ret);
1085+ goto err_unregister_v4l2_dev;
1086+ }
1087+ dev_info(&s->udev->dev, "Registered as %s\n",
1088+ video_device_node_name(&s->vdev));
1089+
1090+ return 0;
1091+
1092+err_free_controls:
1093+ v4l2_ctrl_handler_free(&s->hdl);
1094+err_unregister_v4l2_dev:
1095+ v4l2_device_unregister(&s->v4l2_dev);
1096+err_free_mem:
1097+ kfree(s);
1098+ return ret;
1099+}
1100+
1101+/* USB device ID list */
1102+static struct usb_device_id airspy_id_table[] = {
1103+ { USB_DEVICE(0x1d50, 0x60a1) }, /* AirSpy */
1104+ { }
1105+};
1106+MODULE_DEVICE_TABLE(usb, airspy_id_table);
1107+
1108+/* USB subsystem interface */
1109+static struct usb_driver airspy_driver = {
1110+ .name = KBUILD_MODNAME,
1111+ .probe = airspy_probe,
1112+ .disconnect = airspy_disconnect,
1113+ .id_table = airspy_id_table,
1114+};
1115+
1116+module_usb_driver(airspy_driver);
1117+
1118+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
1119+MODULE_DESCRIPTION("AirSpy SDR");
1120+MODULE_LICENSE("GPL");

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t