V4L/DVB (4410): Cleanups and fixes for dsbr100
[linux-2.6.git] / drivers / media / radio / dsbr100.c
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.
5
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.
10
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:-)
14
15  You might find some interesting stuff about this module at
16  http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
17
18  Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
19
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.
24
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.
29
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
33
34  History:
35
36  Version 0.41-ac1:
37         Alan Cox: Some cleanups and fixes
38
39  Version 0.41:
40         Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
41
42  Version 0.40:
43         Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
44
45  Version 0.30:
46         Markus: Updates for 2.5.x kernel and more ISO compliant source
47
48  Version 0.25:
49         PSL and Markus: Cleanup, radio now doesn't stop on device close
50
51  Version 0.24:
52         Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
53         right.  Some minor cleanup, improved standalone compilation
54
55  Version 0.23:
56         Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
57
58  Version 0.22:
59         Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
60         thanks to Mike Cox for pointing the problem out.
61
62  Version 0.21:
63         Markus: Minor cleanup, warnings if something goes wrong, lame attempt
64         to adhere to Documentation/CodingStyle
65
66  Version 0.2:
67         Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
68         Markus: Copyright clarification
69
70  Version 0.01: Markus: initial release
71
72 */
73
74 #include <linux/kernel.h>
75 #include <linux/module.h>
76 #include <linux/init.h>
77 #include <linux/slab.h>
78 #include <linux/input.h>
79 #include <linux/videodev2.h>
80 #include <media/v4l2-common.h>
81 #include <linux/usb.h>
82 #include <linux/smp_lock.h>
83
84 /*
85  * Version Information
86  */
87 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
88
89 #define DRIVER_VERSION "v0.41"
90 #define RADIO_VERSION KERNEL_VERSION(0,4,1)
91
92 static struct v4l2_queryctrl radio_qctrl[] = {
93         {
94                 .id            = V4L2_CID_AUDIO_MUTE,
95                 .name          = "Mute",
96                 .minimum       = 0,
97                 .maximum       = 1,
98                 .default_value = 1,
99                 .type          = V4L2_CTRL_TYPE_BOOLEAN,
100         }
101 };
102
103 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
104 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
105
106 #define DSB100_VENDOR 0x04b4
107 #define DSB100_PRODUCT 0x1002
108
109 /* Commands the device appears to understand */
110 #define DSB100_TUNE 1
111 #define DSB100_ONOFF 2
112
113 #define TB_LEN 16
114
115 /* Frequency limits in MHz -- these are European values.  For Japanese
116 devices, that would be 76 and 91.  */
117 #define FREQ_MIN  87.5
118 #define FREQ_MAX 108.0
119 #define FREQ_MUL 16000
120
121
122 static int usb_dsbr100_probe(struct usb_interface *intf,
123                              const struct usb_device_id *id);
124 static void usb_dsbr100_disconnect(struct usb_interface *intf);
125 static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
126                              unsigned int cmd, unsigned long arg);
127 static int usb_dsbr100_open(struct inode *inode, struct file *file);
128 static int usb_dsbr100_close(struct inode *inode, struct file *file);
129
130 static int radio_nr = -1;
131 module_param(radio_nr, int, 0);
132
133 /* Data for one (physical) device */
134 struct dsbr100_device {
135         struct usb_device *usbdev;
136         struct video_device *videodev;
137         unsigned char transfer_buffer[TB_LEN];
138         int curfreq;
139         int stereo;
140         int users;
141         int removed;
142         int muted;
143 };
144
145
146 /* File system interface */
147 static struct file_operations usb_dsbr100_fops = {
148         .owner =        THIS_MODULE,
149         .open =         usb_dsbr100_open,
150         .release =      usb_dsbr100_close,
151         .ioctl =        usb_dsbr100_ioctl,
152         .compat_ioctl = v4l_compat_ioctl32,
153         .llseek =       no_llseek,
154 };
155
156 /* V4L interface */
157 static struct video_device dsbr100_videodev_template=
158 {
159         .owner =        THIS_MODULE,
160         .name =         "D-Link DSB-R 100",
161         .type =         VID_TYPE_TUNER,
162         .fops =         &usb_dsbr100_fops,
163         .release = video_device_release,
164 };
165
166 static struct usb_device_id usb_dsbr100_device_table [] = {
167         { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
168         { }                                             /* Terminating entry */
169 };
170
171 MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
172
173 /* USB subsystem interface */
174 static struct usb_driver usb_dsbr100_driver = {
175         .name =         "dsbr100",
176         .probe =        usb_dsbr100_probe,
177         .disconnect =   usb_dsbr100_disconnect,
178         .id_table =     usb_dsbr100_device_table,
179 };
180
181 /* Low-level device interface begins here */
182
183 /* switch on radio */
184 static int dsbr100_start(struct dsbr100_device *radio)
185 {
186         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
187                         USB_REQ_GET_STATUS,
188                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
189                         0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
190         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
191                         DSB100_ONOFF,
192                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
193                         0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
194                 return -1;
195         radio->muted=0;
196         return (radio->transfer_buffer)[0];
197 }
198
199
200 /* switch off radio */
201 static int dsbr100_stop(struct dsbr100_device *radio)
202 {
203         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
204                         USB_REQ_GET_STATUS,
205                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
206                         0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
207         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
208                         DSB100_ONOFF,
209                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
210                         0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
211                 return -1;
212         radio->muted=1;
213         return (radio->transfer_buffer)[0];
214 }
215
216 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
217 static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
218 {
219         freq = (freq/16*80)/1000+856;
220         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
221                         DSB100_TUNE,
222                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
223                         (freq>>8)&0x00ff, freq&0xff,
224                         radio->transfer_buffer, 8, 300)<0 ||
225            usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
226                         USB_REQ_GET_STATUS,
227                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
228                         0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
229         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
230                         USB_REQ_GET_STATUS,
231                         USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
232                         0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
233                 radio->stereo = -1;
234                 return -1;
235         }
236         radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
237         return (radio->transfer_buffer)[0];
238 }
239
240 /* return the device status.  This is, in effect, just whether it
241 sees a stereo signal or not.  Pity. */
242 static void dsbr100_getstat(struct dsbr100_device *radio)
243 {
244         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
245                 USB_REQ_GET_STATUS,
246                 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
247                 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
248                 radio->stereo = -1;
249         else
250                 radio->stereo = ! (radio->transfer_buffer[0]&0x01);
251 }
252
253
254 /* USB subsystem interface begins here */
255
256 /* check if the device is present and register with v4l and
257 usb if it is */
258 static int usb_dsbr100_probe(struct usb_interface *intf,
259                          const struct usb_device_id *id)
260 {
261         struct dsbr100_device *radio;
262
263         if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
264                 return -ENOMEM;
265         if (!(radio->videodev = video_device_alloc())) {
266                 kfree(radio);
267                 return -ENOMEM;
268         }
269         memcpy(radio->videodev, &dsbr100_videodev_template,
270                 sizeof(dsbr100_videodev_template));
271         radio->removed = 0;
272         radio->users = 0;
273         radio->usbdev = interface_to_usbdev(intf);
274         radio->curfreq = FREQ_MIN*FREQ_MUL;
275         video_set_drvdata(radio->videodev, radio);
276         if (video_register_device(radio->videodev, VFL_TYPE_RADIO,
277                 radio_nr)) {
278                 warn("Could not register video device");
279                 video_device_release(radio->videodev);
280                 kfree(radio);
281                 return -EIO;
282         }
283         usb_set_intfdata(intf, radio);
284         return 0;
285 }
286
287 /* handle unplugging of the device, release data structures
288 if nothing keeps us from doing it.  If something is still
289 keeping us busy, the release callback of v4l will take care
290 of releasing it.  stv680.c does not relase its private
291 data, so I don't do this here either.  Checking out the
292 code I'd expect I better did that, but if there's a memory
293 leak here it's tiny (~50 bytes per disconnect) */
294 static void usb_dsbr100_disconnect(struct usb_interface *intf)
295 {
296         struct dsbr100_device *radio = usb_get_intfdata(intf);
297
298         usb_set_intfdata (intf, NULL);
299         if (radio) {
300                 video_unregister_device(radio->videodev);
301                 radio->videodev = NULL;
302                 if (radio->users) {
303                         kfree(radio);
304                 } else {
305                         radio->removed = 1;
306                 }
307         }
308 }
309
310
311 /* Video for Linux interface */
312
313 static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
314                                 unsigned int cmd, void *arg)
315 {
316         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
317
318         if (!radio)
319                 return -EIO;
320
321         switch(cmd) {
322                 case VIDIOC_QUERYCAP:
323                 {
324                         struct v4l2_capability *v = arg;
325                         memset(v,0,sizeof(*v));
326                         strlcpy(v->driver, "dsbr100", sizeof (v->driver));
327                         strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card));
328                         sprintf(v->bus_info,"ISA");
329                         v->version = RADIO_VERSION;
330                         v->capabilities = V4L2_CAP_TUNER;
331
332                         return 0;
333                 }
334                 case VIDIOC_G_TUNER:
335                 {
336                         struct v4l2_tuner *v = arg;
337
338                         if (v->index > 0)
339                                 return -EINVAL;
340
341                         dsbr100_getstat(radio);
342
343                         memset(v,0,sizeof(*v));
344                         strcpy(v->name, "FM");
345                         v->type = V4L2_TUNER_RADIO;
346
347                         v->rangelow = FREQ_MIN*FREQ_MUL;
348                         v->rangehigh = FREQ_MAX*FREQ_MUL;
349                         v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
350                         v->capability=V4L2_TUNER_CAP_LOW;
351                         if(radio->stereo)
352                                 v->audmode = V4L2_TUNER_MODE_STEREO;
353                         else
354                                 v->audmode = V4L2_TUNER_MODE_MONO;
355                         v->signal = 0xFFFF;     /* We can't get the signal strength */
356
357                         return 0;
358                 }
359                 case VIDIOC_S_TUNER:
360                 {
361                         struct v4l2_tuner *v = arg;
362
363                         if (v->index > 0)
364                                 return -EINVAL;
365
366                         return 0;
367                 }
368                 case VIDIOC_S_FREQUENCY:
369                 {
370                         struct v4l2_frequency *f = arg;
371
372                         radio->curfreq = f->frequency;
373                         if (dsbr100_setfreq(radio, radio->curfreq)==-1)
374                                 warn("Set frequency failed");
375                         return 0;
376                 }
377                 case VIDIOC_G_FREQUENCY:
378                 {
379                         struct v4l2_frequency *f = arg;
380
381                         f->type = V4L2_TUNER_RADIO;
382                         f->frequency = radio->curfreq;
383
384                         return 0;
385                 }
386                 case VIDIOC_QUERYCTRL:
387                 {
388                         struct v4l2_queryctrl *qc = arg;
389                         int i;
390
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]),
394                                                                 sizeof(*qc));
395                                         return 0;
396                                 }
397                         }
398                         return -EINVAL;
399                 }
400                 case VIDIOC_G_CTRL:
401                 {
402                         struct v4l2_control *ctrl= arg;
403
404                         switch (ctrl->id) {
405                         case V4L2_CID_AUDIO_MUTE:
406                                 ctrl->value=radio->muted;
407                                 return 0;
408                         }
409                         return -EINVAL;
410                 }
411                 case VIDIOC_S_CTRL:
412                 {
413                         struct v4l2_control *ctrl= arg;
414
415                         switch (ctrl->id) {
416                         case V4L2_CID_AUDIO_MUTE:
417                                 if (ctrl->value) {
418                                         if (dsbr100_stop(radio)==-1)
419                                                 warn("Radio did not respond properly");
420                                 } else {
421                                         if (dsbr100_start(radio)==-1)
422                                                 warn("Radio did not respond properly");
423                                 }
424                                 return 0;
425                         }
426                         return -EINVAL;
427                 }
428                 default:
429                         return v4l_compat_translate_ioctl(inode,file,cmd,arg,
430                                                           usb_dsbr100_do_ioctl);
431         }
432 }
433
434 static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
435                              unsigned int cmd, unsigned long arg)
436 {
437         return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
438 }
439
440 static int usb_dsbr100_open(struct inode *inode, struct file *file)
441 {
442         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
443
444         radio->users = 1;
445         radio->muted = 1;
446
447         if (dsbr100_start(radio)<0) {
448                 warn("Radio did not start up properly");
449                 radio->users = 0;
450                 return -EIO;
451         }
452         dsbr100_setfreq(radio, radio->curfreq);
453         return 0;
454 }
455
456 static int usb_dsbr100_close(struct inode *inode, struct file *file)
457 {
458         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
459
460         if (!radio)
461                 return -ENODEV;
462         radio->users = 0;
463         if (radio->removed) {
464                 kfree(radio);
465         }
466         return 0;
467 }
468
469 static int __init dsbr100_init(void)
470 {
471         int retval = usb_register(&usb_dsbr100_driver);
472         info(DRIVER_VERSION ":" DRIVER_DESC);
473         return retval;
474 }
475
476 static void __exit dsbr100_exit(void)
477 {
478         usb_deregister(&usb_dsbr100_driver);
479 }
480
481 module_init (dsbr100_init);
482 module_exit (dsbr100_exit);
483
484 MODULE_AUTHOR( DRIVER_AUTHOR );
485 MODULE_DESCRIPTION( DRIVER_DESC );
486 MODULE_LICENSE("GPL");