diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-04-06 05:00:17 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-04-14 18:57:32 -0400 |
commit | ede197aac0c64021a0b2139d19edd8fa066530c2 (patch) | |
tree | 2865f3550473c1fe42c4bb462de21e575166fc7d /drivers/media | |
parent | 99c77aa4281c41fab255a4eb25ccc36a8c2e113d (diff) |
[media] hdpvr: remove hdpvr_fh and just use v4l2_fh
This prepares the driver for priority and control event handling.
This patch also checks for correct streaming ownership and it makes a
small improvement to the encoder_cmd ioctls: always zero 'flags' and
drop the memset of 'raw' as that is already done by the v4l2 core.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-video.c | 115 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr.h | 4 |
2 files changed, 46 insertions, 73 deletions
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index a89012720e5a..4bbcf480d5e7 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c | |||
@@ -35,10 +35,6 @@ | |||
35 | list_size(&dev->free_buff_list), \ | 35 | list_size(&dev->free_buff_list), \ |
36 | list_size(&dev->rec_buff_list)); } | 36 | list_size(&dev->rec_buff_list)); } |
37 | 37 | ||
38 | struct hdpvr_fh { | ||
39 | struct hdpvr_device *dev; | ||
40 | }; | ||
41 | |||
42 | static uint list_size(struct list_head *list) | 38 | static uint list_size(struct list_head *list) |
43 | { | 39 | { |
44 | struct list_head *tmp; | 40 | struct list_head *tmp; |
@@ -358,55 +354,21 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev) | |||
358 | * video 4 linux 2 file operations | 354 | * video 4 linux 2 file operations |
359 | */ | 355 | */ |
360 | 356 | ||
361 | static int hdpvr_open(struct file *file) | ||
362 | { | ||
363 | struct hdpvr_device *dev; | ||
364 | struct hdpvr_fh *fh; | ||
365 | int retval = -ENOMEM; | ||
366 | |||
367 | dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); | ||
368 | if (!dev) { | ||
369 | pr_err("open failing with with ENODEV\n"); | ||
370 | retval = -ENODEV; | ||
371 | goto err; | ||
372 | } | ||
373 | |||
374 | fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL); | ||
375 | if (!fh) { | ||
376 | v4l2_err(&dev->v4l2_dev, "Out of memory\n"); | ||
377 | goto err; | ||
378 | } | ||
379 | /* lock the device to allow correctly handling errors | ||
380 | * in resumption */ | ||
381 | mutex_lock(&dev->io_mutex); | ||
382 | dev->open_count++; | ||
383 | mutex_unlock(&dev->io_mutex); | ||
384 | |||
385 | fh->dev = dev; | ||
386 | |||
387 | /* save our object in the file's private structure */ | ||
388 | file->private_data = fh; | ||
389 | |||
390 | retval = 0; | ||
391 | err: | ||
392 | return retval; | ||
393 | } | ||
394 | |||
395 | static int hdpvr_release(struct file *file) | 357 | static int hdpvr_release(struct file *file) |
396 | { | 358 | { |
397 | struct hdpvr_fh *fh = file->private_data; | 359 | struct hdpvr_device *dev = video_drvdata(file); |
398 | struct hdpvr_device *dev = fh->dev; | ||
399 | 360 | ||
400 | if (!dev) | 361 | if (!dev) |
401 | return -ENODEV; | 362 | return -ENODEV; |
402 | 363 | ||
403 | mutex_lock(&dev->io_mutex); | 364 | mutex_lock(&dev->io_mutex); |
404 | if (!(--dev->open_count) && dev->status == STATUS_STREAMING) | 365 | if (file->private_data == dev->owner) { |
405 | hdpvr_stop_streaming(dev); | 366 | hdpvr_stop_streaming(dev); |
406 | 367 | dev->owner = NULL; | |
368 | } | ||
407 | mutex_unlock(&dev->io_mutex); | 369 | mutex_unlock(&dev->io_mutex); |
408 | 370 | ||
409 | return 0; | 371 | return v4l2_fh_release(file); |
410 | } | 372 | } |
411 | 373 | ||
412 | /* | 374 | /* |
@@ -416,8 +378,7 @@ static int hdpvr_release(struct file *file) | |||
416 | static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, | 378 | static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, |
417 | loff_t *pos) | 379 | loff_t *pos) |
418 | { | 380 | { |
419 | struct hdpvr_fh *fh = file->private_data; | 381 | struct hdpvr_device *dev = video_drvdata(file); |
420 | struct hdpvr_device *dev = fh->dev; | ||
421 | struct hdpvr_buffer *buf = NULL; | 382 | struct hdpvr_buffer *buf = NULL; |
422 | struct urb *urb; | 383 | struct urb *urb; |
423 | unsigned int ret = 0; | 384 | unsigned int ret = 0; |
@@ -440,6 +401,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, | |||
440 | mutex_unlock(&dev->io_mutex); | 401 | mutex_unlock(&dev->io_mutex); |
441 | goto err; | 402 | goto err; |
442 | } | 403 | } |
404 | dev->owner = file->private_data; | ||
443 | print_buffer_status(); | 405 | print_buffer_status(); |
444 | } | 406 | } |
445 | mutex_unlock(&dev->io_mutex); | 407 | mutex_unlock(&dev->io_mutex); |
@@ -518,8 +480,7 @@ err: | |||
518 | static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) | 480 | static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) |
519 | { | 481 | { |
520 | struct hdpvr_buffer *buf = NULL; | 482 | struct hdpvr_buffer *buf = NULL; |
521 | struct hdpvr_fh *fh = filp->private_data; | 483 | struct hdpvr_device *dev = video_drvdata(filp); |
522 | struct hdpvr_device *dev = fh->dev; | ||
523 | unsigned int mask = 0; | 484 | unsigned int mask = 0; |
524 | 485 | ||
525 | mutex_lock(&dev->io_mutex); | 486 | mutex_lock(&dev->io_mutex); |
@@ -534,6 +495,8 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) | |||
534 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | 495 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, |
535 | "start_streaming failed\n"); | 496 | "start_streaming failed\n"); |
536 | dev->status = STATUS_IDLE; | 497 | dev->status = STATUS_IDLE; |
498 | } else { | ||
499 | dev->owner = filp->private_data; | ||
537 | } | 500 | } |
538 | 501 | ||
539 | print_buffer_status(); | 502 | print_buffer_status(); |
@@ -555,7 +518,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) | |||
555 | 518 | ||
556 | static const struct v4l2_file_operations hdpvr_fops = { | 519 | static const struct v4l2_file_operations hdpvr_fops = { |
557 | .owner = THIS_MODULE, | 520 | .owner = THIS_MODULE, |
558 | .open = hdpvr_open, | 521 | .open = v4l2_fh_open, |
559 | .release = hdpvr_release, | 522 | .release = hdpvr_release, |
560 | .read = hdpvr_read, | 523 | .read = hdpvr_read, |
561 | .poll = hdpvr_poll, | 524 | .poll = hdpvr_poll, |
@@ -584,8 +547,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
584 | static int vidioc_s_std(struct file *file, void *private_data, | 547 | static int vidioc_s_std(struct file *file, void *private_data, |
585 | v4l2_std_id std) | 548 | v4l2_std_id std) |
586 | { | 549 | { |
587 | struct hdpvr_fh *fh = file->private_data; | 550 | struct hdpvr_device *dev = video_drvdata(file); |
588 | struct hdpvr_device *dev = fh->dev; | ||
589 | u8 std_type = 1; | 551 | u8 std_type = 1; |
590 | 552 | ||
591 | if (std & (V4L2_STD_NTSC | V4L2_STD_PAL_60)) | 553 | if (std & (V4L2_STD_NTSC | V4L2_STD_PAL_60)) |
@@ -603,8 +565,7 @@ static const char *iname[] = { | |||
603 | static int vidioc_enum_input(struct file *file, void *priv, | 565 | static int vidioc_enum_input(struct file *file, void *priv, |
604 | struct v4l2_input *i) | 566 | struct v4l2_input *i) |
605 | { | 567 | { |
606 | struct hdpvr_fh *fh = file->private_data; | 568 | struct hdpvr_device *dev = video_drvdata(file); |
607 | struct hdpvr_device *dev = fh->dev; | ||
608 | unsigned int n; | 569 | unsigned int n; |
609 | 570 | ||
610 | n = i->index; | 571 | n = i->index; |
@@ -626,8 +587,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
626 | static int vidioc_s_input(struct file *file, void *private_data, | 587 | static int vidioc_s_input(struct file *file, void *private_data, |
627 | unsigned int index) | 588 | unsigned int index) |
628 | { | 589 | { |
629 | struct hdpvr_fh *fh = file->private_data; | 590 | struct hdpvr_device *dev = video_drvdata(file); |
630 | struct hdpvr_device *dev = fh->dev; | ||
631 | int retval; | 591 | int retval; |
632 | 592 | ||
633 | if (index >= HDPVR_VIDEO_INPUTS) | 593 | if (index >= HDPVR_VIDEO_INPUTS) |
@@ -646,8 +606,7 @@ static int vidioc_s_input(struct file *file, void *private_data, | |||
646 | static int vidioc_g_input(struct file *file, void *private_data, | 606 | static int vidioc_g_input(struct file *file, void *private_data, |
647 | unsigned int *index) | 607 | unsigned int *index) |
648 | { | 608 | { |
649 | struct hdpvr_fh *fh = file->private_data; | 609 | struct hdpvr_device *dev = video_drvdata(file); |
650 | struct hdpvr_device *dev = fh->dev; | ||
651 | 610 | ||
652 | *index = dev->options.video_input; | 611 | *index = dev->options.video_input; |
653 | return 0; | 612 | return 0; |
@@ -680,8 +639,7 @@ static int vidioc_enumaudio(struct file *file, void *priv, | |||
680 | static int vidioc_s_audio(struct file *file, void *private_data, | 639 | static int vidioc_s_audio(struct file *file, void *private_data, |
681 | const struct v4l2_audio *audio) | 640 | const struct v4l2_audio *audio) |
682 | { | 641 | { |
683 | struct hdpvr_fh *fh = file->private_data; | 642 | struct hdpvr_device *dev = video_drvdata(file); |
684 | struct hdpvr_device *dev = fh->dev; | ||
685 | int retval; | 643 | int retval; |
686 | 644 | ||
687 | if (audio->index >= HDPVR_AUDIO_INPUTS) | 645 | if (audio->index >= HDPVR_AUDIO_INPUTS) |
@@ -700,8 +658,7 @@ static int vidioc_s_audio(struct file *file, void *private_data, | |||
700 | static int vidioc_g_audio(struct file *file, void *private_data, | 658 | static int vidioc_g_audio(struct file *file, void *private_data, |
701 | struct v4l2_audio *audio) | 659 | struct v4l2_audio *audio) |
702 | { | 660 | { |
703 | struct hdpvr_fh *fh = file->private_data; | 661 | struct hdpvr_device *dev = video_drvdata(file); |
704 | struct hdpvr_device *dev = fh->dev; | ||
705 | 662 | ||
706 | audio->index = dev->options.audio_input; | 663 | audio->index = dev->options.audio_input; |
707 | audio->capability = V4L2_AUDCAP_STEREO; | 664 | audio->capability = V4L2_AUDCAP_STEREO; |
@@ -833,8 +790,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, | |||
833 | static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, | 790 | static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, |
834 | struct v4l2_format *f) | 791 | struct v4l2_format *f) |
835 | { | 792 | { |
836 | struct hdpvr_fh *fh = file->private_data; | 793 | struct hdpvr_device *dev = video_drvdata(file); |
837 | struct hdpvr_device *dev = fh->dev; | ||
838 | struct hdpvr_video_info *vid_info; | 794 | struct hdpvr_video_info *vid_info; |
839 | 795 | ||
840 | if (!dev) | 796 | if (!dev) |
@@ -860,26 +816,44 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, | |||
860 | static int vidioc_encoder_cmd(struct file *filp, void *priv, | 816 | static int vidioc_encoder_cmd(struct file *filp, void *priv, |
861 | struct v4l2_encoder_cmd *a) | 817 | struct v4l2_encoder_cmd *a) |
862 | { | 818 | { |
863 | struct hdpvr_fh *fh = filp->private_data; | 819 | struct hdpvr_device *dev = video_drvdata(filp); |
864 | struct hdpvr_device *dev = fh->dev; | 820 | int res = 0; |
865 | int res; | ||
866 | 821 | ||
867 | mutex_lock(&dev->io_mutex); | 822 | mutex_lock(&dev->io_mutex); |
823 | a->flags = 0; | ||
868 | 824 | ||
869 | memset(&a->raw, 0, sizeof(a->raw)); | ||
870 | switch (a->cmd) { | 825 | switch (a->cmd) { |
871 | case V4L2_ENC_CMD_START: | 826 | case V4L2_ENC_CMD_START: |
872 | a->flags = 0; | 827 | if (dev->owner && filp->private_data != dev->owner) { |
828 | res = -EBUSY; | ||
829 | break; | ||
830 | } | ||
831 | if (dev->status == STATUS_STREAMING) | ||
832 | break; | ||
873 | res = hdpvr_start_streaming(dev); | 833 | res = hdpvr_start_streaming(dev); |
834 | if (!res) | ||
835 | dev->owner = filp->private_data; | ||
836 | else | ||
837 | dev->status = STATUS_IDLE; | ||
874 | break; | 838 | break; |
875 | case V4L2_ENC_CMD_STOP: | 839 | case V4L2_ENC_CMD_STOP: |
840 | if (dev->owner && filp->private_data != dev->owner) { | ||
841 | res = -EBUSY; | ||
842 | break; | ||
843 | } | ||
844 | if (dev->status == STATUS_IDLE) | ||
845 | break; | ||
876 | res = hdpvr_stop_streaming(dev); | 846 | res = hdpvr_stop_streaming(dev); |
847 | if (!res) | ||
848 | dev->owner = NULL; | ||
877 | break; | 849 | break; |
878 | default: | 850 | default: |
879 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | 851 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, |
880 | "Unsupported encoder cmd %d\n", a->cmd); | 852 | "Unsupported encoder cmd %d\n", a->cmd); |
881 | res = -EINVAL; | 853 | res = -EINVAL; |
854 | break; | ||
882 | } | 855 | } |
856 | |||
883 | mutex_unlock(&dev->io_mutex); | 857 | mutex_unlock(&dev->io_mutex); |
884 | return res; | 858 | return res; |
885 | } | 859 | } |
@@ -887,6 +861,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, | |||
887 | static int vidioc_try_encoder_cmd(struct file *filp, void *priv, | 861 | static int vidioc_try_encoder_cmd(struct file *filp, void *priv, |
888 | struct v4l2_encoder_cmd *a) | 862 | struct v4l2_encoder_cmd *a) |
889 | { | 863 | { |
864 | a->flags = 0; | ||
890 | switch (a->cmd) { | 865 | switch (a->cmd) { |
891 | case V4L2_ENC_CMD_START: | 866 | case V4L2_ENC_CMD_START: |
892 | case V4L2_ENC_CMD_STOP: | 867 | case V4L2_ENC_CMD_STOP: |
@@ -935,8 +910,6 @@ static void hdpvr_device_release(struct video_device *vdev) | |||
935 | } | 910 | } |
936 | 911 | ||
937 | static const struct video_device hdpvr_video_template = { | 912 | static const struct video_device hdpvr_video_template = { |
938 | /* .type = VFL_TYPE_GRABBER, */ | ||
939 | /* .type2 = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */ | ||
940 | .fops = &hdpvr_fops, | 913 | .fops = &hdpvr_fops, |
941 | .release = hdpvr_device_release, | 914 | .release = hdpvr_device_release, |
942 | .ioctl_ops = &hdpvr_ioctl_ops, | 915 | .ioctl_ops = &hdpvr_ioctl_ops, |
@@ -1031,9 +1004,9 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, | |||
1031 | goto error; | 1004 | goto error; |
1032 | } | 1005 | } |
1033 | 1006 | ||
1034 | *(dev->video_dev) = hdpvr_video_template; | 1007 | *dev->video_dev = hdpvr_video_template; |
1035 | strcpy(dev->video_dev->name, "Hauppauge HD PVR"); | 1008 | strcpy(dev->video_dev->name, "Hauppauge HD PVR"); |
1036 | dev->video_dev->parent = parent; | 1009 | dev->video_dev->v4l2_dev = &dev->v4l2_dev; |
1037 | video_set_drvdata(dev->video_dev, dev); | 1010 | video_set_drvdata(dev->video_dev, dev); |
1038 | 1011 | ||
1039 | res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum); | 1012 | res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum); |
diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h index 2a4deab70762..945009356127 100644 --- a/drivers/media/usb/hdpvr/hdpvr.h +++ b/drivers/media/usb/hdpvr/hdpvr.h | |||
@@ -85,8 +85,6 @@ struct hdpvr_device { | |||
85 | 85 | ||
86 | /* holds the current device status */ | 86 | /* holds the current device status */ |
87 | __u8 status; | 87 | __u8 status; |
88 | /* count the number of openers */ | ||
89 | uint open_count; | ||
90 | 88 | ||
91 | /* holds the cureent set options */ | 89 | /* holds the cureent set options */ |
92 | struct hdpvr_options options; | 90 | struct hdpvr_options options; |
@@ -107,6 +105,8 @@ struct hdpvr_device { | |||
107 | struct workqueue_struct *workqueue; | 105 | struct workqueue_struct *workqueue; |
108 | /**/ | 106 | /**/ |
109 | struct work_struct worker; | 107 | struct work_struct worker; |
108 | /* current stream owner */ | ||
109 | struct v4l2_fh *owner; | ||
110 | 110 | ||
111 | /* I2C adapter */ | 111 | /* I2C adapter */ |
112 | struct i2c_adapter i2c_adapter; | 112 | struct i2c_adapter i2c_adapter; |