diff options
Diffstat (limited to 'drivers/media/radio/radio-mr800.c')
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 123 |
1 files changed, 91 insertions, 32 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 256cbeffdcb6..e730eddb2bb5 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
@@ -72,6 +72,11 @@ MODULE_LICENSE("GPL"); | |||
72 | #define USB_AMRADIO_VENDOR 0x07ca | 72 | #define USB_AMRADIO_VENDOR 0x07ca |
73 | #define USB_AMRADIO_PRODUCT 0xb800 | 73 | #define USB_AMRADIO_PRODUCT 0xb800 |
74 | 74 | ||
75 | /* dev_warn macro with driver name */ | ||
76 | #define MR800_DRIVER_NAME "radio-mr800" | ||
77 | #define amradio_dev_warn(dev, fmt, arg...) \ | ||
78 | dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg) | ||
79 | |||
75 | /* Probably USB_TIMEOUT should be modified in module parameter */ | 80 | /* Probably USB_TIMEOUT should be modified in module parameter */ |
76 | #define BUFFER_LENGTH 8 | 81 | #define BUFFER_LENGTH 8 |
77 | #define USB_TIMEOUT 500 | 82 | #define USB_TIMEOUT 500 |
@@ -154,14 +159,14 @@ MODULE_DEVICE_TABLE(usb, usb_amradio_device_table); | |||
154 | 159 | ||
155 | /* USB subsystem interface */ | 160 | /* USB subsystem interface */ |
156 | static struct usb_driver usb_amradio_driver = { | 161 | static struct usb_driver usb_amradio_driver = { |
157 | .name = "radio-mr800", | 162 | .name = MR800_DRIVER_NAME, |
158 | .probe = usb_amradio_probe, | 163 | .probe = usb_amradio_probe, |
159 | .disconnect = usb_amradio_disconnect, | 164 | .disconnect = usb_amradio_disconnect, |
160 | .suspend = usb_amradio_suspend, | 165 | .suspend = usb_amradio_suspend, |
161 | .resume = usb_amradio_resume, | 166 | .resume = usb_amradio_resume, |
162 | .reset_resume = usb_amradio_resume, | 167 | .reset_resume = usb_amradio_resume, |
163 | .id_table = usb_amradio_device_table, | 168 | .id_table = usb_amradio_device_table, |
164 | .supports_autosuspend = 1, | 169 | .supports_autosuspend = 0, |
165 | }; | 170 | }; |
166 | 171 | ||
167 | /* switch on radio. Send 8 bytes to device. */ | 172 | /* switch on radio. Send 8 bytes to device. */ |
@@ -202,6 +207,10 @@ static int amradio_stop(struct amradio_device *radio) | |||
202 | int retval; | 207 | int retval; |
203 | int size; | 208 | int size; |
204 | 209 | ||
210 | /* safety check */ | ||
211 | if (radio->removed) | ||
212 | return -EIO; | ||
213 | |||
205 | mutex_lock(&radio->lock); | 214 | mutex_lock(&radio->lock); |
206 | 215 | ||
207 | radio->buffer[0] = 0x00; | 216 | radio->buffer[0] = 0x00; |
@@ -235,6 +244,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) | |||
235 | int size; | 244 | int size; |
236 | unsigned short freq_send = 0x13 + (freq >> 3) / 25; | 245 | unsigned short freq_send = 0x13 + (freq >> 3) / 25; |
237 | 246 | ||
247 | /* safety check */ | ||
248 | if (radio->removed) | ||
249 | return -EIO; | ||
250 | |||
238 | mutex_lock(&radio->lock); | 251 | mutex_lock(&radio->lock); |
239 | 252 | ||
240 | radio->buffer[0] = 0x00; | 253 | radio->buffer[0] = 0x00; |
@@ -288,18 +301,12 @@ static void usb_amradio_disconnect(struct usb_interface *intf) | |||
288 | { | 301 | { |
289 | struct amradio_device *radio = usb_get_intfdata(intf); | 302 | struct amradio_device *radio = usb_get_intfdata(intf); |
290 | 303 | ||
291 | usb_set_intfdata(intf, NULL); | 304 | mutex_lock(&radio->lock); |
305 | radio->removed = 1; | ||
306 | mutex_unlock(&radio->lock); | ||
292 | 307 | ||
293 | if (radio) { | 308 | usb_set_intfdata(intf, NULL); |
294 | video_unregister_device(radio->videodev); | 309 | video_unregister_device(radio->videodev); |
295 | radio->videodev = NULL; | ||
296 | if (radio->users) { | ||
297 | kfree(radio->buffer); | ||
298 | kfree(radio); | ||
299 | } else { | ||
300 | radio->removed = 1; | ||
301 | } | ||
302 | } | ||
303 | } | 310 | } |
304 | 311 | ||
305 | /* vidioc_querycap - query device capabilities */ | 312 | /* vidioc_querycap - query device capabilities */ |
@@ -320,6 +327,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
320 | { | 327 | { |
321 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | 328 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); |
322 | 329 | ||
330 | /* safety check */ | ||
331 | if (radio->removed) | ||
332 | return -EIO; | ||
333 | |||
323 | if (v->index > 0) | 334 | if (v->index > 0) |
324 | return -EINVAL; | 335 | return -EINVAL; |
325 | 336 | ||
@@ -346,6 +357,12 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
346 | static int vidioc_s_tuner(struct file *file, void *priv, | 357 | static int vidioc_s_tuner(struct file *file, void *priv, |
347 | struct v4l2_tuner *v) | 358 | struct v4l2_tuner *v) |
348 | { | 359 | { |
360 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
361 | |||
362 | /* safety check */ | ||
363 | if (radio->removed) | ||
364 | return -EIO; | ||
365 | |||
349 | if (v->index > 0) | 366 | if (v->index > 0) |
350 | return -EINVAL; | 367 | return -EINVAL; |
351 | return 0; | 368 | return 0; |
@@ -357,9 +374,14 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
357 | { | 374 | { |
358 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | 375 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); |
359 | 376 | ||
377 | /* safety check */ | ||
378 | if (radio->removed) | ||
379 | return -EIO; | ||
380 | |||
360 | radio->curfreq = f->frequency; | 381 | radio->curfreq = f->frequency; |
361 | if (amradio_setfreq(radio, radio->curfreq) < 0) | 382 | if (amradio_setfreq(radio, radio->curfreq) < 0) |
362 | warn("Set frequency failed"); | 383 | amradio_dev_warn(&radio->videodev->dev, |
384 | "set frequency failed\n"); | ||
363 | return 0; | 385 | return 0; |
364 | } | 386 | } |
365 | 387 | ||
@@ -369,6 +391,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
369 | { | 391 | { |
370 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | 392 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); |
371 | 393 | ||
394 | /* safety check */ | ||
395 | if (radio->removed) | ||
396 | return -EIO; | ||
397 | |||
372 | f->type = V4L2_TUNER_RADIO; | 398 | f->type = V4L2_TUNER_RADIO; |
373 | f->frequency = radio->curfreq; | 399 | f->frequency = radio->curfreq; |
374 | return 0; | 400 | return 0; |
@@ -382,8 +408,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
382 | 408 | ||
383 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 409 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { |
384 | if (qc->id && qc->id == radio_qctrl[i].id) { | 410 | if (qc->id && qc->id == radio_qctrl[i].id) { |
385 | memcpy(qc, &(radio_qctrl[i]), | 411 | memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); |
386 | sizeof(*qc)); | ||
387 | return 0; | 412 | return 0; |
388 | } | 413 | } |
389 | } | 414 | } |
@@ -396,6 +421,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
396 | { | 421 | { |
397 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | 422 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); |
398 | 423 | ||
424 | /* safety check */ | ||
425 | if (radio->removed) | ||
426 | return -EIO; | ||
427 | |||
399 | switch (ctrl->id) { | 428 | switch (ctrl->id) { |
400 | case V4L2_CID_AUDIO_MUTE: | 429 | case V4L2_CID_AUDIO_MUTE: |
401 | ctrl->value = radio->muted; | 430 | ctrl->value = radio->muted; |
@@ -410,16 +439,22 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
410 | { | 439 | { |
411 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | 440 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); |
412 | 441 | ||
442 | /* safety check */ | ||
443 | if (radio->removed) | ||
444 | return -EIO; | ||
445 | |||
413 | switch (ctrl->id) { | 446 | switch (ctrl->id) { |
414 | case V4L2_CID_AUDIO_MUTE: | 447 | case V4L2_CID_AUDIO_MUTE: |
415 | if (ctrl->value) { | 448 | if (ctrl->value) { |
416 | if (amradio_stop(radio) < 0) { | 449 | if (amradio_stop(radio) < 0) { |
417 | warn("amradio_stop() failed"); | 450 | amradio_dev_warn(&radio->videodev->dev, |
451 | "amradio_stop failed\n"); | ||
418 | return -1; | 452 | return -1; |
419 | } | 453 | } |
420 | } else { | 454 | } else { |
421 | if (amradio_start(radio) < 0) { | 455 | if (amradio_start(radio) < 0) { |
422 | warn("amradio_start() failed"); | 456 | amradio_dev_warn(&radio->videodev->dev, |
457 | "amradio_start failed\n"); | ||
423 | return -1; | 458 | return -1; |
424 | } | 459 | } |
425 | } | 460 | } |
@@ -475,30 +510,38 @@ static int usb_amradio_open(struct inode *inode, struct file *file) | |||
475 | radio->muted = 1; | 510 | radio->muted = 1; |
476 | 511 | ||
477 | if (amradio_start(radio) < 0) { | 512 | if (amradio_start(radio) < 0) { |
478 | warn("Radio did not start up properly"); | 513 | amradio_dev_warn(&radio->videodev->dev, |
514 | "radio did not start up properly\n"); | ||
479 | radio->users = 0; | 515 | radio->users = 0; |
480 | unlock_kernel(); | 516 | unlock_kernel(); |
481 | return -EIO; | 517 | return -EIO; |
482 | } | 518 | } |
483 | if (amradio_setfreq(radio, radio->curfreq) < 0) | 519 | if (amradio_setfreq(radio, radio->curfreq) < 0) |
484 | warn("Set frequency failed"); | 520 | amradio_dev_warn(&radio->videodev->dev, |
521 | "set frequency failed\n"); | ||
485 | 522 | ||
486 | unlock_kernel(); | 523 | unlock_kernel(); |
487 | return 0; | 524 | return 0; |
488 | } | 525 | } |
489 | 526 | ||
490 | /*close device - free driver structures */ | 527 | /*close device */ |
491 | static int usb_amradio_close(struct inode *inode, struct file *file) | 528 | static int usb_amradio_close(struct inode *inode, struct file *file) |
492 | { | 529 | { |
493 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | 530 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); |
531 | int retval; | ||
494 | 532 | ||
495 | if (!radio) | 533 | if (!radio) |
496 | return -ENODEV; | 534 | return -ENODEV; |
535 | |||
497 | radio->users = 0; | 536 | radio->users = 0; |
498 | if (radio->removed) { | 537 | |
499 | kfree(radio->buffer); | 538 | if (!radio->removed) { |
500 | kfree(radio); | 539 | retval = amradio_stop(radio); |
540 | if (retval < 0) | ||
541 | amradio_dev_warn(&radio->videodev->dev, | ||
542 | "amradio_stop failed\n"); | ||
501 | } | 543 | } |
544 | |||
502 | return 0; | 545 | return 0; |
503 | } | 546 | } |
504 | 547 | ||
@@ -508,9 +551,9 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) | |||
508 | struct amradio_device *radio = usb_get_intfdata(intf); | 551 | struct amradio_device *radio = usb_get_intfdata(intf); |
509 | 552 | ||
510 | if (amradio_stop(radio) < 0) | 553 | if (amradio_stop(radio) < 0) |
511 | warn("amradio_stop() failed"); | 554 | dev_warn(&intf->dev, "amradio_stop failed\n"); |
512 | 555 | ||
513 | info("radio-mr800: Going into suspend.."); | 556 | dev_info(&intf->dev, "going into suspend..\n"); |
514 | 557 | ||
515 | return 0; | 558 | return 0; |
516 | } | 559 | } |
@@ -521,9 +564,9 @@ static int usb_amradio_resume(struct usb_interface *intf) | |||
521 | struct amradio_device *radio = usb_get_intfdata(intf); | 564 | struct amradio_device *radio = usb_get_intfdata(intf); |
522 | 565 | ||
523 | if (amradio_start(radio) < 0) | 566 | if (amradio_start(radio) < 0) |
524 | warn("amradio_start() failed"); | 567 | dev_warn(&intf->dev, "amradio_start failed\n"); |
525 | 568 | ||
526 | info("radio-mr800: Coming out of suspend.."); | 569 | dev_info(&intf->dev, "coming out of suspend..\n"); |
527 | 570 | ||
528 | return 0; | 571 | return 0; |
529 | } | 572 | } |
@@ -555,12 +598,24 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { | |||
555 | .vidioc_s_input = vidioc_s_input, | 598 | .vidioc_s_input = vidioc_s_input, |
556 | }; | 599 | }; |
557 | 600 | ||
601 | static void usb_amradio_device_release(struct video_device *videodev) | ||
602 | { | ||
603 | struct amradio_device *radio = video_get_drvdata(videodev); | ||
604 | |||
605 | /* we call v4l to free radio->videodev */ | ||
606 | video_device_release(videodev); | ||
607 | |||
608 | /* free rest memory */ | ||
609 | kfree(radio->buffer); | ||
610 | kfree(radio); | ||
611 | } | ||
612 | |||
558 | /* V4L2 interface */ | 613 | /* V4L2 interface */ |
559 | static struct video_device amradio_videodev_template = { | 614 | static struct video_device amradio_videodev_template = { |
560 | .name = "AverMedia MR 800 USB FM Radio", | 615 | .name = "AverMedia MR 800 USB FM Radio", |
561 | .fops = &usb_amradio_fops, | 616 | .fops = &usb_amradio_fops, |
562 | .ioctl_ops = &usb_amradio_ioctl_ops, | 617 | .ioctl_ops = &usb_amradio_ioctl_ops, |
563 | .release = video_device_release, | 618 | .release = usb_amradio_device_release, |
564 | }; | 619 | }; |
565 | 620 | ||
566 | /* check if the device is present and register with v4l and | 621 | /* check if the device is present and register with v4l and |
@@ -602,7 +657,7 @@ static int usb_amradio_probe(struct usb_interface *intf, | |||
602 | 657 | ||
603 | video_set_drvdata(radio->videodev, radio); | 658 | video_set_drvdata(radio->videodev, radio); |
604 | if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { | 659 | if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { |
605 | warn("Could not register video device"); | 660 | dev_warn(&intf->dev, "could not register video device\n"); |
606 | video_device_release(radio->videodev); | 661 | video_device_release(radio->videodev); |
607 | kfree(radio->buffer); | 662 | kfree(radio->buffer); |
608 | kfree(radio); | 663 | kfree(radio); |
@@ -617,9 +672,13 @@ static int __init amradio_init(void) | |||
617 | { | 672 | { |
618 | int retval = usb_register(&usb_amradio_driver); | 673 | int retval = usb_register(&usb_amradio_driver); |
619 | 674 | ||
620 | info(DRIVER_VERSION " " DRIVER_DESC); | 675 | pr_info(KBUILD_MODNAME |
676 | ": version " DRIVER_VERSION " " DRIVER_DESC "\n"); | ||
677 | |||
621 | if (retval) | 678 | if (retval) |
622 | err("usb_register failed. Error number %d", retval); | 679 | pr_err(KBUILD_MODNAME |
680 | ": usb_register failed. Error number %d\n", retval); | ||
681 | |||
623 | return retval; | 682 | return retval; |
624 | } | 683 | } |
625 | 684 | ||