summaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/tlg2300
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-07-16 11:52:41 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-05 11:00:26 -0300
commit60c66b6f276ec2a1f76788f0833ad2bf366522b6 (patch)
treeb93f8f22566268cd124feeacd5f099015ee9e210 /drivers/media/usb/tlg2300
parentd4de6e406211028b9186e223b766bcd17579ec97 (diff)
downloadlinux-60c66b6f276ec2a1f76788f0833ad2bf366522b6.tar.bz2
[media] tlg2300: allow multiple opens
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>
Diffstat (limited to 'drivers/media/usb/tlg2300')
-rw-r--r--drivers/media/usb/tlg2300/pd-common.h1
-rw-r--r--drivers/media/usb/tlg2300/pd-video.c40
2 files changed, 15 insertions, 26 deletions
diff --git a/drivers/media/usb/tlg2300/pd-common.h b/drivers/media/usb/tlg2300/pd-common.h
index cb5cb0f70062..3010496787ab 100644
--- a/drivers/media/usb/tlg2300/pd-common.h
+++ b/drivers/media/usb/tlg2300/pd-common.h
@@ -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
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
index 4c045b3c1456..834428d90766 100644
--- a/drivers/media/usb/tlg2300/pd-video.c
+++ b/drivers/media/usb/tlg2300/pd-video.c
@@ -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);