cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

radio-mr800.c (16793B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * A driver for the AverMedia MR 800 USB FM radio. This device plugs
      4 * into both the USB and an analog audio input, so this thing
      5 * only deals with initialization and frequency setting, the
      6 * audio data has to be handled by a sound driver.
      7 *
      8 * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com>
      9 */
     10
     11/*
     12 * Big thanks to authors and contributors of dsbr100.c and radio-si470x.c
     13 *
     14 * When work was looked pretty good, i discover this:
     15 * http://av-usbradio.sourceforge.net/index.php
     16 * http://sourceforge.net/projects/av-usbradio/
     17 * Latest release of theirs project was in 2005.
     18 * Probably, this driver could be improved through using their
     19 * achievements (specifications given).
     20 * Also, Faidon Liambotis <paravoid@debian.org> wrote nice driver for this radio
     21 * in 2007. He allowed to use his driver to improve current mr800 radio driver.
     22 * http://www.spinics.net/lists/linux-usb-devel/msg10109.html
     23 *
     24 * Version 0.01:	First working version.
     25 *			It's required to blacklist AverMedia USB Radio
     26 *			in usbhid/hid-quirks.c
     27 * Version 0.10:	A lot of cleanups and fixes: unpluging the device,
     28 *			few mutex locks were added, codinstyle issues, etc.
     29 *			Added stereo support. Thanks to
     30 *			Douglas Schilling Landgraf <dougsland@gmail.com> and
     31 *			David Ellingsworth <david@identd.dyndns.org>
     32 *			for discussion, help and support.
     33 * Version 0.11:	Converted to v4l2_device.
     34 *
     35 * Many things to do:
     36 *	- Correct power management of device (suspend & resume)
     37 *	- Add code for scanning and smooth tuning
     38 *	- Add code for sensitivity value
     39 *	- Correct mistakes
     40 *	- In Japan another FREQ_MIN and FREQ_MAX
     41 */
     42
     43/* kernel includes */
     44#include <linux/kernel.h>
     45#include <linux/module.h>
     46#include <linux/init.h>
     47#include <linux/slab.h>
     48#include <linux/input.h>
     49#include <linux/videodev2.h>
     50#include <media/v4l2-device.h>
     51#include <media/v4l2-ioctl.h>
     52#include <media/v4l2-ctrls.h>
     53#include <media/v4l2-event.h>
     54#include <linux/usb.h>
     55#include <linux/mutex.h>
     56
     57/* driver and module definitions */
     58#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
     59#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
     60#define DRIVER_VERSION "0.1.2"
     61
     62MODULE_AUTHOR(DRIVER_AUTHOR);
     63MODULE_DESCRIPTION(DRIVER_DESC);
     64MODULE_LICENSE("GPL");
     65MODULE_VERSION(DRIVER_VERSION);
     66
     67#define USB_AMRADIO_VENDOR 0x07ca
     68#define USB_AMRADIO_PRODUCT 0xb800
     69
     70/* dev_warn macro with driver name */
     71#define MR800_DRIVER_NAME "radio-mr800"
     72#define amradio_dev_warn(dev, fmt, arg...)				\
     73		dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
     74
     75#define amradio_dev_err(dev, fmt, arg...) \
     76		dev_err(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
     77
     78/* Probably USB_TIMEOUT should be modified in module parameter */
     79#define BUFFER_LENGTH 8
     80#define USB_TIMEOUT 500
     81
     82/* Frequency limits in MHz -- these are European values.  For Japanese
     83devices, that would be 76 and 91.  */
     84#define FREQ_MIN  87.5
     85#define FREQ_MAX 108.0
     86#define FREQ_MUL 16000
     87
     88/*
     89 * Commands that device should understand
     90 * List isn't full and will be updated with implementation of new functions
     91 */
     92#define AMRADIO_SET_FREQ	0xa4
     93#define AMRADIO_GET_READY_FLAG	0xa5
     94#define AMRADIO_GET_SIGNAL	0xa7
     95#define AMRADIO_GET_FREQ	0xa8
     96#define AMRADIO_SET_SEARCH_UP	0xa9
     97#define AMRADIO_SET_SEARCH_DOWN	0xaa
     98#define AMRADIO_SET_MUTE	0xab
     99#define AMRADIO_SET_RIGHT_MUTE	0xac
    100#define AMRADIO_SET_LEFT_MUTE	0xad
    101#define AMRADIO_SET_MONO	0xae
    102#define AMRADIO_SET_SEARCH_LVL	0xb0
    103#define AMRADIO_STOP_SEARCH	0xb1
    104
    105/* Comfortable defines for amradio_set_stereo */
    106#define WANT_STEREO		0x00
    107#define WANT_MONO		0x01
    108
    109/* module parameter */
    110static int radio_nr = -1;
    111module_param(radio_nr, int, 0);
    112MODULE_PARM_DESC(radio_nr, "Radio Nr");
    113
    114/* Data for one (physical) device */
    115struct amradio_device {
    116	/* reference to USB and video device */
    117	struct usb_device *usbdev;
    118	struct usb_interface *intf;
    119	struct video_device vdev;
    120	struct v4l2_device v4l2_dev;
    121	struct v4l2_ctrl_handler hdl;
    122
    123	u8 *buffer;
    124	struct mutex lock;	/* buffer locking */
    125	int curfreq;
    126	int stereo;
    127	int muted;
    128};
    129
    130static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev)
    131{
    132	return container_of(v4l2_dev, struct amradio_device, v4l2_dev);
    133}
    134
    135static int amradio_send_cmd(struct amradio_device *radio, u8 cmd, u8 arg,
    136		u8 *extra, u8 extralen, bool reply)
    137{
    138	int retval;
    139	int size;
    140
    141	radio->buffer[0] = 0x00;
    142	radio->buffer[1] = 0x55;
    143	radio->buffer[2] = 0xaa;
    144	radio->buffer[3] = extralen;
    145	radio->buffer[4] = cmd;
    146	radio->buffer[5] = arg;
    147	radio->buffer[6] = 0x00;
    148	radio->buffer[7] = extra || reply ? 8 : 0;
    149
    150	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
    151		radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT);
    152
    153	if (retval < 0 || size != BUFFER_LENGTH) {
    154		if (video_is_registered(&radio->vdev))
    155			amradio_dev_warn(&radio->vdev.dev,
    156					"cmd %02x failed\n", cmd);
    157		return retval ? retval : -EIO;
    158	}
    159	if (!extra && !reply)
    160		return 0;
    161
    162	if (extra) {
    163		memcpy(radio->buffer, extra, extralen);
    164		memset(radio->buffer + extralen, 0, 8 - extralen);
    165		retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
    166			radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT);
    167	} else {
    168		memset(radio->buffer, 0, 8);
    169		retval = usb_bulk_msg(radio->usbdev, usb_rcvbulkpipe(radio->usbdev, 0x81),
    170			radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT);
    171	}
    172	if (retval == 0 && size == BUFFER_LENGTH)
    173		return 0;
    174	if (video_is_registered(&radio->vdev) && cmd != AMRADIO_GET_READY_FLAG)
    175		amradio_dev_warn(&radio->vdev.dev, "follow-up to cmd %02x failed\n", cmd);
    176	return retval ? retval : -EIO;
    177}
    178
    179/* switch on/off the radio. Send 8 bytes to device */
    180static int amradio_set_mute(struct amradio_device *radio, bool mute)
    181{
    182	int ret = amradio_send_cmd(radio,
    183			AMRADIO_SET_MUTE, mute, NULL, 0, false);
    184
    185	if (!ret)
    186		radio->muted = mute;
    187	return ret;
    188}
    189
    190/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
    191static int amradio_set_freq(struct amradio_device *radio, int freq)
    192{
    193	unsigned short freq_send;
    194	u8 buf[3];
    195	int retval;
    196
    197	/* we need to be sure that frequency isn't out of range */
    198	freq = clamp_t(unsigned, freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
    199	freq_send = 0x10 + (freq >> 3) / 25;
    200
    201	/* frequency is calculated from freq_send and placed in first 2 bytes */
    202	buf[0] = (freq_send >> 8) & 0xff;
    203	buf[1] = freq_send & 0xff;
    204	buf[2] = 0x01;
    205
    206	retval = amradio_send_cmd(radio, AMRADIO_SET_FREQ, 0, buf, 3, false);
    207	if (retval)
    208		return retval;
    209	radio->curfreq = freq;
    210	msleep(40);
    211	return 0;
    212}
    213
    214static int amradio_set_stereo(struct amradio_device *radio, bool stereo)
    215{
    216	int ret = amradio_send_cmd(radio,
    217			AMRADIO_SET_MONO, !stereo, NULL, 0, false);
    218
    219	if (!ret)
    220		radio->stereo = stereo;
    221	return ret;
    222}
    223
    224static int amradio_get_stat(struct amradio_device *radio, bool *is_stereo, u32 *signal)
    225{
    226	int ret = amradio_send_cmd(radio,
    227			AMRADIO_GET_SIGNAL, 0, NULL, 0, true);
    228
    229	if (ret)
    230		return ret;
    231	*is_stereo = radio->buffer[2] >> 7;
    232	*signal = (radio->buffer[3] & 0xf0) << 8;
    233	return 0;
    234}
    235
    236/* Handle unplugging the device.
    237 * We call video_unregister_device in any case.
    238 * The last function called in this procedure is
    239 * usb_amradio_device_release.
    240 */
    241static void usb_amradio_disconnect(struct usb_interface *intf)
    242{
    243	struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
    244
    245	mutex_lock(&radio->lock);
    246	video_unregister_device(&radio->vdev);
    247	amradio_set_mute(radio, true);
    248	usb_set_intfdata(intf, NULL);
    249	v4l2_device_disconnect(&radio->v4l2_dev);
    250	mutex_unlock(&radio->lock);
    251	v4l2_device_put(&radio->v4l2_dev);
    252}
    253
    254/* vidioc_querycap - query device capabilities */
    255static int vidioc_querycap(struct file *file, void *priv,
    256					struct v4l2_capability *v)
    257{
    258	struct amradio_device *radio = video_drvdata(file);
    259
    260	strscpy(v->driver, "radio-mr800", sizeof(v->driver));
    261	strscpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
    262	usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
    263	return 0;
    264}
    265
    266/* vidioc_g_tuner - get tuner attributes */
    267static int vidioc_g_tuner(struct file *file, void *priv,
    268				struct v4l2_tuner *v)
    269{
    270	struct amradio_device *radio = video_drvdata(file);
    271	bool is_stereo = false;
    272	int retval;
    273
    274	if (v->index > 0)
    275		return -EINVAL;
    276
    277	v->signal = 0;
    278	retval = amradio_get_stat(radio, &is_stereo, &v->signal);
    279	if (retval)
    280		return retval;
    281
    282	strscpy(v->name, "FM", sizeof(v->name));
    283	v->type = V4L2_TUNER_RADIO;
    284	v->rangelow = FREQ_MIN * FREQ_MUL;
    285	v->rangehigh = FREQ_MAX * FREQ_MUL;
    286	v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
    287		V4L2_TUNER_CAP_HWSEEK_WRAP;
    288	v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
    289	v->audmode = radio->stereo ?
    290		V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
    291	return 0;
    292}
    293
    294/* vidioc_s_tuner - set tuner attributes */
    295static int vidioc_s_tuner(struct file *file, void *priv,
    296				const struct v4l2_tuner *v)
    297{
    298	struct amradio_device *radio = video_drvdata(file);
    299
    300	if (v->index > 0)
    301		return -EINVAL;
    302
    303	/* mono/stereo selector */
    304	switch (v->audmode) {
    305	case V4L2_TUNER_MODE_MONO:
    306		return amradio_set_stereo(radio, WANT_MONO);
    307	default:
    308		return amradio_set_stereo(radio, WANT_STEREO);
    309	}
    310}
    311
    312/* vidioc_s_frequency - set tuner radio frequency */
    313static int vidioc_s_frequency(struct file *file, void *priv,
    314				const struct v4l2_frequency *f)
    315{
    316	struct amradio_device *radio = video_drvdata(file);
    317
    318	if (f->tuner != 0)
    319		return -EINVAL;
    320	return amradio_set_freq(radio, f->frequency);
    321}
    322
    323/* vidioc_g_frequency - get tuner radio frequency */
    324static int vidioc_g_frequency(struct file *file, void *priv,
    325				struct v4l2_frequency *f)
    326{
    327	struct amradio_device *radio = video_drvdata(file);
    328
    329	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
    330		return -EINVAL;
    331	f->type = V4L2_TUNER_RADIO;
    332	f->frequency = radio->curfreq;
    333
    334	return 0;
    335}
    336
    337static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
    338		const struct v4l2_hw_freq_seek *seek)
    339{
    340	static u8 buf[8] = {
    341		0x3d, 0x32, 0x0f, 0x08, 0x3d, 0x32, 0x0f, 0x08
    342	};
    343	struct amradio_device *radio = video_drvdata(file);
    344	unsigned long timeout;
    345	int retval;
    346
    347	if (seek->tuner != 0 || !seek->wrap_around)
    348		return -EINVAL;
    349
    350	if (file->f_flags & O_NONBLOCK)
    351		return -EWOULDBLOCK;
    352
    353	retval = amradio_send_cmd(radio,
    354			AMRADIO_SET_SEARCH_LVL, 0, buf, 8, false);
    355	if (retval)
    356		return retval;
    357	amradio_set_freq(radio, radio->curfreq);
    358	retval = amradio_send_cmd(radio,
    359		seek->seek_upward ? AMRADIO_SET_SEARCH_UP : AMRADIO_SET_SEARCH_DOWN,
    360		0, NULL, 0, false);
    361	if (retval)
    362		return retval;
    363	timeout = jiffies + msecs_to_jiffies(30000);
    364	for (;;) {
    365		if (time_after(jiffies, timeout)) {
    366			retval = -ENODATA;
    367			break;
    368		}
    369		if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
    370			retval = -ERESTARTSYS;
    371			break;
    372		}
    373		retval = amradio_send_cmd(radio, AMRADIO_GET_READY_FLAG,
    374				0, NULL, 0, true);
    375		if (retval)
    376			continue;
    377		amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true);
    378		if (radio->buffer[1] || radio->buffer[2]) {
    379			/* To check: sometimes radio->curfreq is set to out of range value */
    380			radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2];
    381			radio->curfreq = (radio->curfreq - 0x10) * 200;
    382			amradio_send_cmd(radio, AMRADIO_STOP_SEARCH,
    383					0, NULL, 0, false);
    384			amradio_set_freq(radio, radio->curfreq);
    385			retval = 0;
    386			break;
    387		}
    388	}
    389	amradio_send_cmd(radio, AMRADIO_STOP_SEARCH, 0, NULL, 0, false);
    390	amradio_set_freq(radio, radio->curfreq);
    391	return retval;
    392}
    393
    394static int usb_amradio_s_ctrl(struct v4l2_ctrl *ctrl)
    395{
    396	struct amradio_device *radio =
    397		container_of(ctrl->handler, struct amradio_device, hdl);
    398
    399	switch (ctrl->id) {
    400	case V4L2_CID_AUDIO_MUTE:
    401		return amradio_set_mute(radio, ctrl->val);
    402	}
    403
    404	return -EINVAL;
    405}
    406
    407static int usb_amradio_init(struct amradio_device *radio)
    408{
    409	int retval;
    410
    411	retval = amradio_set_mute(radio, true);
    412	if (retval)
    413		goto out_err;
    414	retval = amradio_set_stereo(radio, true);
    415	if (retval)
    416		goto out_err;
    417	retval = amradio_set_freq(radio, radio->curfreq);
    418	if (retval)
    419		goto out_err;
    420	return 0;
    421
    422out_err:
    423	amradio_dev_err(&radio->vdev.dev, "initialization failed\n");
    424	return retval;
    425}
    426
    427/* Suspend device - stop device. Need to be checked and fixed */
    428static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
    429{
    430	struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
    431
    432	mutex_lock(&radio->lock);
    433	if (!radio->muted) {
    434		amradio_set_mute(radio, true);
    435		radio->muted = false;
    436	}
    437	mutex_unlock(&radio->lock);
    438
    439	dev_info(&intf->dev, "going into suspend..\n");
    440	return 0;
    441}
    442
    443/* Resume device - start device. Need to be checked and fixed */
    444static int usb_amradio_resume(struct usb_interface *intf)
    445{
    446	struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf));
    447
    448	mutex_lock(&radio->lock);
    449	amradio_set_stereo(radio, radio->stereo);
    450	amradio_set_freq(radio, radio->curfreq);
    451
    452	if (!radio->muted)
    453		amradio_set_mute(radio, false);
    454
    455	mutex_unlock(&radio->lock);
    456
    457	dev_info(&intf->dev, "coming out of suspend..\n");
    458	return 0;
    459}
    460
    461static const struct v4l2_ctrl_ops usb_amradio_ctrl_ops = {
    462	.s_ctrl = usb_amradio_s_ctrl,
    463};
    464
    465/* File system interface */
    466static const struct v4l2_file_operations usb_amradio_fops = {
    467	.owner		= THIS_MODULE,
    468	.open		= v4l2_fh_open,
    469	.release	= v4l2_fh_release,
    470	.poll		= v4l2_ctrl_poll,
    471	.unlocked_ioctl	= video_ioctl2,
    472};
    473
    474static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
    475	.vidioc_querycap    = vidioc_querycap,
    476	.vidioc_g_tuner     = vidioc_g_tuner,
    477	.vidioc_s_tuner     = vidioc_s_tuner,
    478	.vidioc_g_frequency = vidioc_g_frequency,
    479	.vidioc_s_frequency = vidioc_s_frequency,
    480	.vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
    481	.vidioc_log_status  = v4l2_ctrl_log_status,
    482	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
    483	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
    484};
    485
    486static void usb_amradio_release(struct v4l2_device *v4l2_dev)
    487{
    488	struct amradio_device *radio = to_amradio_dev(v4l2_dev);
    489
    490	/* free rest memory */
    491	v4l2_ctrl_handler_free(&radio->hdl);
    492	v4l2_device_unregister(&radio->v4l2_dev);
    493	kfree(radio->buffer);
    494	kfree(radio);
    495}
    496
    497/* check if the device is present and register with v4l and usb if it is */
    498static int usb_amradio_probe(struct usb_interface *intf,
    499				const struct usb_device_id *id)
    500{
    501	struct amradio_device *radio;
    502	int retval;
    503
    504	radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL);
    505
    506	if (!radio) {
    507		dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
    508		retval = -ENOMEM;
    509		goto err;
    510	}
    511
    512	radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
    513
    514	if (!radio->buffer) {
    515		dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
    516		retval = -ENOMEM;
    517		goto err_nobuf;
    518	}
    519
    520	retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
    521	if (retval < 0) {
    522		dev_err(&intf->dev, "couldn't register v4l2_device\n");
    523		goto err_v4l2;
    524	}
    525
    526	v4l2_ctrl_handler_init(&radio->hdl, 1);
    527	v4l2_ctrl_new_std(&radio->hdl, &usb_amradio_ctrl_ops,
    528			  V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
    529	if (radio->hdl.error) {
    530		retval = radio->hdl.error;
    531		dev_err(&intf->dev, "couldn't register control\n");
    532		goto err_ctrl;
    533	}
    534	mutex_init(&radio->lock);
    535
    536	radio->v4l2_dev.ctrl_handler = &radio->hdl;
    537	radio->v4l2_dev.release = usb_amradio_release;
    538	strscpy(radio->vdev.name, radio->v4l2_dev.name,
    539		sizeof(radio->vdev.name));
    540	radio->vdev.v4l2_dev = &radio->v4l2_dev;
    541	radio->vdev.fops = &usb_amradio_fops;
    542	radio->vdev.ioctl_ops = &usb_amradio_ioctl_ops;
    543	radio->vdev.release = video_device_release_empty;
    544	radio->vdev.lock = &radio->lock;
    545	radio->vdev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER |
    546				  V4L2_CAP_HW_FREQ_SEEK;
    547
    548	radio->usbdev = interface_to_usbdev(intf);
    549	radio->intf = intf;
    550	usb_set_intfdata(intf, &radio->v4l2_dev);
    551	radio->curfreq = 95.16 * FREQ_MUL;
    552
    553	video_set_drvdata(&radio->vdev, radio);
    554	retval = usb_amradio_init(radio);
    555	if (retval)
    556		goto err_vdev;
    557
    558	retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO,
    559					radio_nr);
    560	if (retval < 0) {
    561		dev_err(&intf->dev, "could not register video device\n");
    562		goto err_vdev;
    563	}
    564
    565	return 0;
    566
    567err_vdev:
    568	v4l2_ctrl_handler_free(&radio->hdl);
    569err_ctrl:
    570	v4l2_device_unregister(&radio->v4l2_dev);
    571err_v4l2:
    572	kfree(radio->buffer);
    573err_nobuf:
    574	kfree(radio);
    575err:
    576	return retval;
    577}
    578
    579/* USB Device ID List */
    580static const struct usb_device_id usb_amradio_device_table[] = {
    581	{ USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
    582							USB_CLASS_HID, 0, 0) },
    583	{ }						/* Terminating entry */
    584};
    585
    586MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
    587
    588/* USB subsystem interface */
    589static struct usb_driver usb_amradio_driver = {
    590	.name			= MR800_DRIVER_NAME,
    591	.probe			= usb_amradio_probe,
    592	.disconnect		= usb_amradio_disconnect,
    593	.suspend		= usb_amradio_suspend,
    594	.resume			= usb_amradio_resume,
    595	.reset_resume		= usb_amradio_resume,
    596	.id_table		= usb_amradio_device_table,
    597};
    598
    599module_usb_driver(usb_amradio_driver);