1 /* A driver for the D-Link DSB-R100 USB radio. The R100 plugs
2 into both the USB and an analog audio input, so this thing
3 only deals with initialisation and frequency setting, the
4 audio data has to be handled by a sound driver.
6 Major issue: I can't find out where the device reports the signal
7 strength, and indeed the windows software appearantly just looks
8 at the stereo indicator as well. So, scanning will only find
9 stereo stations. Sad, but I can't help it.
11 Also, the windows program sends oodles of messages over to the
12 device, and I couldn't figure out their meaning. My suspicion
13 is that they don't have any:-)
15 You might find some interesting stuff about this module at
16 http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
18 Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 2 of the License, or
23 (at your option) any later version.
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 Oliver Neukum: avoided DMA coherency issue
40 Converted dsbr100 to use video_ioctl2
41 by Douglas Landgraf <dougsland@gmail.com>
44 Alan Cox: Some cleanups and fixes
47 Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
50 Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
53 Markus: Updates for 2.5.x kernel and more ISO compliant source
56 PSL and Markus: Cleanup, radio now doesn't stop on device close
59 Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
60 right. Some minor cleanup, improved standalone compilation
63 Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
66 Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
67 thanks to Mike Cox for pointing the problem out.
70 Markus: Minor cleanup, warnings if something goes wrong, lame attempt
71 to adhere to Documentation/CodingStyle
74 Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
75 Markus: Copyright clarification
77 Version 0.01: Markus: initial release
81 #include <linux/kernel.h>
82 #include <linux/module.h>
83 #include <linux/init.h>
84 #include <linux/slab.h>
85 #include <linux/input.h>
86 #include <linux/videodev2.h>
87 #include <media/v4l2-common.h>
88 #include <media/v4l2-ioctl.h>
89 #include <linux/usb.h>
94 #include <linux/version.h> /* for KERNEL_VERSION MACRO */
96 #define DRIVER_VERSION "v0.43"
97 #define RADIO_VERSION KERNEL_VERSION(0, 4, 3)
99 static struct v4l2_queryctrl radio_qctrl[] = {
101 .id = V4L2_CID_AUDIO_MUTE,
106 .type = V4L2_CTRL_TYPE_BOOLEAN,
108 /* HINT: the disabled controls are only here to satify kradio and such apps */
109 { .id = V4L2_CID_AUDIO_VOLUME,
110 .flags = V4L2_CTRL_FLAG_DISABLED,
113 .id = V4L2_CID_AUDIO_BALANCE,
114 .flags = V4L2_CTRL_FLAG_DISABLED,
117 .id = V4L2_CID_AUDIO_BASS,
118 .flags = V4L2_CTRL_FLAG_DISABLED,
121 .id = V4L2_CID_AUDIO_TREBLE,
122 .flags = V4L2_CTRL_FLAG_DISABLED,
125 .id = V4L2_CID_AUDIO_LOUDNESS,
126 .flags = V4L2_CTRL_FLAG_DISABLED,
130 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
131 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
133 #define DSB100_VENDOR 0x04b4
134 #define DSB100_PRODUCT 0x1002
136 /* Commands the device appears to understand */
137 #define DSB100_TUNE 1
138 #define DSB100_ONOFF 2
142 /* Frequency limits in MHz -- these are European values. For Japanese
143 devices, that would be 76 and 91. */
144 #define FREQ_MIN 87.5
145 #define FREQ_MAX 108.0
146 #define FREQ_MUL 16000
148 #define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev)
150 static int usb_dsbr100_probe(struct usb_interface *intf,
151 const struct usb_device_id *id);
152 static void usb_dsbr100_disconnect(struct usb_interface *intf);
153 static int usb_dsbr100_open(struct inode *inode, struct file *file);
154 static int usb_dsbr100_close(struct inode *inode, struct file *file);
155 static int usb_dsbr100_suspend(struct usb_interface *intf,
156 pm_message_t message);
157 static int usb_dsbr100_resume(struct usb_interface *intf);
159 static int radio_nr = -1;
160 module_param(radio_nr, int, 0);
162 /* Data for one (physical) device */
163 struct dsbr100_device {
164 struct usb_device *usbdev;
165 struct video_device videodev;
167 struct mutex lock; /* buffer locking */
176 static struct usb_device_id usb_dsbr100_device_table [] = {
177 { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
178 { } /* Terminating entry */
181 MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
183 /* USB subsystem interface */
184 static struct usb_driver usb_dsbr100_driver = {
186 .probe = usb_dsbr100_probe,
187 .disconnect = usb_dsbr100_disconnect,
188 .id_table = usb_dsbr100_device_table,
189 .suspend = usb_dsbr100_suspend,
190 .resume = usb_dsbr100_resume,
191 .reset_resume = usb_dsbr100_resume,
192 .supports_autosuspend = 0,
195 /* Low-level device interface begins here */
197 /* switch on radio */
198 static int dsbr100_start(struct dsbr100_device *radio)
200 mutex_lock(&radio->lock);
201 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
203 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
204 0x00, 0xC7, radio->transfer_buffer, 8, 300) < 0 ||
205 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
207 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
208 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0) {
209 mutex_unlock(&radio->lock);
214 mutex_unlock(&radio->lock);
215 return (radio->transfer_buffer)[0];
219 /* switch off radio */
220 static int dsbr100_stop(struct dsbr100_device *radio)
222 mutex_lock(&radio->lock);
223 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
225 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
226 0x16, 0x1C, radio->transfer_buffer, 8, 300) < 0 ||
227 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
229 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
230 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0) {
231 mutex_unlock(&radio->lock);
236 mutex_unlock(&radio->lock);
237 return (radio->transfer_buffer)[0];
240 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
241 static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
243 freq = (freq / 16 * 80) / 1000 + 856;
244 mutex_lock(&radio->lock);
245 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
247 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
248 (freq >> 8) & 0x00ff, freq & 0xff,
249 radio->transfer_buffer, 8, 300) < 0 ||
250 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
252 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
253 0x96, 0xB7, radio->transfer_buffer, 8, 300) < 0 ||
254 usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
256 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
257 0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) {
259 mutex_unlock(&radio->lock);
263 radio->stereo = !((radio->transfer_buffer)[0] & 0x01);
264 mutex_unlock(&radio->lock);
265 return (radio->transfer_buffer)[0];
268 /* return the device status. This is, in effect, just whether it
269 sees a stereo signal or not. Pity. */
270 static void dsbr100_getstat(struct dsbr100_device *radio)
272 mutex_lock(&radio->lock);
273 if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
275 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
276 0x00 , 0x24, radio->transfer_buffer, 8, 300) < 0)
279 radio->stereo = !(radio->transfer_buffer[0] & 0x01);
280 mutex_unlock(&radio->lock);
284 /* USB subsystem interface begins here */
286 /* handle unplugging of the device, release data structures
287 if nothing keeps us from doing it. If something is still
288 keeping us busy, the release callback of v4l will take care
290 static void usb_dsbr100_disconnect(struct usb_interface *intf)
292 struct dsbr100_device *radio = usb_get_intfdata(intf);
294 usb_set_intfdata (intf, NULL);
296 mutex_lock(&radio->lock);
298 mutex_unlock(&radio->lock);
300 video_unregister_device(&radio->videodev);
304 static int vidioc_querycap(struct file *file, void *priv,
305 struct v4l2_capability *v)
307 strlcpy(v->driver, "dsbr100", sizeof(v->driver));
308 strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
309 sprintf(v->bus_info, "USB");
310 v->version = RADIO_VERSION;
311 v->capabilities = V4L2_CAP_TUNER;
315 static int vidioc_g_tuner(struct file *file, void *priv,
316 struct v4l2_tuner *v)
318 struct dsbr100_device *radio = video_drvdata(file);
327 dsbr100_getstat(radio);
328 strcpy(v->name, "FM");
329 v->type = V4L2_TUNER_RADIO;
330 v->rangelow = FREQ_MIN * FREQ_MUL;
331 v->rangehigh = FREQ_MAX * FREQ_MUL;
332 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
333 v->capability = V4L2_TUNER_CAP_LOW;
335 v->audmode = V4L2_TUNER_MODE_STEREO;
337 v->audmode = V4L2_TUNER_MODE_MONO;
338 v->signal = 0xffff; /* We can't get the signal strength */
342 static int vidioc_s_tuner(struct file *file, void *priv,
343 struct v4l2_tuner *v)
345 struct dsbr100_device *radio = video_drvdata(file);
357 static int vidioc_s_frequency(struct file *file, void *priv,
358 struct v4l2_frequency *f)
360 struct dsbr100_device *radio = video_drvdata(file);
366 radio->curfreq = f->frequency;
367 if (dsbr100_setfreq(radio, radio->curfreq) == -1)
368 dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
372 static int vidioc_g_frequency(struct file *file, void *priv,
373 struct v4l2_frequency *f)
375 struct dsbr100_device *radio = video_drvdata(file);
381 f->type = V4L2_TUNER_RADIO;
382 f->frequency = radio->curfreq;
386 static int vidioc_queryctrl(struct file *file, void *priv,
387 struct v4l2_queryctrl *qc)
391 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
392 if (qc->id && qc->id == radio_qctrl[i].id) {
393 memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
400 static int vidioc_g_ctrl(struct file *file, void *priv,
401 struct v4l2_control *ctrl)
403 struct dsbr100_device *radio = video_drvdata(file);
410 case V4L2_CID_AUDIO_MUTE:
411 ctrl->value = radio->muted;
417 static int vidioc_s_ctrl(struct file *file, void *priv,
418 struct v4l2_control *ctrl)
420 struct dsbr100_device *radio = video_drvdata(file);
427 case V4L2_CID_AUDIO_MUTE:
429 if (dsbr100_stop(radio) == -1) {
430 dev_warn(&radio->usbdev->dev,
431 "Radio did not respond properly\n");
435 if (dsbr100_start(radio) == -1) {
436 dev_warn(&radio->usbdev->dev,
437 "Radio did not respond properly\n");
446 static int vidioc_g_audio(struct file *file, void *priv,
447 struct v4l2_audio *a)
452 strcpy(a->name, "Radio");
453 a->capability = V4L2_AUDCAP_STEREO;
457 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
463 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
470 static int vidioc_s_audio(struct file *file, void *priv,
471 struct v4l2_audio *a)
478 static int usb_dsbr100_open(struct inode *inode, struct file *file)
480 struct dsbr100_device *radio = video_drvdata(file);
487 if (dsbr100_start(radio) < 0) {
488 dev_warn(&radio->usbdev->dev,
489 "Radio did not start up properly\n");
495 retval = dsbr100_setfreq(radio, radio->curfreq);
498 dev_warn(&radio->usbdev->dev,
499 "set frequency failed\n");
505 static int usb_dsbr100_close(struct inode *inode, struct file *file)
507 struct dsbr100_device *radio = video_drvdata(file);
514 if (!radio->removed) {
515 retval = dsbr100_stop(radio);
517 dev_warn(&radio->usbdev->dev,
518 "dsbr100_stop failed\n");
525 /* Suspend device - stop device. */
526 static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message)
528 struct dsbr100_device *radio = usb_get_intfdata(intf);
531 retval = dsbr100_stop(radio);
533 dev_warn(&intf->dev, "dsbr100_stop failed\n");
535 dev_info(&intf->dev, "going into suspend..\n");
540 /* Resume device - start device. */
541 static int usb_dsbr100_resume(struct usb_interface *intf)
543 struct dsbr100_device *radio = usb_get_intfdata(intf);
546 retval = dsbr100_start(radio);
548 dev_warn(&intf->dev, "dsbr100_start failed\n");
550 dev_info(&intf->dev, "coming out of suspend..\n");
555 static void usb_dsbr100_video_device_release(struct video_device *videodev)
557 struct dsbr100_device *radio = videodev_to_radio(videodev);
559 kfree(radio->transfer_buffer);
563 /* File system interface */
564 static const struct file_operations usb_dsbr100_fops = {
565 .owner = THIS_MODULE,
566 .open = usb_dsbr100_open,
567 .release = usb_dsbr100_close,
568 .ioctl = video_ioctl2,
570 .compat_ioctl = v4l_compat_ioctl32,
575 static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
576 .vidioc_querycap = vidioc_querycap,
577 .vidioc_g_tuner = vidioc_g_tuner,
578 .vidioc_s_tuner = vidioc_s_tuner,
579 .vidioc_g_frequency = vidioc_g_frequency,
580 .vidioc_s_frequency = vidioc_s_frequency,
581 .vidioc_queryctrl = vidioc_queryctrl,
582 .vidioc_g_ctrl = vidioc_g_ctrl,
583 .vidioc_s_ctrl = vidioc_s_ctrl,
584 .vidioc_g_audio = vidioc_g_audio,
585 .vidioc_s_audio = vidioc_s_audio,
586 .vidioc_g_input = vidioc_g_input,
587 .vidioc_s_input = vidioc_s_input,
591 static struct video_device dsbr100_videodev_data = {
592 .name = "D-Link DSB-R 100",
593 .fops = &usb_dsbr100_fops,
594 .ioctl_ops = &usb_dsbr100_ioctl_ops,
595 .release = usb_dsbr100_video_device_release,
598 /* check if the device is present and register with v4l and
600 static int usb_dsbr100_probe(struct usb_interface *intf,
601 const struct usb_device_id *id)
603 struct dsbr100_device *radio;
605 radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL);
610 radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
612 if (!(radio->transfer_buffer)) {
617 mutex_init(&radio->lock);
618 radio->videodev = dsbr100_videodev_data;
622 radio->usbdev = interface_to_usbdev(intf);
623 radio->curfreq = FREQ_MIN * FREQ_MUL;
624 video_set_drvdata(&radio->videodev, radio);
625 if (video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
626 dev_warn(&intf->dev, "Could not register video device\n");
627 kfree(radio->transfer_buffer);
631 usb_set_intfdata(intf, radio);
635 static int __init dsbr100_init(void)
637 int retval = usb_register(&usb_dsbr100_driver);
638 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
643 static void __exit dsbr100_exit(void)
645 usb_deregister(&usb_dsbr100_driver);
648 module_init (dsbr100_init);
649 module_exit (dsbr100_exit);
651 MODULE_AUTHOR( DRIVER_AUTHOR );
652 MODULE_DESCRIPTION( DRIVER_DESC );
653 MODULE_LICENSE("GPL");