aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2011-01-17 18:25:11 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-22 15:38:09 -0400
commit13099294973b14f07915d0342af2be8fa0af589b (patch)
tree0b755cadc08407c29f0046c83f03df40e7c568cf
parente64d07c92daa5c7973c1d4433f939a4e0fa3beb9 (diff)
[media] dsbr100: ensure correct disconnect sequence
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/radio/dsbr100.c59
1 files changed, 12 insertions, 47 deletions
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index bf2dd6ff042..3d8cc425fa6 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -129,7 +129,7 @@ devices, that would be 76 and 91. */
129#define STARTED 0 129#define STARTED 0
130#define STOPPED 1 130#define STOPPED 1
131 131
132#define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev) 132#define v4l2_dev_to_radio(d) container_of(d, struct dsbr100_device, v4l2_dev)
133 133
134static int usb_dsbr100_probe(struct usb_interface *intf, 134static int usb_dsbr100_probe(struct usb_interface *intf,
135 const struct usb_device_id *id); 135 const struct usb_device_id *id);
@@ -151,7 +151,6 @@ struct dsbr100_device {
151 struct mutex v4l2_lock; 151 struct mutex v4l2_lock;
152 int curfreq; 152 int curfreq;
153 int stereo; 153 int stereo;
154 int removed;
155 int status; 154 int status;
156}; 155};
157 156
@@ -346,10 +345,6 @@ static int vidioc_g_tuner(struct file *file, void *priv,
346{ 345{
347 struct dsbr100_device *radio = video_drvdata(file); 346 struct dsbr100_device *radio = video_drvdata(file);
348 347
349 /* safety check */
350 if (radio->removed)
351 return -EIO;
352
353 if (v->index > 0) 348 if (v->index > 0)
354 return -EINVAL; 349 return -EINVAL;
355 350
@@ -371,16 +366,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
371static int vidioc_s_tuner(struct file *file, void *priv, 366static int vidioc_s_tuner(struct file *file, void *priv,
372 struct v4l2_tuner *v) 367 struct v4l2_tuner *v)
373{ 368{
374 struct dsbr100_device *radio = video_drvdata(file); 369 return v->index ? -EINVAL : 0;
375
376 /* safety check */
377 if (radio->removed)
378 return -EIO;
379
380 if (v->index > 0)
381 return -EINVAL;
382
383 return 0;
384} 370}
385 371
386static int vidioc_s_frequency(struct file *file, void *priv, 372static int vidioc_s_frequency(struct file *file, void *priv,
@@ -389,10 +375,6 @@ static int vidioc_s_frequency(struct file *file, void *priv,
389 struct dsbr100_device *radio = video_drvdata(file); 375 struct dsbr100_device *radio = video_drvdata(file);
390 int retval; 376 int retval;
391 377
392 /* safety check */
393 if (radio->removed)
394 return -EIO;
395
396 radio->curfreq = f->frequency; 378 radio->curfreq = f->frequency;
397 379
398 retval = dsbr100_setfreq(radio); 380 retval = dsbr100_setfreq(radio);
@@ -406,10 +388,6 @@ static int vidioc_g_frequency(struct file *file, void *priv,
406{ 388{
407 struct dsbr100_device *radio = video_drvdata(file); 389 struct dsbr100_device *radio = video_drvdata(file);
408 390
409 /* safety check */
410 if (radio->removed)
411 return -EIO;
412
413 f->type = V4L2_TUNER_RADIO; 391 f->type = V4L2_TUNER_RADIO;
414 f->frequency = radio->curfreq; 392 f->frequency = radio->curfreq;
415 return 0; 393 return 0;
@@ -431,10 +409,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
431{ 409{
432 struct dsbr100_device *radio = video_drvdata(file); 410 struct dsbr100_device *radio = video_drvdata(file);
433 411
434 /* safety check */
435 if (radio->removed)
436 return -EIO;
437
438 switch (ctrl->id) { 412 switch (ctrl->id) {
439 case V4L2_CID_AUDIO_MUTE: 413 case V4L2_CID_AUDIO_MUTE:
440 ctrl->value = radio->status; 414 ctrl->value = radio->status;
@@ -449,10 +423,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
449 struct dsbr100_device *radio = video_drvdata(file); 423 struct dsbr100_device *radio = video_drvdata(file);
450 int retval; 424 int retval;
451 425
452 /* safety check */
453 if (radio->removed)
454 return -EIO;
455
456 switch (ctrl->id) { 426 switch (ctrl->id) {
457 case V4L2_CID_AUDIO_MUTE: 427 case V4L2_CID_AUDIO_MUTE:
458 if (ctrl->value) { 428 if (ctrl->value) {
@@ -494,17 +464,13 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
494 464
495static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 465static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
496{ 466{
497 if (i != 0) 467 return i ? -EINVAL : 0;
498 return -EINVAL;
499 return 0;
500} 468}
501 469
502static int vidioc_s_audio(struct file *file, void *priv, 470static int vidioc_s_audio(struct file *file, void *priv,
503 struct v4l2_audio *a) 471 struct v4l2_audio *a)
504{ 472{
505 if (a->index != 0) 473 return a->index ? -EINVAL : 0;
506 return -EINVAL;
507 return 0;
508} 474}
509 475
510/* USB subsystem interface begins here */ 476/* USB subsystem interface begins here */
@@ -519,14 +485,13 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
519{ 485{
520 struct dsbr100_device *radio = usb_get_intfdata(intf); 486 struct dsbr100_device *radio = usb_get_intfdata(intf);
521 487
522 usb_set_intfdata(intf, NULL); 488 v4l2_device_get(&radio->v4l2_dev);
523
524 mutex_lock(&radio->v4l2_lock); 489 mutex_lock(&radio->v4l2_lock);
525 radio->removed = 1; 490 usb_set_intfdata(intf, NULL);
526 mutex_unlock(&radio->v4l2_lock);
527
528 video_unregister_device(&radio->videodev); 491 video_unregister_device(&radio->videodev);
529 v4l2_device_disconnect(&radio->v4l2_dev); 492 v4l2_device_disconnect(&radio->v4l2_dev);
493 mutex_unlock(&radio->v4l2_lock);
494 v4l2_device_put(&radio->v4l2_dev);
530} 495}
531 496
532 497
@@ -576,9 +541,9 @@ static int usb_dsbr100_resume(struct usb_interface *intf)
576} 541}
577 542
578/* free data structures */ 543/* free data structures */
579static void usb_dsbr100_video_device_release(struct video_device *videodev) 544static void usb_dsbr100_release(struct v4l2_device *v4l2_dev)
580{ 545{
581 struct dsbr100_device *radio = videodev_to_radio(videodev); 546 struct dsbr100_device *radio = v4l2_dev_to_radio(v4l2_dev);
582 547
583 v4l2_device_unregister(&radio->v4l2_dev); 548 v4l2_device_unregister(&radio->v4l2_dev);
584 kfree(radio->transfer_buffer); 549 kfree(radio->transfer_buffer);
@@ -627,6 +592,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
627 } 592 }
628 593
629 v4l2_dev = &radio->v4l2_dev; 594 v4l2_dev = &radio->v4l2_dev;
595 v4l2_dev->release = usb_dsbr100_release;
630 596
631 retval = v4l2_device_register(&intf->dev, v4l2_dev); 597 retval = v4l2_device_register(&intf->dev, v4l2_dev);
632 if (retval < 0) { 598 if (retval < 0) {
@@ -641,10 +607,9 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
641 radio->videodev.v4l2_dev = v4l2_dev; 607 radio->videodev.v4l2_dev = v4l2_dev;
642 radio->videodev.fops = &usb_dsbr100_fops; 608 radio->videodev.fops = &usb_dsbr100_fops;
643 radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops; 609 radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops;
644 radio->videodev.release = usb_dsbr100_video_device_release; 610 radio->videodev.release = video_device_release_empty;
645 radio->videodev.lock = &radio->v4l2_lock; 611 radio->videodev.lock = &radio->v4l2_lock;
646 612
647 radio->removed = 0;
648 radio->usbdev = interface_to_usbdev(intf); 613 radio->usbdev = interface_to_usbdev(intf);
649 radio->curfreq = FREQ_MIN * FREQ_MUL; 614 radio->curfreq = FREQ_MIN * FREQ_MUL;
650 radio->status = STOPPED; 615 radio->status = STOPPED;