1 /* A driver for the D-Link DSB-R100 USB radio and Gemtek USB Radio 21. 2 The device plugs 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.46: 37 Removed usb_dsbr100_open/close calls and radio->users counter. Also, 38 radio->muted changed to radio->status and suspend/resume calls updated. 39 40 Version 0.45: 41 Converted to v4l2_device. 42 43 Version 0.44: 44 Add suspend/resume functions, fix unplug of device, 45 a lot of cleanups and fixes by Alexey Klimov <klimov.linux@gmail.com> 46 47 Version 0.43: 48 Oliver Neukum: avoided DMA coherency issue 49 50 Version 0.42: 51 Converted dsbr100 to use video_ioctl2 52 by Douglas Landgraf <dougsland@gmail.com> 53 54 Version 0.41-ac1: 55 Alan Cox: Some cleanups and fixes 56 57 Version 0.41: 58 Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> 59 60 Version 0.40: 61 Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing 62 63 Version 0.30: 64 Markus: Updates for 2.5.x kernel and more ISO compliant source 65 66 Version 0.25: 67 PSL and Markus: Cleanup, radio now doesn't stop on device close 68 69 Version 0.24: 70 Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally 71 right. Some minor cleanup, improved standalone compilation 72 73 Version 0.23: 74 Markus: Sign extension bug fixed by declaring transfer_buffer unsigned 75 76 Version 0.22: 77 Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, 78 thanks to Mike Cox for pointing the problem out. 79 80 Version 0.21: 81 Markus: Minor cleanup, warnings if something goes wrong, lame attempt 82 to adhere to Documentation/CodingStyle 83 84 Version 0.2: 85 Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module 86 Markus: Copyright clarification 87 88 Version 0.01: Markus: initial release 89 90 */ 91 92 #include <linux/kernel.h> 93 #include <linux/module.h> 94 #include <linux/init.h> 95 #include <linux/slab.h> 96 #include <linux/input.h> 97 #include <linux/videodev2.h> 98 #include <media/v4l2-device.h> 99 #include <media/v4l2-ioctl.h> 100 #include <linux/usb.h> 101 102 /* 103 * Version Information 104 */ 105 #define DRIVER_VERSION "0.4.7" 106 107 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>" 108 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" 109 110 #define DSB100_VENDOR 0x04b4 111 #define DSB100_PRODUCT 0x1002 112 113 /* Commands the device appears to understand */ 114 #define DSB100_TUNE 1 115 #define DSB100_ONOFF 2 116 117 #define TB_LEN 16 118 119 /* Frequency limits in MHz -- these are European values. For Japanese 120 devices, that would be 76 and 91. */ 121 #define FREQ_MIN 87.5 122 #define FREQ_MAX 108.0 123 #define FREQ_MUL 16000 124 125 /* defines for radio->status */ 126 #define STARTED 0 127 #define STOPPED 1 128 129 #define v4l2_dev_to_radio(d) container_of(d, struct dsbr100_device, v4l2_dev) 130 131 static int usb_dsbr100_probe(struct usb_interface *intf, 132 const struct usb_device_id *id); 133 static void usb_dsbr100_disconnect(struct usb_interface *intf); 134 static int usb_dsbr100_suspend(struct usb_interface *intf, 135 pm_message_t message); 136 static int usb_dsbr100_resume(struct usb_interface *intf); 137 138 static int radio_nr = -1; 139 module_param(radio_nr, int, 0); 140 141 /* Data for one (physical) device */ 142 struct dsbr100_device { 143 struct usb_device *usbdev; 144 struct video_device videodev; 145 struct v4l2_device v4l2_dev; 146 147 u8 *transfer_buffer; 148 struct mutex v4l2_lock; 149 int curfreq; 150 int stereo; 151 int status; 152 }; 153 154 static struct usb_device_id usb_dsbr100_device_table [] = { 155 { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, 156 { } /* Terminating entry */ 157 }; 158 159 MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table); 160 161 /* USB subsystem interface */ 162 static struct usb_driver usb_dsbr100_driver = { 163 .name = "dsbr100", 164 .probe = usb_dsbr100_probe, 165 .disconnect = usb_dsbr100_disconnect, 166 .id_table = usb_dsbr100_device_table, 167 .suspend = usb_dsbr100_suspend, 168 .resume = usb_dsbr100_resume, 169 .reset_resume = usb_dsbr100_resume, 170 .supports_autosuspend = 0, 171 }; 172 173 /* Low-level device interface begins here */ 174 175 /* switch on radio */ 176 static int dsbr100_start(struct dsbr100_device *radio) 177 { 178 int retval; 179 int request; 180 181 retval = usb_control_msg(radio->usbdev, 182 usb_rcvctrlpipe(radio->usbdev, 0), 183 USB_REQ_GET_STATUS, 184 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 185 0x00, 0xC7, radio->transfer_buffer, 8, 300); 186 187 if (retval < 0) { 188 request = USB_REQ_GET_STATUS; 189 goto usb_control_msg_failed; 190 } 191 192 retval = usb_control_msg(radio->usbdev, 193 usb_rcvctrlpipe(radio->usbdev, 0), 194 DSB100_ONOFF, 195 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 196 0x01, 0x00, radio->transfer_buffer, 8, 300); 197 198 if (retval < 0) { 199 request = DSB100_ONOFF; 200 goto usb_control_msg_failed; 201 } 202 203 radio->status = STARTED; 204 return (radio->transfer_buffer)[0]; 205 206 usb_control_msg_failed: 207 dev_err(&radio->usbdev->dev, 208 "%s - usb_control_msg returned %i, request %i\n", 209 __func__, retval, request); 210 return retval; 211 212 } 213 214 /* switch off radio */ 215 static int dsbr100_stop(struct dsbr100_device *radio) 216 { 217 int retval; 218 int request; 219 220 retval = usb_control_msg(radio->usbdev, 221 usb_rcvctrlpipe(radio->usbdev, 0), 222 USB_REQ_GET_STATUS, 223 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 224 0x16, 0x1C, radio->transfer_buffer, 8, 300); 225 226 if (retval < 0) { 227 request = USB_REQ_GET_STATUS; 228 goto usb_control_msg_failed; 229 } 230 231 retval = usb_control_msg(radio->usbdev, 232 usb_rcvctrlpipe(radio->usbdev, 0), 233 DSB100_ONOFF, 234 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 235 0x00, 0x00, radio->transfer_buffer, 8, 300); 236 237 if (retval < 0) { 238 request = DSB100_ONOFF; 239 goto usb_control_msg_failed; 240 } 241 242 radio->status = STOPPED; 243 return (radio->transfer_buffer)[0]; 244 245 usb_control_msg_failed: 246 dev_err(&radio->usbdev->dev, 247 "%s - usb_control_msg returned %i, request %i\n", 248 __func__, retval, request); 249 return retval; 250 251 } 252 253 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ 254 static int dsbr100_setfreq(struct dsbr100_device *radio) 255 { 256 int retval; 257 int request; 258 int freq = (radio->curfreq / 16 * 80) / 1000 + 856; 259 260 retval = usb_control_msg(radio->usbdev, 261 usb_rcvctrlpipe(radio->usbdev, 0), 262 DSB100_TUNE, 263 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 264 (freq >> 8) & 0x00ff, freq & 0xff, 265 radio->transfer_buffer, 8, 300); 266 267 if (retval < 0) { 268 request = DSB100_TUNE; 269 goto usb_control_msg_failed; 270 } 271 272 retval = usb_control_msg(radio->usbdev, 273 usb_rcvctrlpipe(radio->usbdev, 0), 274 USB_REQ_GET_STATUS, 275 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 276 0x96, 0xB7, radio->transfer_buffer, 8, 300); 277 278 if (retval < 0) { 279 request = USB_REQ_GET_STATUS; 280 goto usb_control_msg_failed; 281 } 282 283 retval = usb_control_msg(radio->usbdev, 284 usb_rcvctrlpipe(radio->usbdev, 0), 285 USB_REQ_GET_STATUS, 286 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 287 0x00, 0x24, radio->transfer_buffer, 8, 300); 288 289 if (retval < 0) { 290 request = USB_REQ_GET_STATUS; 291 goto usb_control_msg_failed; 292 } 293 294 radio->stereo = !((radio->transfer_buffer)[0] & 0x01); 295 return (radio->transfer_buffer)[0]; 296 297 usb_control_msg_failed: 298 radio->stereo = -1; 299 dev_err(&radio->usbdev->dev, 300 "%s - usb_control_msg returned %i, request %i\n", 301 __func__, retval, request); 302 return retval; 303 } 304 305 /* return the device status. This is, in effect, just whether it 306 sees a stereo signal or not. Pity. */ 307 static void dsbr100_getstat(struct dsbr100_device *radio) 308 { 309 int retval; 310 311 retval = usb_control_msg(radio->usbdev, 312 usb_rcvctrlpipe(radio->usbdev, 0), 313 USB_REQ_GET_STATUS, 314 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 315 0x00 , 0x24, radio->transfer_buffer, 8, 300); 316 317 if (retval < 0) { 318 radio->stereo = -1; 319 dev_err(&radio->usbdev->dev, 320 "%s - usb_control_msg returned %i, request %i\n", 321 __func__, retval, USB_REQ_GET_STATUS); 322 } else { 323 radio->stereo = !(radio->transfer_buffer[0] & 0x01); 324 } 325 } 326 327 static int vidioc_querycap(struct file *file, void *priv, 328 struct v4l2_capability *v) 329 { 330 struct dsbr100_device *radio = video_drvdata(file); 331 332 strlcpy(v->driver, "dsbr100", sizeof(v->driver)); 333 strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card)); 334 usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); 335 v->capabilities = V4L2_CAP_TUNER; 336 return 0; 337 } 338 339 static int vidioc_g_tuner(struct file *file, void *priv, 340 struct v4l2_tuner *v) 341 { 342 struct dsbr100_device *radio = video_drvdata(file); 343 344 if (v->index > 0) 345 return -EINVAL; 346 347 dsbr100_getstat(radio); 348 strcpy(v->name, "FM"); 349 v->type = V4L2_TUNER_RADIO; 350 v->rangelow = FREQ_MIN * FREQ_MUL; 351 v->rangehigh = FREQ_MAX * FREQ_MUL; 352 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 353 v->capability = V4L2_TUNER_CAP_LOW; 354 if(radio->stereo) 355 v->audmode = V4L2_TUNER_MODE_STEREO; 356 else 357 v->audmode = V4L2_TUNER_MODE_MONO; 358 v->signal = 0xffff; /* We can't get the signal strength */ 359 return 0; 360 } 361 362 static int vidioc_s_tuner(struct file *file, void *priv, 363 struct v4l2_tuner *v) 364 { 365 return v->index ? -EINVAL : 0; 366 } 367 368 static int vidioc_s_frequency(struct file *file, void *priv, 369 struct v4l2_frequency *f) 370 { 371 struct dsbr100_device *radio = video_drvdata(file); 372 int retval; 373 374 radio->curfreq = f->frequency; 375 376 retval = dsbr100_setfreq(radio); 377 if (retval < 0) 378 dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); 379 return 0; 380 } 381 382 static int vidioc_g_frequency(struct file *file, void *priv, 383 struct v4l2_frequency *f) 384 { 385 struct dsbr100_device *radio = video_drvdata(file); 386 387 f->type = V4L2_TUNER_RADIO; 388 f->frequency = radio->curfreq; 389 return 0; 390 } 391 392 static int vidioc_queryctrl(struct file *file, void *priv, 393 struct v4l2_queryctrl *qc) 394 { 395 switch (qc->id) { 396 case V4L2_CID_AUDIO_MUTE: 397 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); 398 } 399 400 return -EINVAL; 401 } 402 403 static int vidioc_g_ctrl(struct file *file, void *priv, 404 struct v4l2_control *ctrl) 405 { 406 struct dsbr100_device *radio = video_drvdata(file); 407 408 switch (ctrl->id) { 409 case V4L2_CID_AUDIO_MUTE: 410 ctrl->value = radio->status; 411 return 0; 412 } 413 return -EINVAL; 414 } 415 416 static int vidioc_s_ctrl(struct file *file, void *priv, 417 struct v4l2_control *ctrl) 418 { 419 struct dsbr100_device *radio = video_drvdata(file); 420 int retval; 421 422 switch (ctrl->id) { 423 case V4L2_CID_AUDIO_MUTE: 424 if (ctrl->value) { 425 retval = dsbr100_stop(radio); 426 if (retval < 0) { 427 dev_warn(&radio->usbdev->dev, 428 "Radio did not respond properly\n"); 429 return -EBUSY; 430 } 431 } else { 432 retval = dsbr100_start(radio); 433 if (retval < 0) { 434 dev_warn(&radio->usbdev->dev, 435 "Radio did not respond properly\n"); 436 return -EBUSY; 437 } 438 } 439 return 0; 440 } 441 return -EINVAL; 442 } 443 444 static int vidioc_g_audio(struct file *file, void *priv, 445 struct v4l2_audio *a) 446 { 447 if (a->index > 1) 448 return -EINVAL; 449 450 strcpy(a->name, "Radio"); 451 a->capability = V4L2_AUDCAP_STEREO; 452 return 0; 453 } 454 455 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 456 { 457 *i = 0; 458 return 0; 459 } 460 461 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 462 { 463 return i ? -EINVAL : 0; 464 } 465 466 static int vidioc_s_audio(struct file *file, void *priv, 467 struct v4l2_audio *a) 468 { 469 return a->index ? -EINVAL : 0; 470 } 471 472 /* USB subsystem interface begins here */ 473 474 /* 475 * Handle unplugging of the device. 476 * We call video_unregister_device in any case. 477 * The last function called in this procedure is 478 * usb_dsbr100_video_device_release 479 */ 480 static void usb_dsbr100_disconnect(struct usb_interface *intf) 481 { 482 struct dsbr100_device *radio = usb_get_intfdata(intf); 483 484 v4l2_device_get(&radio->v4l2_dev); 485 mutex_lock(&radio->v4l2_lock); 486 usb_set_intfdata(intf, NULL); 487 video_unregister_device(&radio->videodev); 488 v4l2_device_disconnect(&radio->v4l2_dev); 489 mutex_unlock(&radio->v4l2_lock); 490 v4l2_device_put(&radio->v4l2_dev); 491 } 492 493 494 /* Suspend device - stop device. */ 495 static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) 496 { 497 struct dsbr100_device *radio = usb_get_intfdata(intf); 498 int retval; 499 500 mutex_lock(&radio->v4l2_lock); 501 if (radio->status == STARTED) { 502 retval = dsbr100_stop(radio); 503 if (retval < 0) 504 dev_warn(&intf->dev, "dsbr100_stop failed\n"); 505 506 /* After dsbr100_stop() status set to STOPPED. 507 * If we want driver to start radio on resume 508 * we set status equal to STARTED. 509 * On resume we will check status and run radio if needed. 510 */ 511 radio->status = STARTED; 512 } 513 mutex_unlock(&radio->v4l2_lock); 514 515 dev_info(&intf->dev, "going into suspend..\n"); 516 517 return 0; 518 } 519 520 /* Resume device - start device. */ 521 static int usb_dsbr100_resume(struct usb_interface *intf) 522 { 523 struct dsbr100_device *radio = usb_get_intfdata(intf); 524 int retval; 525 526 mutex_lock(&radio->v4l2_lock); 527 if (radio->status == STARTED) { 528 retval = dsbr100_start(radio); 529 if (retval < 0) 530 dev_warn(&intf->dev, "dsbr100_start failed\n"); 531 } 532 mutex_unlock(&radio->v4l2_lock); 533 534 dev_info(&intf->dev, "coming out of suspend..\n"); 535 536 return 0; 537 } 538 539 /* free data structures */ 540 static void usb_dsbr100_release(struct v4l2_device *v4l2_dev) 541 { 542 struct dsbr100_device *radio = v4l2_dev_to_radio(v4l2_dev); 543 544 v4l2_device_unregister(&radio->v4l2_dev); 545 kfree(radio->transfer_buffer); 546 kfree(radio); 547 } 548 549 /* File system interface */ 550 static const struct v4l2_file_operations usb_dsbr100_fops = { 551 .owner = THIS_MODULE, 552 .unlocked_ioctl = video_ioctl2, 553 }; 554 555 static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = { 556 .vidioc_querycap = vidioc_querycap, 557 .vidioc_g_tuner = vidioc_g_tuner, 558 .vidioc_s_tuner = vidioc_s_tuner, 559 .vidioc_g_frequency = vidioc_g_frequency, 560 .vidioc_s_frequency = vidioc_s_frequency, 561 .vidioc_queryctrl = vidioc_queryctrl, 562 .vidioc_g_ctrl = vidioc_g_ctrl, 563 .vidioc_s_ctrl = vidioc_s_ctrl, 564 .vidioc_g_audio = vidioc_g_audio, 565 .vidioc_s_audio = vidioc_s_audio, 566 .vidioc_g_input = vidioc_g_input, 567 .vidioc_s_input = vidioc_s_input, 568 }; 569 570 /* check if the device is present and register with v4l and usb if it is */ 571 static int usb_dsbr100_probe(struct usb_interface *intf, 572 const struct usb_device_id *id) 573 { 574 struct dsbr100_device *radio; 575 struct v4l2_device *v4l2_dev; 576 int retval; 577 578 radio = kzalloc(sizeof(struct dsbr100_device), GFP_KERNEL); 579 580 if (!radio) 581 return -ENOMEM; 582 583 radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL); 584 585 if (!(radio->transfer_buffer)) { 586 kfree(radio); 587 return -ENOMEM; 588 } 589 590 v4l2_dev = &radio->v4l2_dev; 591 v4l2_dev->release = usb_dsbr100_release; 592 593 retval = v4l2_device_register(&intf->dev, v4l2_dev); 594 if (retval < 0) { 595 v4l2_err(v4l2_dev, "couldn't register v4l2_device\n"); 596 kfree(radio->transfer_buffer); 597 kfree(radio); 598 return retval; 599 } 600 601 mutex_init(&radio->v4l2_lock); 602 strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name)); 603 radio->videodev.v4l2_dev = v4l2_dev; 604 radio->videodev.fops = &usb_dsbr100_fops; 605 radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops; 606 radio->videodev.release = video_device_release_empty; 607 radio->videodev.lock = &radio->v4l2_lock; 608 609 radio->usbdev = interface_to_usbdev(intf); 610 radio->curfreq = FREQ_MIN * FREQ_MUL; 611 radio->status = STOPPED; 612 613 video_set_drvdata(&radio->videodev, radio); 614 615 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr); 616 if (retval < 0) { 617 v4l2_err(v4l2_dev, "couldn't register video device\n"); 618 v4l2_device_unregister(v4l2_dev); 619 kfree(radio->transfer_buffer); 620 kfree(radio); 621 return -EIO; 622 } 623 usb_set_intfdata(intf, radio); 624 return 0; 625 } 626 627 static int __init dsbr100_init(void) 628 { 629 int retval = usb_register(&usb_dsbr100_driver); 630 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" 631 DRIVER_DESC "\n"); 632 return retval; 633 } 634 635 static void __exit dsbr100_exit(void) 636 { 637 usb_deregister(&usb_dsbr100_driver); 638 } 639 640 module_init (dsbr100_init); 641 module_exit (dsbr100_exit); 642 643 MODULE_AUTHOR( DRIVER_AUTHOR ); 644 MODULE_DESCRIPTION( DRIVER_DESC ); 645 MODULE_LICENSE("GPL"); 646 MODULE_VERSION(DRIVER_VERSION); 647