Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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