[media] pwc: Allow multiple opens
authorHans de Goede <hdegoede@redhat.com>
Sun, 26 Jun 2011 15:13:44 +0000 (12:13 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 27 Jul 2011 20:53:44 +0000 (17:53 -0300)
Allow multiple opens of the /dev/video node so that control panel apps
can be open to-gether with streaming apps.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pwc/pwc.h

index b591b723f5a1437a245162f6cd4a6f62c76e8485..a6b5fde5c3ad20dd007bb4304ccc844505771e26 100644 (file)
@@ -678,12 +678,6 @@ static int pwc_video_open(struct file *file)
        if (!pdev->udev)
                return -ENODEV;
 
-       if (pdev->vopen) {
-               PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
-               return -EBUSY;
-       }
-
-       pdev->vopen++;
        file->private_data = vdev;
        PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
        return 0;
@@ -718,10 +712,12 @@ static int pwc_video_close(struct file *file)
        PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
        pdev = video_get_drvdata(vdev);
-       vb2_queue_release(&pdev->vb_queue);
-       pdev->vopen--;
+       if (pdev->capt_file == file) {
+               vb2_queue_release(&pdev->vb_queue);
+               pdev->capt_file = NULL;
+       }
 
-       PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
+       PWC_DEBUG_OPEN("<< video_close()\n");
        return 0;
 }
 
@@ -734,6 +730,12 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
        if (!pdev->udev)
                return -ENODEV;
 
+       if (pdev->capt_file != NULL &&
+           pdev->capt_file != file)
+               return -EBUSY;
+
+       pdev->capt_file = file;
+
        return vb2_read(&pdev->vb_queue, buf, count, ppos,
                        file->f_flags & O_NONBLOCK);
 }
@@ -754,6 +756,9 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
        struct video_device *vdev = file->private_data;
        struct pwc_device *pdev = video_get_drvdata(vdev);
 
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
        return vb2_mmap(&pdev->vb_queue, vma);
 }
 
index 8bd0a681990d71a1a80a3499649c26713593580a..834055b71e0418352d100a650d57bddeb7a407c8 100644 (file)
@@ -284,13 +284,21 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
 }
 
 /* ioctl(VIDIOC_SET_FMT) */
-static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+
+static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
 {
+       struct pwc_device *pdev = video_drvdata(file);
        int ret, fps, snapshot, compression, pixelformat;
 
        if (!pdev->udev)
                return -ENODEV;
 
+       if (pdev->capt_file != NULL &&
+           pdev->capt_file != file)
+               return -EBUSY;
+
+       pdev->capt_file = file;
+
        ret = pwc_vidioc_try_fmt(pdev, f);
        if (ret<0)
                return ret;
@@ -678,18 +686,17 @@ static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *
        return pwc_vidioc_try_fmt(pdev, f);
 }
 
-static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-
-       return pwc_vidioc_set_fmt(pdev, f);
-}
-
 static int pwc_reqbufs(struct file *file, void *fh,
                       struct v4l2_requestbuffers *rb)
 {
        struct pwc_device *pdev = video_drvdata(file);
 
+       if (pdev->capt_file != NULL &&
+           pdev->capt_file != file)
+               return -EBUSY;
+
+       pdev->capt_file = file;
+
        return vb2_reqbufs(&pdev->vb_queue, rb);
 }
 
@@ -707,6 +714,9 @@ static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
        if (!pdev->udev)
                return -ENODEV;
 
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
        return vb2_qbuf(&pdev->vb_queue, buf);
 }
 
@@ -717,6 +727,9 @@ static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
        if (!pdev->udev)
                return -ENODEV;
 
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
        return vb2_dqbuf(&pdev->vb_queue, buf, file->f_flags & O_NONBLOCK);
 }
 
@@ -727,6 +740,9 @@ static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
        if (!pdev->udev)
                return -ENODEV;
 
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
        return vb2_streamon(&pdev->vb_queue, i);
 }
 
@@ -737,6 +753,9 @@ static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
        if (!pdev->udev)
                return -ENODEV;
 
+       if (pdev->capt_file != file)
+               return -EBUSY;
+
        return vb2_streamoff(&pdev->vb_queue, i);
 }
 
index 8d82c6aac42c8672bbce6e4e162c54eadf3352fe..d65cd14ef9f21eff0bba43d4b07814bd62921f15 100644 (file)
@@ -160,7 +160,7 @@ struct pwc_device
        char serial[30];        /* serial number (string) */
 
        /*** Video data ***/
-       int vopen;              /* flag */
+       struct file *capt_file; /* file doing video capture */
        int vendpoint;          /* video isoc endpoint */
        int vcinterface;        /* video control interface */
        int valternate;         /* alternate interface needed */