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