aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2014-03-09 20:33:21 +0100
committerHans Verkuil <hans.verkuil@cisco.com>2014-03-09 20:33:21 +0100
commita752e4030bb15c2008305dd4f8a3623945a8e00e (patch)
treef4f30328917b075d48a4854977110c0911fa6836
parent4387aeea5c4bd5de0d4bacdfe715b04431cf1183 (diff)
wipuvc2
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c1
-rw-r--r--drivers/media/usb/uvc/uvc_queue.c63
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c239
-rw-r--r--drivers/media/usb/uvc/uvc_video.c20
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h11
5 files changed, 55 insertions, 279 deletions
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index a93c418f398a..79c43dfcbbed 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1745,6 +1745,7 @@ static int uvc_register_video(struct uvc_device *dev,
vdev->fops = &uvc_fops;
vdev->ioctl_ops = &uvc_ioctl_ops;
vdev->release = uvc_release;
+ vdev->queue = &stream->queue.queue;
set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
vdev->vfl_dir = VFL_DIR_TX;
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 6e92d2080255..dbae00e3c48a 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -117,18 +117,22 @@ static void uvc_buffer_finish(struct vb2_buffer *vb)
uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
}
-static void uvc_wait_prepare(struct vb2_queue *vq)
+static int uvc_start_streaming(struct vb2_queue *q, unsigned int count)
{
- struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+ struct uvc_video_queue *queue = vb2_get_drv_priv(q);
+ struct uvc_streaming *stream =
+ container_of(queue, struct uvc_streaming, queue);
- mutex_unlock(&queue->mutex);
+ return uvc_video_enable(stream, 1);
}
-static void uvc_wait_finish(struct vb2_queue *vq)
+static int uvc_stop_streaming(struct vb2_queue *q)
{
- struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+ struct uvc_video_queue *queue = vb2_get_drv_priv(q);
+ struct uvc_streaming *stream =
+ container_of(queue, struct uvc_streaming, queue);
- mutex_lock(&queue->mutex);
+ return uvc_video_enable(stream, 0);
}
static struct vb2_ops uvc_queue_qops = {
@@ -136,39 +140,36 @@ static struct vb2_ops uvc_queue_qops = {
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue,
.buf_finish = uvc_buffer_finish,
- .wait_prepare = uvc_wait_prepare,
- .wait_finish = uvc_wait_finish,
+ .start_streaming = uvc_start_streaming,
+ .stop_streaming = uvc_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
};
int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
int drop_corrupted)
{
- int ret;
-
queue->queue.type = type;
- queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+ queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
queue->queue.drv_priv = queue;
queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
queue->queue.ops = &uvc_queue_qops;
queue->queue.mem_ops = &vb2_vmalloc_memops;
queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
| V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
- ret = vb2_queue_init(&queue->queue);
- if (ret)
- return ret;
-
+ queue->queue.lock = &queue->mutex;
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
INIT_LIST_HEAD(&queue->irqqueue);
queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
- return 0;
+ return vb2_queue_init(&queue->queue);
}
/* -----------------------------------------------------------------------------
* V4L2 queue operations
*/
-
+#if 0
int uvc_alloc_buffers(struct uvc_video_queue *queue,
struct v4l2_requestbuffers *rb)
{
@@ -233,18 +234,7 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
return ret;
}
-
-int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
-{
- int ret;
-
- mutex_lock(&queue->mutex);
- ret = vb2_mmap(&queue->queue, vma);
- mutex_unlock(&queue->mutex);
-
- return ret;
-}
-
+#endif
#ifndef CONFIG_MMU
unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
unsigned long pgoff)
@@ -258,18 +248,6 @@ unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
}
#endif
-unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
- poll_table *wait)
-{
- unsigned int ret;
-
- mutex_lock(&queue->mutex);
- ret = vb2_poll(&queue->queue, file, wait);
- mutex_unlock(&queue->mutex);
-
- return ret;
-}
-
/* -----------------------------------------------------------------------------
*
*/
@@ -304,6 +282,7 @@ int uvc_queue_allocated(struct uvc_video_queue *queue)
* This function can't be called from interrupt context. Use
* uvc_queue_cancel() instead.
*/
+/*
int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
unsigned long flags;
@@ -329,7 +308,7 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
done:
mutex_unlock(&queue->mutex);
return ret;
-}
+}*/
/*
* Cancel the video buffers queue.
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index c14dc66cc10d..a625e28e8f0b 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -416,62 +416,6 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
}
/* ------------------------------------------------------------------------
- * Privilege management
- */
-
-/*
- * Privilege management is the multiple-open implementation basis. The current
- * implementation is completely transparent for the end-user and doesn't
- * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls.
- * Those ioctls enable finer control on the device (by making possible for a
- * user to request exclusive access to a device), but are not mature yet.
- * Switching to the V4L2 priority mechanism might be considered in the future
- * if this situation changes.
- *
- * Each open instance of a UVC device can either be in a privileged or
- * unprivileged state. Only a single instance can be in a privileged state at
- * a given time. Trying to perform an operation that requires privileges will
- * automatically acquire the required privileges if possible, or return -EBUSY
- * otherwise. Privileges are dismissed when closing the instance or when
- * freeing the video buffers using VIDIOC_REQBUFS.
- *
- * Operations that require privileges are:
- *
- * - VIDIOC_S_INPUT
- * - VIDIOC_S_PARM
- * - VIDIOC_S_FMT
- * - VIDIOC_REQBUFS
- */
-static int uvc_acquire_privileges(struct uvc_fh *handle)
-{
- /* Always succeed if the handle is already privileged. */
- if (handle->state == UVC_HANDLE_ACTIVE)
- return 0;
-
- /* Check if the device already has a privileged handle. */
- if (atomic_inc_return(&handle->stream->active) != 1) {
- atomic_dec(&handle->stream->active);
- return -EBUSY;
- }
-
- handle->state = UVC_HANDLE_ACTIVE;
- return 0;
-}
-
-static void uvc_dismiss_privileges(struct uvc_fh *handle)
-{
- if (handle->state == UVC_HANDLE_ACTIVE)
- atomic_dec(&handle->stream->active);
-
- handle->state = UVC_HANDLE_PASSIVE;
-}
-
-static int uvc_has_privileges(struct uvc_fh *handle)
-{
- return handle->state == UVC_HANDLE_ACTIVE;
-}
-
-/* ------------------------------------------------------------------------
* V4L2 file operations
*/
@@ -516,7 +460,6 @@ static int uvc_v4l2_open(struct file *file)
v4l2_fh_add(&handle->vfh);
handle->chain = stream->chain;
handle->stream = stream;
- handle->state = UVC_HANDLE_PASSIVE;
file->private_data = handle;
return 0;
@@ -529,16 +472,7 @@ static int uvc_v4l2_release(struct file *file)
uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
- /* Only free resources if this is a privileged handle. */
- if (uvc_has_privileges(handle)) {
- uvc_video_enable(stream, 0);
- uvc_free_buffers(&stream->queue);
- }
-
- /* Release the file handle. */
- uvc_dismiss_privileges(handle);
- v4l2_fh_del(&handle->vfh);
- v4l2_fh_exit(&handle->vfh);
+ vb2_fop_release(file);
kfree(handle);
file->private_data = NULL;
@@ -562,12 +496,14 @@ static int uvc_querycap(struct file *file, void *fh, struct v4l2_capability *cap
strlcpy(cap->card, vdev->name, sizeof(cap->card));
usb_make_path(stream->dev->udev,
cap->bus_info, sizeof(cap->bus_info));
- cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
- | chain->caps;
+ cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+ cap->capabilities = V4L2_CAP_DEVICE_CAPS |
+ cap->device_caps | chain->caps;
+
if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
else
- cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+ cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
return 0;
}
@@ -772,12 +708,11 @@ static int uvc_g_input(struct file *file, void *fh, unsigned int *i)
static int uvc_s_input(struct file *file, void *fh, unsigned int input)
{
struct uvc_fh *handle = file->private_data;
+ struct uvc_streaming *stream = handle->stream;
struct uvc_video_chain *chain = handle->chain;
- int ret;
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
+ if (vb2_is_busy(&stream->queue.queue))
+ return -EBUSY;
if (chain->selector == NULL ||
(chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
@@ -828,11 +763,9 @@ static int uvc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
{
struct uvc_fh *handle = file->private_data;
struct uvc_streaming *stream = handle->stream;
- int ret;
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
+ if (vb2_is_busy(&stream->queue.queue))
+ return -EBUSY;
return uvc_v4l2_set_format(stream, f);
}
@@ -953,11 +886,9 @@ static int uvc_s_parm(struct file *file, void *fh,
{
struct uvc_fh *handle = file->private_data;
struct uvc_streaming *stream = handle->stream;
- int ret;
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
+ if (vb2_is_busy(&stream->queue.queue))
+ return -EBUSY;
return uvc_v4l2_set_streamparm(stream, parm);
}
@@ -986,109 +917,6 @@ static int uvc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *ccap)
return 0;
}
-/* Buffers & streaming */
-static int uvc_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *b)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
-
- mutex_lock(&stream->mutex);
- ret = uvc_alloc_buffers(&stream->queue, b);
- mutex_unlock(&stream->mutex);
- if (ret < 0)
- return ret;
-
- if (ret == 0)
- uvc_dismiss_privileges(handle);
-
- return 0;
-}
-
-static int uvc_create_bufs(struct file *file, void *fh, struct v4l2_create_buffers *cb)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
- return uvc_create_buffers(&stream->queue, cb);
-}
-
-static int uvc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- return uvc_query_buffer(&stream->queue, buf);
-}
-
-static int uvc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- return uvc_queue_buffer(&stream->queue, buf);
-}
-
-static int uvc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- return uvc_dequeue_buffer(&stream->queue, buf,
- file->f_flags & O_NONBLOCK);
-}
-
-static int uvc_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- if (type != stream->type)
- return -EINVAL;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- mutex_lock(&stream->mutex);
- ret = uvc_video_enable(stream, 1);
- mutex_unlock(&stream->mutex);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-static int uvc_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
-
- if (type != stream->type)
- return -EINVAL;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- return uvc_video_enable(stream, 0);
-}
-
static int uvc_subscribe_event(struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub)
{
@@ -1136,13 +964,13 @@ const struct v4l2_ioctl_ops uvc_ioctl_ops = {
.vidioc_s_fmt_vid_cap = uvc_s_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = uvc_try_fmt_vid_cap,
.vidioc_cropcap = uvc_cropcap,
- .vidioc_reqbufs = uvc_reqbufs,
- .vidioc_create_bufs = uvc_create_bufs,
- .vidioc_querybuf = uvc_querybuf,
- .vidioc_qbuf = uvc_qbuf,
- .vidioc_dqbuf = uvc_dqbuf,
- .vidioc_streamon = uvc_streamon,
- .vidioc_streamoff = uvc_streamoff,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_enum_framesizes = uvc_enum_framesizes,
.vidioc_enum_frameintervals = uvc_enum_frameintervals,
.vidioc_g_parm = uvc_g_parm,
@@ -1352,26 +1180,6 @@ static long uvc_v4l2_compat_ioctl32(struct file *file,
}
#endif
-static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
-
- uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
-
- return uvc_queue_mmap(&stream->queue, vma);
-}
-
-static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
-{
- struct uvc_fh *handle = file->private_data;
- struct uvc_streaming *stream = handle->stream;
-
- uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
-
- return uvc_queue_poll(&stream->queue, file, wait);
-}
-
#ifndef CONFIG_MMU
static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
unsigned long addr, unsigned long len, unsigned long pgoff,
@@ -1394,8 +1202,9 @@ const struct v4l2_file_operations uvc_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl32 = uvc_v4l2_compat_ioctl32,
#endif
- .mmap = uvc_v4l2_mmap,
- .poll = uvc_v4l2_poll,
+ .read = vb2_fop_read,
+ .mmap = vb2_fop_mmap,
+ .poll = vb2_fop_poll,
#ifndef CONFIG_MMU
.get_unmapped_area = uvc_v4l2_get_unmapped_area,
#endif
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 8d52baf5952b..0c2cab572bf2 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1715,7 +1715,7 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset)
ret = uvc_commit_video(stream, &stream->ctrl);
if (ret < 0) {
- uvc_queue_enable(&stream->queue, 0);
+ //uvc_queue_enable(&stream->queue, 0);
return ret;
}
@@ -1723,8 +1723,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset)
return 0;
ret = uvc_init_video(stream, GFP_NOIO);
- if (ret < 0)
- uvc_queue_enable(&stream->queue, 0);
+// if (ret < 0)
+// uvc_queue_enable(&stream->queue, 0);
return ret;
}
@@ -1756,8 +1756,6 @@ int uvc_video_init(struct uvc_streaming *stream)
return -EINVAL;
}
- atomic_set(&stream->active, 0);
-
/* Initialize the video buffers queue. */
ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
if (ret)
@@ -1869,7 +1867,7 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
usb_clear_halt(stream->dev->udev, pipe);
}
- uvc_queue_enable(&stream->queue, 0);
+ //uvc_queue_enable(&stream->queue, 0);
uvc_video_clock_cleanup(stream);
return 0;
}
@@ -1878,9 +1876,9 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
if (ret < 0)
return ret;
- ret = uvc_queue_enable(&stream->queue, 1);
- if (ret < 0)
- goto error_queue;
+ //ret = uvc_queue_enable(&stream->queue, 1);
+ //if (ret < 0)
+ // goto error_queue;
/* Commit the streaming parameters. */
ret = uvc_commit_video(stream, &stream->ctrl);
@@ -1896,8 +1894,8 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
error_video:
usb_set_interface(stream->dev->udev, stream->intfnum, 0);
error_commit:
- uvc_queue_enable(&stream->queue, 0);
-error_queue:
+ //uvc_queue_enable(&stream->queue, 0);
+//error_queue:
uvc_video_clock_cleanup(stream);
return ret;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index b0479426cbce..d018df651405 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -439,7 +439,6 @@ struct uvc_streaming {
struct uvc_device *dev;
struct video_device *vdev;
struct uvc_video_chain *chain;
- atomic_t active;
struct usb_interface *intf;
int intfnum;
@@ -550,16 +549,10 @@ struct uvc_device {
char input_phys[64];
};
-enum uvc_handle_state {
- UVC_HANDLE_PASSIVE = 0,
- UVC_HANDLE_ACTIVE = 1,
-};
-
struct uvc_fh {
struct v4l2_fh vfh;
struct uvc_video_chain *chain;
struct uvc_streaming *stream;
- enum uvc_handle_state state;
};
struct uvc_driver {
@@ -635,10 +628,6 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
-extern int uvc_queue_mmap(struct uvc_video_queue *queue,
- struct vm_area_struct *vma);
-extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
- struct file *file, poll_table *wait);
#ifndef CONFIG_MMU
extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
unsigned long pgoff);

Privacy Policy