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 120devices, 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 131static int usb_dsbr100_probe(struct usb_interface *intf, 132 const struct usb_device_id *id); 133static void usb_dsbr100_disconnect(struct usb_interface *intf); 134static int usb_dsbr100_suspend(struct usb_interface *intf, 135 pm_message_t message); 136static int usb_dsbr100_resume(struct usb_interface *intf); 137 138static int radio_nr = -1; 139module_param(radio_nr, int, 0); 140 141/* Data for one (physical) device */ 142struct 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 154static struct usb_device_id usb_dsbr100_device_table [] = { 155 { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, 156 { } /* Terminating entry */ 157}; 158 159MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table); 160 161/* USB subsystem interface */ 162static 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 */ 176static 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 206usb_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 */ 215static 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 245usb_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 */ 254static 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 297usb_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 306sees a stereo signal or not. Pity. */ 307static 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 327static 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 339static 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 362static int vidioc_s_tuner(struct file *file, void *priv, 363 struct v4l2_tuner *v) 364{ 365 return v->index ? -EINVAL : 0; 366} 367 368static 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 382static 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 392static 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 403static 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 416static 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 444static 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 455static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 456{ 457 *i = 0; 458 return 0; 459} 460 461static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 462{ 463 return i ? -EINVAL : 0; 464} 465 466static 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 */ 480static 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. */ 495static 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. */ 521static 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 */ 540static 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 */ 550static const struct v4l2_file_operations usb_dsbr100_fops = { 551 .owner = THIS_MODULE, 552 .unlocked_ioctl = video_ioctl2, 553}; 554 555static 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 */ 571static 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 627module_usb_driver(usb_dsbr100_driver); 628 629MODULE_AUTHOR( DRIVER_AUTHOR ); 630MODULE_DESCRIPTION( DRIVER_DESC ); 631MODULE_LICENSE("GPL"); 632MODULE_VERSION(DRIVER_VERSION); 633