1 /*
2  * A driver for the AverMedia MR 800 USB FM radio. This device plugs
3  * into both the USB and an analog audio input, so this thing
4  * only deals with initialization and frequency setting, the
5  * audio data has to be handled by a sound driver.
6  *
7  * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 
24 /*
25  * Big thanks to authors of dsbr100.c and radio-si470x.c
26  *
27  * When work was looked pretty good, i discover this:
28  * http://av-usbradio.sourceforge.net/index.php
29  * http://sourceforge.net/projects/av-usbradio/
30  * Latest release of theirs project was in 2005.
31  * Probably, this driver could be improved trough using their
32  * achievements (specifications given).
33  * So, we have smth to begin with.
34  *
35  * History:
36  * Version 0.01:	First working version.
37  * 			It's required to blacklist AverMedia USB Radio
38  * 			in usbhid/hid-quirks.c
39  *
40  * Many things to do:
41  * 	- Correct power managment of device (suspend & resume)
42  * 	- Make x86 independance (little-endian and big-endian stuff)
43  * 	- Add code for scanning and smooth tuning
44  * 	- Checked and add stereo&mono stuff
45  * 	- Add code for sensitivity value
46  * 	- Correct mistakes
47  * 	- In Japan another FREQ_MIN and FREQ_MAX
48  */
49 
50 /* kernel includes */
51 #include <linux/kernel.h>
52 #include <linux/module.h>
53 #include <linux/init.h>
54 #include <linux/slab.h>
55 #include <linux/input.h>
56 #include <linux/videodev2.h>
57 #include <media/v4l2-common.h>
58 #include <media/v4l2-ioctl.h>
59 #include <linux/usb.h>
60 #include <linux/version.h>	/* for KERNEL_VERSION MACRO */
61 
62 /* driver and module definitions */
63 #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
64 #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
65 #define DRIVER_VERSION "0.01"
66 #define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
67 
68 MODULE_AUTHOR(DRIVER_AUTHOR);
69 MODULE_DESCRIPTION(DRIVER_DESC);
70 MODULE_LICENSE("GPL");
71 
72 #define USB_AMRADIO_VENDOR 0x07ca
73 #define USB_AMRADIO_PRODUCT 0xb800
74 
75 /* Probably USB_TIMEOUT should be modified in module parameter */
76 #define BUFFER_LENGTH 8
77 #define USB_TIMEOUT 500
78 
79 /* Frequency limits in MHz -- these are European values.  For Japanese
80 devices, that would be 76 and 91.  */
81 #define FREQ_MIN  87.5
82 #define FREQ_MAX 108.0
83 #define FREQ_MUL 16000
84 
85 /* module parameter */
86 static int radio_nr = -1;
87 module_param(radio_nr, int, 0);
88 MODULE_PARM_DESC(radio_nr, "Radio Nr");
89 
90 static struct v4l2_queryctrl radio_qctrl[] = {
91 	{
92 		.id            = V4L2_CID_AUDIO_MUTE,
93 		.name          = "Mute",
94 		.minimum       = 0,
95 		.maximum       = 1,
96 		.step	       = 1,
97 		.default_value = 1,
98 		.type          = V4L2_CTRL_TYPE_BOOLEAN,
99 	},
100 /* HINT: the disabled controls are only here to satify kradio and such apps */
101 	{	.id		= V4L2_CID_AUDIO_VOLUME,
102 		.flags		= V4L2_CTRL_FLAG_DISABLED,
103 	},
104 	{
105 		.id		= V4L2_CID_AUDIO_BALANCE,
106 		.flags		= V4L2_CTRL_FLAG_DISABLED,
107 	},
108 	{
109 		.id		= V4L2_CID_AUDIO_BASS,
110 		.flags		= V4L2_CTRL_FLAG_DISABLED,
111 	},
112 	{
113 		.id		= V4L2_CID_AUDIO_TREBLE,
114 		.flags		= V4L2_CTRL_FLAG_DISABLED,
115 	},
116 	{
117 		.id		= V4L2_CID_AUDIO_LOUDNESS,
118 		.flags		= V4L2_CTRL_FLAG_DISABLED,
119 	},
120 };
121 
122 static int usb_amradio_probe(struct usb_interface *intf,
123 			     const struct usb_device_id *id);
124 static void usb_amradio_disconnect(struct usb_interface *intf);
125 static int usb_amradio_open(struct inode *inode, struct file *file);
126 static int usb_amradio_close(struct inode *inode, struct file *file);
127 static int usb_amradio_suspend(struct usb_interface *intf,
128 				pm_message_t message);
129 static int usb_amradio_resume(struct usb_interface *intf);
130 
131 /* Data for one (physical) device */
132 struct amradio_device {
133 	/* reference to USB and video device */
134 	struct usb_device *usbdev;
135 	struct video_device *videodev;
136 
137 	unsigned char *buffer;
138 	struct mutex lock;	/* buffer locking */
139 	int curfreq;
140 	int stereo;
141 	int users;
142 	int removed;
143 	int muted;
144 };
145 
146 /* USB Device ID List */
147 static struct usb_device_id usb_amradio_device_table[] = {
148 	{USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
149 							USB_CLASS_HID, 0, 0) },
150 	{ }						/* Terminating entry */
151 };
152 
153 MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
154 
155 /* USB subsystem interface */
156 static struct usb_driver usb_amradio_driver = {
157 	.name			= "radio-mr800",
158 	.probe			= usb_amradio_probe,
159 	.disconnect		= usb_amradio_disconnect,
160 	.suspend		= usb_amradio_suspend,
161 	.resume			= usb_amradio_resume,
162 	.reset_resume		= usb_amradio_resume,
163 	.id_table		= usb_amradio_device_table,
164 	.supports_autosuspend	= 1,
165 };
166 
167 /* switch on radio. Send 8 bytes to device. */
168 static int amradio_start(struct amradio_device *radio)
169 {
170 	int retval;
171 	int size;
172 
173 	mutex_lock(&radio->lock);
174 
175 	radio->buffer[0] = 0x00;
176 	radio->buffer[1] = 0x55;
177 	radio->buffer[2] = 0xaa;
178 	radio->buffer[3] = 0x00;
179 	radio->buffer[4] = 0xab;
180 	radio->buffer[5] = 0x00;
181 	radio->buffer[6] = 0x00;
182 	radio->buffer[7] = 0x00;
183 
184 	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
185 		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
186 
187 	if (retval) {
188 		mutex_unlock(&radio->lock);
189 		return retval;
190 	}
191 
192 	mutex_unlock(&radio->lock);
193 
194 	radio->muted = 0;
195 
196 	return retval;
197 }
198 
199 /* switch off radio */
200 static int amradio_stop(struct amradio_device *radio)
201 {
202 	int retval;
203 	int size;
204 
205 	mutex_lock(&radio->lock);
206 
207 	radio->buffer[0] = 0x00;
208 	radio->buffer[1] = 0x55;
209 	radio->buffer[2] = 0xaa;
210 	radio->buffer[3] = 0x00;
211 	radio->buffer[4] = 0xab;
212 	radio->buffer[5] = 0x01;
213 	radio->buffer[6] = 0x00;
214 	radio->buffer[7] = 0x00;
215 
216 	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
217 		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
218 
219 	if (retval) {
220 		mutex_unlock(&radio->lock);
221 		return retval;
222 	}
223 
224 	mutex_unlock(&radio->lock);
225 
226 	radio->muted = 1;
227 
228 	return retval;
229 }
230 
231 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
232 static int amradio_setfreq(struct amradio_device *radio, int freq)
233 {
234 	int retval;
235 	int size;
236 	unsigned short freq_send = 0x13 + (freq >> 3) / 25;
237 
238 	mutex_lock(&radio->lock);
239 
240 	radio->buffer[0] = 0x00;
241 	radio->buffer[1] = 0x55;
242 	radio->buffer[2] = 0xaa;
243 	radio->buffer[3] = 0x03;
244 	radio->buffer[4] = 0xa4;
245 	radio->buffer[5] = 0x00;
246 	radio->buffer[6] = 0x00;
247 	radio->buffer[7] = 0x08;
248 
249 	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
250 		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
251 
252 	if (retval) {
253 		mutex_unlock(&radio->lock);
254 		return retval;
255 	}
256 
257 	/* frequency is calculated from freq_send and placed in first 2 bytes */
258 	radio->buffer[0] = (freq_send >> 8) & 0xff;
259 	radio->buffer[1] = freq_send & 0xff;
260 	radio->buffer[2] = 0x01;
261 	radio->buffer[3] = 0x00;
262 	radio->buffer[4] = 0x00;
263 	/* 5 and 6 bytes of buffer already = 0x00 */
264 	radio->buffer[7] = 0x00;
265 
266 	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
267 		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
268 
269 	if (retval) {
270 		mutex_unlock(&radio->lock);
271 		return retval;
272 	}
273 
274 	mutex_unlock(&radio->lock);
275 
276 	radio->stereo = 0;
277 
278 	return retval;
279 }
280 
281 /* USB subsystem interface begins here */
282 
283 /* handle unplugging of the device, release data structures
284 if nothing keeps us from doing it.  If something is still
285 keeping us busy, the release callback of v4l will take care
286 of releasing it. */
287 static void usb_amradio_disconnect(struct usb_interface *intf)
288 {
289 	struct amradio_device *radio = usb_get_intfdata(intf);
290 
291 	usb_set_intfdata(intf, NULL);
292 
293 	if (radio) {
294 		video_unregister_device(radio->videodev);
295 		radio->videodev = NULL;
296 		if (radio->users) {
297 			kfree(radio->buffer);
298 			kfree(radio);
299 		} else {
300 			radio->removed = 1;
301 		}
302 	}
303 }
304 
305 /* vidioc_querycap - query device capabilities */
306 static int vidioc_querycap(struct file *file, void *priv,
307 					struct v4l2_capability *v)
308 {
309 	strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
310 	strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
311 	sprintf(v->bus_info, "USB");
312 	v->version = RADIO_VERSION;
313 	v->capabilities = V4L2_CAP_TUNER;
314 	return 0;
315 }
316 
317 /* vidioc_g_tuner - get tuner attributes */
318 static int vidioc_g_tuner(struct file *file, void *priv,
319 				struct v4l2_tuner *v)
320 {
321 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
322 
323 	if (v->index > 0)
324 		return -EINVAL;
325 
326 /* TODO: Add function which look is signal stereo or not
327  * 	amradio_getstat(radio);
328  */
329 	radio->stereo = -1;
330 	strcpy(v->name, "FM");
331 	v->type = V4L2_TUNER_RADIO;
332 	v->rangelow = FREQ_MIN * FREQ_MUL;
333 	v->rangehigh = FREQ_MAX * FREQ_MUL;
334 	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
335 	v->capability = V4L2_TUNER_CAP_LOW;
336 	if (radio->stereo)
337 		v->audmode = V4L2_TUNER_MODE_STEREO;
338 	else
339 		v->audmode = V4L2_TUNER_MODE_MONO;
340 	v->signal = 0xffff;     /* Can't get the signal strength, sad.. */
341 	v->afc = 0; /* Don't know what is this */
342 	return 0;
343 }
344 
345 /* vidioc_s_tuner - set tuner attributes */
346 static int vidioc_s_tuner(struct file *file, void *priv,
347 				struct v4l2_tuner *v)
348 {
349 	if (v->index > 0)
350 		return -EINVAL;
351 	return 0;
352 }
353 
354 /* vidioc_s_frequency - set tuner radio frequency */
355 static int vidioc_s_frequency(struct file *file, void *priv,
356 				struct v4l2_frequency *f)
357 {
358 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
359 
360 	radio->curfreq = f->frequency;
361 	if (amradio_setfreq(radio, radio->curfreq) < 0)
362 		warn("Set frequency failed");
363 	return 0;
364 }
365 
366 /* vidioc_g_frequency - get tuner radio frequency */
367 static int vidioc_g_frequency(struct file *file, void *priv,
368 				struct v4l2_frequency *f)
369 {
370 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
371 
372 	f->type = V4L2_TUNER_RADIO;
373 	f->frequency = radio->curfreq;
374 	return 0;
375 }
376 
377 /* vidioc_queryctrl - enumerate control items */
378 static int vidioc_queryctrl(struct file *file, void *priv,
379 				struct v4l2_queryctrl *qc)
380 {
381 	int i;
382 
383 	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
384 		if (qc->id && qc->id == radio_qctrl[i].id) {
385 			memcpy(qc, &(radio_qctrl[i]),
386 						sizeof(*qc));
387 			return 0;
388 		}
389 	}
390 	return -EINVAL;
391 }
392 
393 /* vidioc_g_ctrl - get the value of a control */
394 static int vidioc_g_ctrl(struct file *file, void *priv,
395 				struct v4l2_control *ctrl)
396 {
397 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
398 
399 	switch (ctrl->id) {
400 	case V4L2_CID_AUDIO_MUTE:
401 		ctrl->value = radio->muted;
402 		return 0;
403 	}
404 	return -EINVAL;
405 }
406 
407 /* vidioc_s_ctrl - set the value of a control */
408 static int vidioc_s_ctrl(struct file *file, void *priv,
409 				struct v4l2_control *ctrl)
410 {
411 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
412 
413 	switch (ctrl->id) {
414 	case V4L2_CID_AUDIO_MUTE:
415 		if (ctrl->value) {
416 			if (amradio_stop(radio) < 0) {
417 				warn("amradio_stop() failed");
418 				return -1;
419 			}
420 		} else {
421 			if (amradio_start(radio) < 0) {
422 				warn("amradio_start() failed");
423 				return -1;
424 			}
425 		}
426 		return 0;
427 	}
428 	return -EINVAL;
429 }
430 
431 /* vidioc_g_audio - get audio attributes */
432 static int vidioc_g_audio(struct file *file, void *priv,
433 				struct v4l2_audio *a)
434 {
435 	if (a->index > 1)
436 		return -EINVAL;
437 
438 	strcpy(a->name, "Radio");
439 	a->capability = V4L2_AUDCAP_STEREO;
440 	return 0;
441 }
442 
443 /* vidioc_s_audio - set audio attributes  */
444 static int vidioc_s_audio(struct file *file, void *priv,
445 					struct v4l2_audio *a)
446 {
447 	if (a->index != 0)
448 		return -EINVAL;
449 	return 0;
450 }
451 
452 /* vidioc_g_input - get input */
453 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
454 {
455 	*i = 0;
456 	return 0;
457 }
458 
459 /* vidioc_s_input - set input */
460 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
461 {
462 	if (i != 0)
463 		return -EINVAL;
464 	return 0;
465 }
466 
467 /* open device - amradio_start() and amradio_setfreq() */
468 static int usb_amradio_open(struct inode *inode, struct file *file)
469 {
470 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
471 
472 	lock_kernel();
473 
474 	radio->users = 1;
475 	radio->muted = 1;
476 
477 	if (amradio_start(radio) < 0) {
478 		warn("Radio did not start up properly");
479 		radio->users = 0;
480 		unlock_kernel();
481 		return -EIO;
482 	}
483 	if (amradio_setfreq(radio, radio->curfreq) < 0)
484 		warn("Set frequency failed");
485 
486 	unlock_kernel();
487 	return 0;
488 }
489 
490 /*close device - free driver structures */
491 static int usb_amradio_close(struct inode *inode, struct file *file)
492 {
493 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
494 
495 	if (!radio)
496 		return -ENODEV;
497 	radio->users = 0;
498 	if (radio->removed) {
499 		kfree(radio->buffer);
500 		kfree(radio);
501 	}
502 	return 0;
503 }
504 
505 /* Suspend device - stop device. Need to be checked and fixed */
506 static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
507 {
508 	struct amradio_device *radio = usb_get_intfdata(intf);
509 
510 	if (amradio_stop(radio) < 0)
511 		warn("amradio_stop() failed");
512 
513 	info("radio-mr800: Going into suspend..");
514 
515 	return 0;
516 }
517 
518 /* Resume device - start device. Need to be checked and fixed */
519 static int usb_amradio_resume(struct usb_interface *intf)
520 {
521 	struct amradio_device *radio = usb_get_intfdata(intf);
522 
523 	if (amradio_start(radio) < 0)
524 		warn("amradio_start() failed");
525 
526 	info("radio-mr800: Coming out of suspend..");
527 
528 	return 0;
529 }
530 
531 /* File system interface */
532 static const struct file_operations usb_amradio_fops = {
533 	.owner		= THIS_MODULE,
534 	.open		= usb_amradio_open,
535 	.release	= usb_amradio_close,
536 	.ioctl		= video_ioctl2,
537 #ifdef CONFIG_COMPAT
538 	.compat_ioctl	= v4l_compat_ioctl32,
539 #endif
540 	.llseek		= no_llseek,
541 };
542 
543 static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
544 	.vidioc_querycap    = vidioc_querycap,
545 	.vidioc_g_tuner     = vidioc_g_tuner,
546 	.vidioc_s_tuner     = vidioc_s_tuner,
547 	.vidioc_g_frequency = vidioc_g_frequency,
548 	.vidioc_s_frequency = vidioc_s_frequency,
549 	.vidioc_queryctrl   = vidioc_queryctrl,
550 	.vidioc_g_ctrl      = vidioc_g_ctrl,
551 	.vidioc_s_ctrl      = vidioc_s_ctrl,
552 	.vidioc_g_audio     = vidioc_g_audio,
553 	.vidioc_s_audio     = vidioc_s_audio,
554 	.vidioc_g_input     = vidioc_g_input,
555 	.vidioc_s_input     = vidioc_s_input,
556 };
557 
558 /* V4L2 interface */
559 static struct video_device amradio_videodev_template = {
560 	.name		= "AverMedia MR 800 USB FM Radio",
561 	.fops		= &usb_amradio_fops,
562 	.ioctl_ops 	= &usb_amradio_ioctl_ops,
563 	.release	= video_device_release,
564 };
565 
566 /* check if the device is present and register with v4l and
567 usb if it is */
568 static int usb_amradio_probe(struct usb_interface *intf,
569 				const struct usb_device_id *id)
570 {
571 	struct amradio_device *radio;
572 
573 	radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL);
574 
575 	if (!(radio))
576 		return -ENOMEM;
577 
578 	radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
579 
580 	if (!(radio->buffer)) {
581 		kfree(radio);
582 		return -ENOMEM;
583 	}
584 
585 	radio->videodev = video_device_alloc();
586 
587 	if (!(radio->videodev)) {
588 		kfree(radio->buffer);
589 		kfree(radio);
590 		return -ENOMEM;
591 	}
592 
593 	memcpy(radio->videodev, &amradio_videodev_template,
594 		sizeof(amradio_videodev_template));
595 
596 	radio->removed = 0;
597 	radio->users = 0;
598 	radio->usbdev = interface_to_usbdev(intf);
599 	radio->curfreq = 95.16 * FREQ_MUL;
600 
601 	mutex_init(&radio->lock);
602 
603 	video_set_drvdata(radio->videodev, radio);
604 	if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
605 		warn("Could not register video device");
606 		video_device_release(radio->videodev);
607 		kfree(radio->buffer);
608 		kfree(radio);
609 		return -EIO;
610 	}
611 
612 	usb_set_intfdata(intf, radio);
613 	return 0;
614 }
615 
616 static int __init amradio_init(void)
617 {
618 	int retval = usb_register(&usb_amradio_driver);
619 
620 	info(DRIVER_VERSION " " DRIVER_DESC);
621 	if (retval)
622 		err("usb_register failed. Error number %d", retval);
623 	return retval;
624 }
625 
626 static void __exit amradio_exit(void)
627 {
628 	usb_deregister(&usb_amradio_driver);
629 }
630 
631 module_init(amradio_init);
632 module_exit(amradio_exit);
633 
634