[media] tlg2300: allow multiple opens
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 16 Jul 2012 14:52:41 +0000 (11:52 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 5 Mar 2013 14:00:26 +0000 (11:00 -0300)
Due to a poor administration of the driver state it wasn't possible to open
a video or vbi device multiple times.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Huang Shijie <shijie8@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/usb/tlg2300/pd-common.h
drivers/media/usb/tlg2300/pd-video.c

index cb5cb0f..3010496 100644 (file)
@@ -26,7 +26,6 @@
 #define POSEIDON_STATE_ANALOG          (0x0001)
 #define POSEIDON_STATE_FM              (0x0002)
 #define POSEIDON_STATE_DVBT            (0x0004)
-#define POSEIDON_STATE_VBI             (0x0008)
 #define POSEIDON_STATE_DISCONNECT      (0x0080)
 
 #define PM_SUSPEND_DELAY       3
index 4c045b3..834428d 100644 (file)
@@ -1352,12 +1352,14 @@ static int pd_video_open(struct file *file)
        mutex_lock(&pd->lock);
        usb_autopm_get_interface(pd->interface);
 
-       if (vfd->vfl_type == VFL_TYPE_GRABBER
-               && !(pd->state & POSEIDON_STATE_ANALOG)) {
-               front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
-               if (!front)
-                       goto out;
-
+       if (pd->state && !(pd->state & POSEIDON_STATE_ANALOG)) {
+               ret = -EBUSY;
+               goto out;
+       }
+       front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
+       if (!front)
+               goto out;
+       if (vfd->vfl_type == VFL_TYPE_GRABBER) {
                pd->cur_transfer_mode   = usb_transfer_mode;/* bulk or iso */
                init_video_context(&pd->video_data.context);
 
@@ -1368,7 +1370,6 @@ static int pd_video_open(struct file *file)
                        goto out;
                }
 
-               pd->state               |= POSEIDON_STATE_ANALOG;
                front->type             = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                pd->video_data.users++;
                set_debug_mode(vfd, debug_mode);
@@ -1379,13 +1380,7 @@ static int pd_video_open(struct file *file)
                                V4L2_FIELD_INTERLACED,/* video is interlacd */
                                sizeof(struct videobuf_buffer),/*it's enough*/
                                front, NULL);
-       } else if (vfd->vfl_type == VFL_TYPE_VBI
-               && !(pd->state & POSEIDON_STATE_VBI)) {
-               front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
-               if (!front)
-                       goto out;
-
-               pd->state       |= POSEIDON_STATE_VBI;
+       } else {
                front->type     = V4L2_BUF_TYPE_VBI_CAPTURE;
                pd->vbi_data.front = front;
                pd->vbi_data.users++;
@@ -1396,19 +1391,15 @@ static int pd_video_open(struct file *file)
                                V4L2_FIELD_NONE, /* vbi is NONE mode */
                                sizeof(struct videobuf_buffer),
                                front, NULL);
-       } else {
-               /* maybe add FM support here */
-               log("other ");
-               ret = -EINVAL;
-               goto out;
        }
 
-       front->pd               = pd;
-       front->curr_frame       = NULL;
+       pd->state |= POSEIDON_STATE_ANALOG;
+       front->pd = pd;
+       front->curr_frame = NULL;
        INIT_LIST_HEAD(&front->active);
        spin_lock_init(&front->queue_lock);
 
-       file->private_data      = front;
+       file->private_data = front;
        kref_get(&pd->kref);
 
        mutex_unlock(&pd->lock);
@@ -1429,8 +1420,6 @@ static int pd_video_release(struct file *file)
        mutex_lock(&pd->lock);
 
        if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               pd->state &= ~POSEIDON_STATE_ANALOG;
-
                /* stop the device, and free the URBs */
                usb_transfer_stop(&pd->video_data);
                free_all_urb(&pd->video_data);
@@ -1442,10 +1431,11 @@ static int pd_video_release(struct file *file)
                pd->file_for_stream = NULL;
                pd->video_data.users--;
        } else if (front->type  == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               pd->state &= ~POSEIDON_STATE_VBI;
                pd->vbi_data.front = NULL;
                pd->vbi_data.users--;
        }
+       if (!pd->vbi_data.users && !pd->video_data.users)
+               pd->state &= ~POSEIDON_STATE_ANALOG;
        videobuf_stop(&front->q);
        videobuf_mmap_free(&front->q);