/*
* HackRF driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
/*
* Used Avago MGA-81563 RF amplifier could be destroyed pretty easily with too
* strong signal or transmitting to bad antenna.
* Set RF gain control to 'grabbed' state by default for sure.
*/
static bool hackrf_enable_rf_gain_ctrl;
module_param_named(enable_rf_gain_ctrl, hackrf_enable_rf_gain_ctrl, bool, 0644);
MODULE_PARM_DESC(enable_rf_gain_ctrl, "enable RX/TX RF amplifier control (warn: could damage amplifier)");
/* HackRF USB API commands (from HackRF Library) */
enum {
CMD_SET_TRANSCEIVER_MODE = 0x01,
CMD_SAMPLE_RATE_SET = 0x06,
CMD_BASEBAND_FILTER_BANDWIDTH_SET = 0x07,
CMD_BOARD_ID_READ = 0x0e,
CMD_VERSION_STRING_READ = 0x0f,
CMD_SET_FREQ = 0x10,
CMD_AMP_ENABLE = 0x11,
CMD_SET_LNA_GAIN = 0x13,
CMD_SET_VGA_GAIN = 0x14,
CMD_SET_TXVGA_GAIN = 0x15,
};
/*
* bEndpointAddress 0x81 EP 1 IN
* Transfer Type Bulk
* wMaxPacketSize 0x0200 1x 512 bytes
*/
#define MAX_BULK_BUFS (6)
#define BULK_BUFFER_SIZE (128 * 512)
static const struct v4l2_frequency_band bands_adc_dac[] = {
{
.tuner = 0,
.type = V4L2_TUNER_SDR,
.index = 0,
.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 200000,
.rangehigh = 24000000,
},
};
static const struct v4l2_frequency_band bands_rx_tx[] = {
{
.tuner = 1,
.type = V4L2_TUNER_RF,
.index = 0,
.capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 1,
.rangehigh = 4294967294LL, /* max u32, hw goes over 7GHz */
},
};
/* stream formats */
struct hackrf_format {
u32 pixelformat;
u32 buffersize;
};
/* format descriptions for capture and preview */
static struct hackrf_format formats[] = {
{
.pixelformat = V4L2_SDR_FMT_CS8,
.buffersize = BULK_BUFFER_SIZE,
},
};
static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
/* intermediate buffers with raw data from the USB device */
struct hackrf_buffer {
struct vb2_v4l2_buffer vb;
struct list_head list;
};
struct hackrf_dev {
#define USB_STATE_URB_BUF 1 /* XXX: set manually */
#define RX_ON 4
#define TX_ON 5
#define RX_ADC_FREQUENCY 11
#define TX_DAC_FREQUENCY 12
#define RX_BANDWIDTH 13
#define TX_BANDWIDTH 14
#define RX_RF_FREQUENCY 15
#define TX_RF_FREQUENCY 16
#define RX_RF_GAIN 17
#define TX_RF_GAIN 18
#define RX_IF_GAIN 19
#define RX_LNA_GAIN 20
#define TX_LNA_GAIN 21
unsigned long flags;
struct usb_interface *intf;
struct device *dev;
struct usb_device *udev;
struct video_device rx_vdev;
struct video_device tx_vdev;
struct v4l2_device v4l2_dev;
/* videobuf2 queue and queued buffers list */
struct vb2_queue rx_vb2_queue;
struct vb2_queue tx_vb2_queue;
struct list_head rx_buffer_list;
struct list_head tx_buffer_list;
spinlock_t buffer_list_lock; /* Protects buffer_list */
unsigned int sequence; /* Buffer sequence counter */
unsigned int vb_full; /* vb is full and packets dropped */
unsigned int vb_empty; /* vb is empty and packets dropped */
/* Note if taking both locks v4l2_lock must always be locked first! */
struct mutex v4l2_lock; /* Protects everything else */
struct mutex vb_queue_lock; /* Protects vb_queue */
struct urb *urb_list[MAX_BULK_BUFS];
int buf_num;
unsigned long buf_size;
u8 *buf_list[MAX_BULK_BUFS];
dma_addr_t dma_addr[MAX_BULK_BUFS];
int urbs_initialized;
int urbs_submitted;
/* USB control message buffer */
#define BUF_SIZE 24
u8 buf[BUF_SIZE];
/* Current configuration */
unsigned int f_adc;
unsigned int f_dac;
unsigned int f_rx;
unsigned int f_tx;
u32 pixelformat;
u32 buffersize;
/* Controls */
struct v4l2_ctrl_handler rx_ctrl_handler;
struct v4l2_ctrl *rx_bandwidth_auto;
struct v4l2_ctrl *rx_bandwidth;
struct v4l2_ctrl *rx_rf_gain;
struct v4l2_ctrl *rx_lna_gain;
struct v4l2_ctrl *rx_if_gain;
struct v4l2_ctrl_handler tx_ctrl_handler;
struct v4l2_ctrl *tx_bandwidth_auto;
struct v4l2_ctrl *tx_bandwidth;
struct v4l2_ctrl *tx_rf_gain;
struct v4l2_ctrl *tx_lna_gain;
/* Sample rate calc */
unsigned long jiffies_next;
unsigned int sample;
unsigned int sample_measured;
};
#define hackrf_dbg_usb_control_msg(_dev, _r, _t, _v, _i, _b, _l) { \
char *_direction; \
if (_t & USB_DIR_IN) \
_direction = "<<<"; \
else \
_direction = ">>>"; \
dev_dbg(_dev, "%02x %02x %02x %02x %02x %02x %02x %02x %s %*ph\n", \
_t, _r, _v & 0xff, _v >> 8, _i & 0xff, \
_i >> 8, _l & 0xff, _l >> 8, _direction, _l, _b); \
}
/* execute firmware command */
static int hackrf_ctrl_msg(struct hackrf_dev *dev, u8 request, u16
|