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         Converted dsbr100 to use video_ioctl2
 
  38         by Douglas Landgraf <dougsland@gmail.com>
 
  41         Alan Cox: Some cleanups and fixes
 
  44         Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
 
  47         Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
 
  50         Markus: Updates for 2.5.x kernel and more ISO compliant source
 
  53         PSL and Markus: Cleanup, radio now doesn't stop on device close
 
  56         Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
 
  57         right.  Some minor cleanup, improved standalone compilation
 
  60         Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
 
  63         Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
 
  64         thanks to Mike Cox for pointing the problem out.
 
  67         Markus: Minor cleanup, warnings if something goes wrong, lame attempt
 
  68         to adhere to Documentation/CodingStyle
 
  71         Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
 
  72         Markus: Copyright clarification
 
  74  Version 0.01: Markus: initial release
 
  78 #include <linux/kernel.h>
 
  79 #include <linux/module.h>
 
  80 #include <linux/init.h>
 
  81 #include <linux/slab.h>
 
  82 #include <linux/input.h>
 
  83 #include <linux/videodev2.h>
 
  84 #include <media/v4l2-common.h>
 
  85 #include <linux/usb.h>
 
  90 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 
  92 #define DRIVER_VERSION "v0.41"
 
  93 #define RADIO_VERSION KERNEL_VERSION(0,4,1)
 
  95 static struct v4l2_queryctrl radio_qctrl[] = {
 
  97                 .id            = V4L2_CID_AUDIO_MUTE,
 
 102                 .type          = V4L2_CTRL_TYPE_BOOLEAN,
 
 106 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
 
 107 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
 
 109 #define DSB100_VENDOR 0x04b4
 
 110 #define DSB100_PRODUCT 0x1002
 
 112 /* Commands the device appears to understand */
 
 113 #define DSB100_TUNE 1
 
 114 #define DSB100_ONOFF 2
 
 118 /* Frequency limits in MHz -- these are European values.  For Japanese
 
 119 devices, that would be 76 and 91.  */
 
 120 #define FREQ_MIN  87.5
 
 121 #define FREQ_MAX 108.0
 
 122 #define FREQ_MUL 16000
 
 125 static int usb_dsbr100_probe(struct usb_interface *intf,
 
 126                              const struct usb_device_id *id);
 
 127 static void usb_dsbr100_disconnect(struct usb_interface *intf);
 
 128 static int usb_dsbr100_open(struct inode *inode, struct file *file);
 
 129 static int usb_dsbr100_close(struct inode *inode, struct file *file);
 
 131 static int radio_nr = -1;
 
 132 module_param(radio_nr, int, 0);
 
 134 /* Data for one (physical) device */
 
 135 struct dsbr100_device {
 
 136         struct usb_device *usbdev;
 
 137         struct video_device *videodev;
 
 138         unsigned char transfer_buffer[TB_LEN];
 
 147 static struct usb_device_id usb_dsbr100_device_table [] = {
 
 148         { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
 
 149         { }                                             /* Terminating entry */
 
 152 MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
 
 154 /* USB subsystem interface */
 
 155 static struct usb_driver usb_dsbr100_driver = {
 
 157         .probe =        usb_dsbr100_probe,
 
 158         .disconnect =   usb_dsbr100_disconnect,
 
 159         .id_table =     usb_dsbr100_device_table,
 
 162 /* Low-level device interface begins here */
 
 164 /* switch on radio */
 
 165 static int dsbr100_start(struct dsbr100_device *radio)
 
 167         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 169                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 
 170                         0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
 
 171         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 173                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 
 174                         0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
 
 177         return (radio->transfer_buffer)[0];
 
 181 /* switch off radio */
 
 182 static int dsbr100_stop(struct dsbr100_device *radio)
 
 184         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 186                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 
 187                         0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
 
 188         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 190                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 
 191                         0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
 
 194         return (radio->transfer_buffer)[0];
 
 197 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
 
 198 static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
 
 200         freq = (freq/16*80)/1000+856;
 
 201         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 203                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 
 204                         (freq>>8)&0x00ff, freq&0xff,
 
 205                         radio->transfer_buffer, 8, 300)<0 ||
 
 206            usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 208                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 
 209                         0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
 
 210         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 212                         USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
 
 213                         0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
 
 217         radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
 
 218         return (radio->transfer_buffer)[0];
 
 221 /* return the device status.  This is, in effect, just whether it
 
 222 sees a stereo signal or not.  Pity. */
 
 223 static void dsbr100_getstat(struct dsbr100_device *radio)
 
 225         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 
 227                 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 
 228                 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
 
 231                 radio->stereo = ! (radio->transfer_buffer[0]&0x01);
 
 235 /* USB subsystem interface begins here */
 
 237 /* handle unplugging of the device, release data structures
 
 238 if nothing keeps us from doing it.  If something is still
 
 239 keeping us busy, the release callback of v4l will take care
 
 240 of releasing it.  stv680.c does not relase its private
 
 241 data, so I don't do this here either.  Checking out the
 
 242 code I'd expect I better did that, but if there's a memory
 
 243 leak here it's tiny (~50 bytes per disconnect) */
 
 244 static void usb_dsbr100_disconnect(struct usb_interface *intf)
 
 246         struct dsbr100_device *radio = usb_get_intfdata(intf);
 
 248         usb_set_intfdata (intf, NULL);
 
 250                 video_unregister_device(radio->videodev);
 
 251                 radio->videodev = NULL;
 
 261 static int vidioc_querycap(struct file *file, void *priv,
 
 262                                         struct v4l2_capability *v)
 
 264         strlcpy(v->driver, "dsbr100", sizeof(v->driver));
 
 265         strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
 
 266         sprintf(v->bus_info, "ISA");
 
 267         v->version = RADIO_VERSION;
 
 268         v->capabilities = V4L2_CAP_TUNER;
 
 272 static int vidioc_g_tuner(struct file *file, void *priv,
 
 273                                 struct v4l2_tuner *v)
 
 275         struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
 280         dsbr100_getstat(radio);
 
 281         strcpy(v->name, "FM");
 
 282         v->type = V4L2_TUNER_RADIO;
 
 283         v->rangelow = FREQ_MIN*FREQ_MUL;
 
 284         v->rangehigh = FREQ_MAX*FREQ_MUL;
 
 285         v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
 
 286         v->capability = V4L2_TUNER_CAP_LOW;
 
 288                 v->audmode = V4L2_TUNER_MODE_STEREO;
 
 290                 v->audmode = V4L2_TUNER_MODE_MONO;
 
 291         v->signal = 0xffff;     /* We can't get the signal strength */
 
 295 static int vidioc_s_tuner(struct file *file, void *priv,
 
 296                                 struct v4l2_tuner *v)
 
 304 static int vidioc_s_frequency(struct file *file, void *priv,
 
 305                                 struct v4l2_frequency *f)
 
 307         struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
 309         radio->curfreq = f->frequency;
 
 310         if (dsbr100_setfreq(radio, radio->curfreq)==-1)
 
 311                 warn("Set frequency failed");
 
 315 static int vidioc_g_frequency(struct file *file, void *priv,
 
 316                                 struct v4l2_frequency *f)
 
 318         struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
 320         f->type = V4L2_TUNER_RADIO;
 
 321         f->frequency = radio->curfreq;
 
 325 static int vidioc_queryctrl(struct file *file, void *priv,
 
 326                                 struct v4l2_queryctrl *qc)
 
 330         for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
 
 331                 if (qc->id && qc->id == radio_qctrl[i].id) {
 
 332                         memcpy(qc, &(radio_qctrl[i]),
 
 340 static int vidioc_g_ctrl(struct file *file, void *priv,
 
 341                                 struct v4l2_control *ctrl)
 
 343         struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
 346         case V4L2_CID_AUDIO_MUTE:
 
 347                 ctrl->value = radio->muted;
 
 353 static int vidioc_s_ctrl(struct file *file, void *priv,
 
 354                                 struct v4l2_control *ctrl)
 
 356         struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
 359         case V4L2_CID_AUDIO_MUTE:
 
 361                         if (dsbr100_stop(radio)==-1)
 
 362                                 warn("Radio did not respond properly");
 
 364                         if (dsbr100_start(radio)==-1)
 
 365                                 warn("Radio did not respond properly");
 
 372 static int vidioc_g_audio(struct file *file, void *priv,
 
 373                                 struct v4l2_audio *a)
 
 378         strcpy(a->name, "Radio");
 
 379         a->capability = V4L2_AUDCAP_STEREO;
 
 383 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 
 389 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 
 396 static int vidioc_s_audio(struct file *file, void *priv,
 
 397                                         struct v4l2_audio *a)
 
 404 static int usb_dsbr100_open(struct inode *inode, struct file *file)
 
 406         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
 
 411         if (dsbr100_start(radio)<0) {
 
 412                 warn("Radio did not start up properly");
 
 416         dsbr100_setfreq(radio, radio->curfreq);
 
 420 static int usb_dsbr100_close(struct inode *inode, struct file *file)
 
 422         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
 
 427         if (radio->removed) {
 
 433 /* File system interface */
 
 434 static const struct file_operations usb_dsbr100_fops = {
 
 435         .owner          = THIS_MODULE,
 
 436         .open           = usb_dsbr100_open,
 
 437         .release        = usb_dsbr100_close,
 
 438         .ioctl          = video_ioctl2,
 
 439         .compat_ioctl   = v4l_compat_ioctl32,
 
 444 static struct video_device dsbr100_videodev_template =
 
 446         .owner          = THIS_MODULE,
 
 447         .name           = "D-Link DSB-R 100",
 
 448         .type           = VID_TYPE_TUNER,
 
 449         .fops           = &usb_dsbr100_fops,
 
 450         .release        = video_device_release,
 
 451         .vidioc_querycap    = vidioc_querycap,
 
 452         .vidioc_g_tuner     = vidioc_g_tuner,
 
 453         .vidioc_s_tuner     = vidioc_s_tuner,
 
 454         .vidioc_g_frequency = vidioc_g_frequency,
 
 455         .vidioc_s_frequency = vidioc_s_frequency,
 
 456         .vidioc_queryctrl   = vidioc_queryctrl,
 
 457         .vidioc_g_ctrl      = vidioc_g_ctrl,
 
 458         .vidioc_s_ctrl      = vidioc_s_ctrl,
 
 459         .vidioc_g_audio     = vidioc_g_audio,
 
 460         .vidioc_s_audio     = vidioc_s_audio,
 
 461         .vidioc_g_input     = vidioc_g_input,
 
 462         .vidioc_s_input     = vidioc_s_input,
 
 465 /* check if the device is present and register with v4l and
 
 467 static int usb_dsbr100_probe(struct usb_interface *intf,
 
 468                                 const struct usb_device_id *id)
 
 470         struct dsbr100_device *radio;
 
 472         if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
 
 474         if (!(radio->videodev = video_device_alloc())) {
 
 478         memcpy(radio->videodev, &dsbr100_videodev_template,
 
 479                 sizeof(dsbr100_videodev_template));
 
 482         radio->usbdev = interface_to_usbdev(intf);
 
 483         radio->curfreq = FREQ_MIN*FREQ_MUL;
 
 484         video_set_drvdata(radio->videodev, radio);
 
 485         if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
 
 486                 warn("Could not register video device");
 
 487                 video_device_release(radio->videodev);
 
 491         usb_set_intfdata(intf, radio);
 
 495 static int __init dsbr100_init(void)
 
 497         int retval = usb_register(&usb_dsbr100_driver);
 
 498         info(DRIVER_VERSION ":" DRIVER_DESC);
 
 502 static void __exit dsbr100_exit(void)
 
 504         usb_deregister(&usb_dsbr100_driver);
 
 507 module_init (dsbr100_init);
 
 508 module_exit (dsbr100_exit);
 
 510 MODULE_AUTHOR( DRIVER_AUTHOR );
 
 511 MODULE_DESCRIPTION( DRIVER_DESC );
 
 512 MODULE_LICENSE("GPL");