linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/11] uvcvideo: Move to video_ioctl2
@ 2014-10-31 13:54 Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 01/11] v4l2: get/set prio using video_dev prio structure Laurent Pinchart
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

Hello,

This patch series moves the uvcvideo driver to video_ioctl2 and fixes vb2
usage to rely on the start_streaming and stop_streaming operations.

Please see individual patches for details.

Laurent Pinchart (11):
  v4l2: get/set prio using video_dev prio structure
  uvcvideo: Move to video_ioctl2
  uvcvideo: Add V4L2 debug module parameter
  uvcvideo: Set buffer field to V4L2_FIELD_NONE
  uvcvideo: Separate video and queue enable/disable operations
  uvcvideo: Add function to convert from queue to stream
  uvcvideo: Implement vb2 queue start and stop stream operations
  uvcvideo: Don't stop the stream twice at file handle release
  uvcvideo: Rename uvc_alloc_buffers to uvc_request_buffers
  uvcvideo: Rename and split uvc_queue_enable to
    uvc_queue_stream(on|off)
  uvcvideo: Give back all buffers to userspace when stopping the stream

 drivers/media/usb/uvc/uvc_driver.c   |   22 +-
 drivers/media/usb/uvc/uvc_queue.c    |  146 ++---
 drivers/media/usb/uvc/uvc_v4l2.c     | 1009 +++++++++++++++++++---------------
 drivers/media/usb/uvc/uvc_video.c    |   23 +-
 drivers/media/usb/uvc/uvcvideo.h     |   11 +-
 drivers/media/v4l2-core/v4l2-ioctl.c |    4 +-
 6 files changed, 664 insertions(+), 551 deletions(-)

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 01/11] v4l2: get/set prio using video_dev prio structure
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 02/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

The v4l2_device structure embed a v4l2_prio_state structure used by
default for priority handling, but drivers can override that default by
setting the video_dev prio pointer to a different v4l2_prio_state
instance.

However, the VIDIO_G_PRIORITY and VIDIOC_S_PRIORITY implementations use
the prio state embedded in v4l2_device unconditionally, breaking drivers
that need to override the default. Fix them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 9ccb19a..1bf84a5 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1040,7 +1040,7 @@ static int v4l_g_priority(const struct v4l2_ioctl_ops *ops,
 	if (ops->vidioc_g_priority)
 		return ops->vidioc_g_priority(file, fh, arg);
 	vfd = video_devdata(file);
-	*p = v4l2_prio_max(&vfd->v4l2_dev->prio);
+	*p = v4l2_prio_max(vfd->prio);
 	return 0;
 }
 
@@ -1055,7 +1055,7 @@ static int v4l_s_priority(const struct v4l2_ioctl_ops *ops,
 		return ops->vidioc_s_priority(file, fh, *p);
 	vfd = video_devdata(file);
 	vfh = file->private_data;
-	return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
+	return v4l2_prio_change(vfd->prio, &vfh->prio, *p);
 }
 
 static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 02/11] uvcvideo: Move to video_ioctl2
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 01/11] v4l2: get/set prio using video_dev prio structure Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 03/11] uvcvideo: Add V4L2 debug module parameter Laurent Pinchart
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

Simplify ioctl handling by using video_ioctl2.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

---

Changes since v1:

- Don't memset cap to 0 in uvc_ioctl_querycap
---
 drivers/media/usb/uvc/uvc_driver.c |    1 +
 drivers/media/usb/uvc/uvc_v4l2.c   | 1010 ++++++++++++++++++++----------------
 drivers/media/usb/uvc/uvcvideo.h   |    2 +-
 3 files changed, 559 insertions(+), 454 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index a327f3d..30163432 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1760,6 +1760,7 @@ static int uvc_register_video(struct uvc_device *dev,
 	 */
 	vdev->v4l2_dev = &dev->vdev;
 	vdev->fops = &uvc_fops;
+	vdev->ioctl_ops = &uvc_ioctl_ops;
 	vdev->release = uvc_release;
 	vdev->prio = &stream->chain->prio;
 	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 378ae02..a16fe21 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -551,553 +551,635 @@ static int uvc_v4l2_release(struct file *file)
 	return 0;
 }
 
-static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int uvc_ioctl_querycap(struct file *file, void *fh,
+			      struct v4l2_capability *cap)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct uvc_fh *handle = file->private_data;
 	struct uvc_video_chain *chain = handle->chain;
 	struct uvc_streaming *stream = handle->stream;
-	long ret = 0;
 
-	switch (cmd) {
-	/* Query capabilities */
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
-
-		memset(cap, 0, sizeof *cap);
-		strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
-		strlcpy(cap->card, vdev->name, sizeof cap->card);
-		usb_make_path(stream->dev->udev,
-			      cap->bus_info, sizeof(cap->bus_info));
-		cap->version = LINUX_VERSION_CODE;
-		cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
-				  | chain->caps;
-		if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
-					 | V4L2_CAP_STREAMING;
-		else
-			cap->device_caps = V4L2_CAP_VIDEO_OUTPUT
-					 | V4L2_CAP_STREAMING;
-		break;
-	}
+	strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver));
+	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;
+	if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	else
+		cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 
-	/* Priority */
-	case VIDIOC_G_PRIORITY:
-		*(u32 *)arg = v4l2_prio_max(vdev->prio);
-		break;
+	return 0;
+}
 
-	case VIDIOC_S_PRIORITY:
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
+			      struct v4l2_fmtdesc *fmt)
+{
+	struct uvc_format *format;
+	enum v4l2_buf_type type = fmt->type;
+	__u32 index = fmt->index;
 
-		return v4l2_prio_change(vdev->prio, &handle->vfh.prio,
-					*(u32 *)arg);
+	if (fmt->type != stream->type || fmt->index >= stream->nformats)
+		return -EINVAL;
 
-	/* Get, Set & Query control */
-	case VIDIOC_QUERYCTRL:
-		return uvc_query_v4l2_ctrl(chain, arg);
+	memset(fmt, 0, sizeof(*fmt));
+	fmt->index = index;
+	fmt->type = type;
+
+	format = &stream->format[fmt->index];
+	fmt->flags = 0;
+	if (format->flags & UVC_FMT_FLAG_COMPRESSED)
+		fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+	strlcpy(fmt->description, format->name, sizeof(fmt->description));
+	fmt->description[sizeof(fmt->description) - 1] = 0;
+	fmt->pixelformat = format->fcc;
+	return 0;
+}
 
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-		struct v4l2_ext_control xctrl;
+static int uvc_ioctl_enum_fmt_vid_cap(struct file *file, void *fh,
+				      struct v4l2_fmtdesc *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
 
-		memset(&xctrl, 0, sizeof xctrl);
-		xctrl.id = ctrl->id;
+	return uvc_ioctl_enum_fmt(stream, fmt);
+}
 
-		ret = uvc_ctrl_begin(chain);
-		if (ret < 0)
-			return ret;
+static int uvc_ioctl_enum_fmt_vid_out(struct file *file, void *fh,
+				      struct v4l2_fmtdesc *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
 
-		ret = uvc_ctrl_get(chain, &xctrl);
-		uvc_ctrl_rollback(handle);
-		if (ret >= 0)
-			ctrl->value = xctrl.value;
-		break;
-	}
+	return uvc_ioctl_enum_fmt(stream, fmt);
+}
 
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-		struct v4l2_ext_control xctrl;
+static int uvc_ioctl_g_fmt_vid_cap(struct file *file, void *fh,
+				   struct v4l2_format *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
 
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+	return uvc_v4l2_get_format(stream, fmt);
+}
 
-		memset(&xctrl, 0, sizeof xctrl);
-		xctrl.id = ctrl->id;
-		xctrl.value = ctrl->value;
+static int uvc_ioctl_g_fmt_vid_out(struct file *file, void *fh,
+				   struct v4l2_format *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
 
-		ret = uvc_ctrl_begin(chain);
-		if (ret < 0)
-			return ret;
+	return uvc_v4l2_get_format(stream, fmt);
+}
 
-		ret = uvc_ctrl_set(chain, &xctrl);
-		if (ret < 0) {
-			uvc_ctrl_rollback(handle);
-			return ret;
-		}
-		ret = uvc_ctrl_commit(handle, &xctrl, 1);
-		if (ret == 0)
-			ctrl->value = xctrl.value;
-		break;
-	}
+static int uvc_ioctl_s_fmt_vid_cap(struct file *file, void *fh,
+				   struct v4l2_format *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	int ret;
 
-	case VIDIOC_QUERYMENU:
-		return uvc_query_v4l2_menu(chain, arg);
+	ret = uvc_acquire_privileges(handle);
+	if (ret < 0)
+		return ret;
 
-	case VIDIOC_G_EXT_CTRLS:
-	{
-		struct v4l2_ext_controls *ctrls = arg;
-		struct v4l2_ext_control *ctrl = ctrls->controls;
-		unsigned int i;
+	return uvc_v4l2_set_format(stream, fmt);
+}
 
-		ret = uvc_ctrl_begin(chain);
-		if (ret < 0)
-			return ret;
+static int uvc_ioctl_s_fmt_vid_out(struct file *file, void *fh,
+				   struct v4l2_format *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	int ret;
 
-		for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-			ret = uvc_ctrl_get(chain, ctrl);
-			if (ret < 0) {
-				uvc_ctrl_rollback(handle);
-				ctrls->error_idx = i;
-				return ret;
-			}
-		}
-		ctrls->error_idx = 0;
-		ret = uvc_ctrl_rollback(handle);
-		break;
-	}
+	ret = uvc_acquire_privileges(handle);
+	if (ret < 0)
+		return ret;
 
-	case VIDIOC_S_EXT_CTRLS:
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
-		/* Fall through */
-	case VIDIOC_TRY_EXT_CTRLS:
-	{
-		struct v4l2_ext_controls *ctrls = arg;
-		struct v4l2_ext_control *ctrl = ctrls->controls;
-		unsigned int i;
-
-		ret = uvc_ctrl_begin(chain);
-		if (ret < 0)
-			return ret;
+	return uvc_v4l2_set_format(stream, fmt);
+}
 
-		for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-			ret = uvc_ctrl_set(chain, ctrl);
-			if (ret < 0) {
-				uvc_ctrl_rollback(handle);
-				ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS
-						 ? ctrls->count : i;
-				return ret;
-			}
-		}
+static int uvc_ioctl_try_fmt_vid_cap(struct file *file, void *fh,
+				     struct v4l2_format *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	struct uvc_streaming_control probe;
 
-		ctrls->error_idx = 0;
+	return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
+}
 
-		if (cmd == VIDIOC_S_EXT_CTRLS)
-			ret = uvc_ctrl_commit(handle,
-					      ctrls->controls, ctrls->count);
-		else
-			ret = uvc_ctrl_rollback(handle);
-		break;
-	}
+static int uvc_ioctl_try_fmt_vid_out(struct file *file, void *fh,
+				     struct v4l2_format *fmt)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	struct uvc_streaming_control probe;
 
-	/* Get, Set & Enum input */
-	case VIDIOC_ENUMINPUT:
-	{
-		const struct uvc_entity *selector = chain->selector;
-		struct v4l2_input *input = arg;
-		struct uvc_entity *iterm = NULL;
-		u32 index = input->index;
-		int pin = 0;
-
-		if (selector == NULL ||
-		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-			if (index != 0)
-				return -EINVAL;
-			list_for_each_entry(iterm, &chain->entities, chain) {
-				if (UVC_ENTITY_IS_ITERM(iterm))
-					break;
-			}
-			pin = iterm->id;
-		} else if (index < selector->bNrInPins) {
-			pin = selector->baSourceID[index];
-			list_for_each_entry(iterm, &chain->entities, chain) {
-				if (!UVC_ENTITY_IS_ITERM(iterm))
-					continue;
-				if (iterm->id == pin)
-					break;
-			}
-		}
+	return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
+}
 
-		if (iterm == NULL || iterm->id != pin)
-			return -EINVAL;
+static int uvc_ioctl_reqbufs(struct file *file, void *fh,
+			     struct v4l2_requestbuffers *rb)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	int ret;
 
-		memset(input, 0, sizeof *input);
-		input->index = index;
-		strlcpy(input->name, iterm->name, sizeof input->name);
-		if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
-			input->type = V4L2_INPUT_TYPE_CAMERA;
-		break;
-	}
+	ret = uvc_acquire_privileges(handle);
+	if (ret < 0)
+		return ret;
 
-	case VIDIOC_G_INPUT:
-	{
-		u8 input;
+	mutex_lock(&stream->mutex);
+	ret = uvc_alloc_buffers(&stream->queue, rb);
+	mutex_unlock(&stream->mutex);
+	if (ret < 0)
+		return ret;
 
-		if (chain->selector == NULL ||
-		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-			*(int *)arg = 0;
-			break;
-		}
+	if (ret == 0)
+		uvc_dismiss_privileges(handle);
 
-		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
-			chain->selector->id, chain->dev->intfnum,
-			UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
-		if (ret < 0)
-			return ret;
+	return 0;
+}
 
-		*(int *)arg = input - 1;
-		break;
-	}
+static int uvc_ioctl_querybuf(struct file *file, void *fh,
+			      struct v4l2_buffer *buf)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
 
-	case VIDIOC_S_INPUT:
-	{
-		u32 input = *(u32 *)arg + 1;
+	if (!uvc_has_privileges(handle))
+		return -EBUSY;
 
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+	return uvc_query_buffer(&stream->queue, buf);
+}
 
-		if ((ret = uvc_acquire_privileges(handle)) < 0)
-			return ret;
+static int uvc_ioctl_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
 
-		if (chain->selector == NULL ||
-		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-			if (input != 1)
-				return -EINVAL;
-			break;
-		}
+	if (!uvc_has_privileges(handle))
+		return -EBUSY;
 
-		if (input == 0 || input > chain->selector->bNrInPins)
-			return -EINVAL;
+	return uvc_queue_buffer(&stream->queue, buf);
+}
 
-		return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
-			chain->selector->id, chain->dev->intfnum,
-			UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
-	}
+static int uvc_ioctl_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
 
-	/* Try, Get, Set & Enum format */
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *fmt = arg;
-		struct uvc_format *format;
-		enum v4l2_buf_type type = fmt->type;
-		__u32 index = fmt->index;
+	if (!uvc_has_privileges(handle))
+		return -EBUSY;
 
-		if (fmt->type != stream->type ||
-		    fmt->index >= stream->nformats)
-			return -EINVAL;
+	return uvc_dequeue_buffer(&stream->queue, buf,
+				  file->f_flags & O_NONBLOCK);
+}
 
-		memset(fmt, 0, sizeof(*fmt));
-		fmt->index = index;
-		fmt->type = type;
-
-		format = &stream->format[fmt->index];
-		fmt->flags = 0;
-		if (format->flags & UVC_FMT_FLAG_COMPRESSED)
-			fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-		strlcpy(fmt->description, format->name,
-			sizeof fmt->description);
-		fmt->description[sizeof fmt->description - 1] = 0;
-		fmt->pixelformat = format->fcc;
-		break;
-	}
+static int uvc_ioctl_create_bufs(struct file *file, void *fh,
+				  struct v4l2_create_buffers *cb)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	int ret;
 
-	case VIDIOC_TRY_FMT:
-	{
-		struct uvc_streaming_control probe;
+	ret = uvc_acquire_privileges(handle);
+	if (ret < 0)
+		return ret;
 
-		return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL);
-	}
+	return uvc_create_buffers(&stream->queue, cb);
+}
 
-	case VIDIOC_S_FMT:
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+static int uvc_ioctl_streamon(struct file *file, void *fh,
+			      enum v4l2_buf_type type)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	int ret;
 
-		if ((ret = uvc_acquire_privileges(handle)) < 0)
-			return 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);
 
-		return uvc_v4l2_set_format(stream, arg);
+	return ret;
+}
 
-	case VIDIOC_G_FMT:
-		return uvc_v4l2_get_format(stream, arg);
+static int uvc_ioctl_streamoff(struct file *file, void *fh,
+			       enum v4l2_buf_type type)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	int ret;
 
-	/* Frame size enumeration */
-	case VIDIOC_ENUM_FRAMESIZES:
-	{
-		struct v4l2_frmsizeenum *fsize = arg;
-		struct uvc_format *format = NULL;
-		struct uvc_frame *frame;
-		int i;
+	if (type != stream->type)
+		return -EINVAL;
 
-		/* Look for the given pixel format */
-		for (i = 0; i < stream->nformats; i++) {
-			if (stream->format[i].fcc ==
-					fsize->pixel_format) {
-				format = &stream->format[i];
-				break;
-			}
-		}
-		if (format == NULL)
-			return -EINVAL;
+	if (!uvc_has_privileges(handle))
+		return -EBUSY;
 
-		if (fsize->index >= format->nframes)
-			return -EINVAL;
+	mutex_lock(&stream->mutex);
+	ret = uvc_video_enable(stream, 0);
+	mutex_unlock(&stream->mutex);
 
-		frame = &format->frame[fsize->index];
-		fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-		fsize->discrete.width = frame->wWidth;
-		fsize->discrete.height = frame->wHeight;
-		break;
-	}
+	return ret;
+}
 
-	/* Frame interval enumeration */
-	case VIDIOC_ENUM_FRAMEINTERVALS:
-	{
-		struct v4l2_frmivalenum *fival = arg;
-		struct uvc_format *format = NULL;
-		struct uvc_frame *frame = NULL;
-		int i;
-
-		/* Look for the given pixel format and frame size */
-		for (i = 0; i < stream->nformats; i++) {
-			if (stream->format[i].fcc ==
-					fival->pixel_format) {
-				format = &stream->format[i];
-				break;
-			}
-		}
-		if (format == NULL)
+static int uvc_ioctl_enum_input(struct file *file, void *fh,
+				struct v4l2_input *input)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
+	const struct uvc_entity *selector = chain->selector;
+	struct uvc_entity *iterm = NULL;
+	u32 index = input->index;
+	int pin = 0;
+
+	if (selector == NULL ||
+	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+		if (index != 0)
 			return -EINVAL;
-
-		for (i = 0; i < format->nframes; i++) {
-			if (format->frame[i].wWidth == fival->width &&
-			    format->frame[i].wHeight == fival->height) {
-				frame = &format->frame[i];
+		list_for_each_entry(iterm, &chain->entities, chain) {
+			if (UVC_ENTITY_IS_ITERM(iterm))
 				break;
-			}
 		}
-		if (frame == NULL)
-			return -EINVAL;
-
-		if (frame->bFrameIntervalType) {
-			if (fival->index >= frame->bFrameIntervalType)
-				return -EINVAL;
-
-			fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-			fival->discrete.numerator =
-				frame->dwFrameInterval[fival->index];
-			fival->discrete.denominator = 10000000;
-			uvc_simplify_fraction(&fival->discrete.numerator,
-				&fival->discrete.denominator, 8, 333);
-		} else {
-			fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
-			fival->stepwise.min.numerator =
-				frame->dwFrameInterval[0];
-			fival->stepwise.min.denominator = 10000000;
-			fival->stepwise.max.numerator =
-				frame->dwFrameInterval[1];
-			fival->stepwise.max.denominator = 10000000;
-			fival->stepwise.step.numerator =
-				frame->dwFrameInterval[2];
-			fival->stepwise.step.denominator = 10000000;
-			uvc_simplify_fraction(&fival->stepwise.min.numerator,
-				&fival->stepwise.min.denominator, 8, 333);
-			uvc_simplify_fraction(&fival->stepwise.max.numerator,
-				&fival->stepwise.max.denominator, 8, 333);
-			uvc_simplify_fraction(&fival->stepwise.step.numerator,
-				&fival->stepwise.step.denominator, 8, 333);
+		pin = iterm->id;
+	} else if (index < selector->bNrInPins) {
+		pin = selector->baSourceID[index];
+		list_for_each_entry(iterm, &chain->entities, chain) {
+			if (!UVC_ENTITY_IS_ITERM(iterm))
+				continue;
+			if (iterm->id == pin)
+				break;
 		}
-		break;
 	}
 
-	/* Get & Set streaming parameters */
-	case VIDIOC_G_PARM:
-		return uvc_v4l2_get_streamparm(stream, arg);
+	if (iterm == NULL || iterm->id != pin)
+		return -EINVAL;
 
-	case VIDIOC_S_PARM:
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+	memset(input, 0, sizeof(*input));
+	input->index = index;
+	strlcpy(input->name, iterm->name, sizeof(input->name));
+	if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
+		input->type = V4L2_INPUT_TYPE_CAMERA;
 
-		if ((ret = uvc_acquire_privileges(handle)) < 0)
-			return ret;
+	return 0;
+}
 
-		return uvc_v4l2_set_streamparm(stream, arg);
+static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
+	int ret;
+	u8 i;
 
-	/* Cropping and scaling */
-	case VIDIOC_CROPCAP:
-	{
-		struct v4l2_cropcap *ccap = arg;
+	if (chain->selector == NULL ||
+	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+		*input = 0;
+		return 0;
+	}
 
-		if (ccap->type != stream->type)
-			return -EINVAL;
+	ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
+			     chain->dev->intfnum,  UVC_SU_INPUT_SELECT_CONTROL,
+			     &i, 1);
+	if (ret < 0)
+		return ret;
 
-		ccap->bounds.left = 0;
-		ccap->bounds.top = 0;
+	*input = i - 1;
+	return 0;
+}
 
-		mutex_lock(&stream->mutex);
-		ccap->bounds.width = stream->cur_frame->wWidth;
-		ccap->bounds.height = stream->cur_frame->wHeight;
-		mutex_unlock(&stream->mutex);
+static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
+	int ret;
+	u32 i;
 
-		ccap->defrect = ccap->bounds;
+	ret = uvc_acquire_privileges(handle);
+	if (ret < 0)
+		return ret;
 
-		ccap->pixelaspect.numerator = 1;
-		ccap->pixelaspect.denominator = 1;
-		break;
+	if (chain->selector == NULL ||
+	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+		if (input)
+			return -EINVAL;
+		return 0;
 	}
 
-	case VIDIOC_G_CROP:
-	case VIDIOC_S_CROP:
-		return -ENOTTY;
+	if (input >= chain->selector->bNrInPins)
+		return -EINVAL;
 
-	/* Buffers & streaming */
-	case VIDIOC_REQBUFS:
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+	i = input + 1;
+	return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
+			      chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
+			      &i, 1);
+}
 
-		if ((ret = uvc_acquire_privileges(handle)) < 0)
-			return ret;
+static int uvc_ioctl_queryctrl(struct file *file, void *fh,
+			       struct v4l2_queryctrl *qc)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
 
-		mutex_lock(&stream->mutex);
-		ret = uvc_alloc_buffers(&stream->queue, arg);
-		mutex_unlock(&stream->mutex);
-		if (ret < 0)
-			return ret;
+	return uvc_query_v4l2_ctrl(chain, qc);
+}
 
-		if (ret == 0)
-			uvc_dismiss_privileges(handle);
+static int uvc_ioctl_g_ctrl(struct file *file, void *fh,
+			    struct v4l2_control *ctrl)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
+	struct v4l2_ext_control xctrl;
+	int ret;
 
-		ret = 0;
-		break;
+	memset(&xctrl, 0, sizeof(xctrl));
+	xctrl.id = ctrl->id;
 
-	case VIDIOC_QUERYBUF:
-	{
-		struct v4l2_buffer *buf = arg;
+	ret = uvc_ctrl_begin(chain);
+	if (ret < 0)
+		return ret;
 
-		if (!uvc_has_privileges(handle))
-			return -EBUSY;
+	ret = uvc_ctrl_get(chain, &xctrl);
+	uvc_ctrl_rollback(handle);
+	if (ret < 0)
+		return ret;
 
-		return uvc_query_buffer(&stream->queue, buf);
-	}
+	ctrl->value = xctrl.value;
+	return 0;
+}
 
-	case VIDIOC_CREATE_BUFS:
-	{
-		struct v4l2_create_buffers *cb = arg;
+static int uvc_ioctl_s_ctrl(struct file *file, void *fh,
+			    struct v4l2_control *ctrl)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
+	struct v4l2_ext_control xctrl;
+	int ret;
 
-		ret = uvc_acquire_privileges(handle);
-		if (ret < 0)
-			return ret;
+	memset(&xctrl, 0, sizeof(xctrl));
+	xctrl.id = ctrl->id;
+	xctrl.value = ctrl->value;
 
-		return uvc_create_buffers(&stream->queue, cb);
+	ret = uvc_ctrl_begin(chain);
+	if (ret < 0)
+		return ret;
+
+	ret = uvc_ctrl_set(chain, &xctrl);
+	if (ret < 0) {
+		uvc_ctrl_rollback(handle);
+		return ret;
 	}
 
-	case VIDIOC_QBUF:
-		if (!uvc_has_privileges(handle))
-			return -EBUSY;
+	ret = uvc_ctrl_commit(handle, &xctrl, 1);
+	if (ret < 0)
+		return ret;
 
-		return uvc_queue_buffer(&stream->queue, arg);
+	ctrl->value = xctrl.value;
+	return 0;
+}
 
-	case VIDIOC_DQBUF:
-		if (!uvc_has_privileges(handle))
-			return -EBUSY;
+static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
+				 struct v4l2_ext_controls *ctrls)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
+	struct v4l2_ext_control *ctrl = ctrls->controls;
+	unsigned int i;
+	int ret;
 
-		return uvc_dequeue_buffer(&stream->queue, arg,
-			file->f_flags & O_NONBLOCK);
+	ret = uvc_ctrl_begin(chain);
+	if (ret < 0)
+		return ret;
 
-	case VIDIOC_STREAMON:
-	{
-		int *type = arg;
+	for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+		ret = uvc_ctrl_get(chain, ctrl);
+		if (ret < 0) {
+			uvc_ctrl_rollback(handle);
+			ctrls->error_idx = i;
+			return ret;
+		}
+	}
 
-		if (*type != stream->type)
-			return -EINVAL;
+	ctrls->error_idx = 0;
 
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+	return uvc_ctrl_rollback(handle);
+}
 
-		if (!uvc_has_privileges(handle))
-			return -EBUSY;
+static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle,
+				     struct v4l2_ext_controls *ctrls,
+				     bool commit)
+{
+	struct v4l2_ext_control *ctrl = ctrls->controls;
+	struct uvc_video_chain *chain = handle->chain;
+	unsigned int i;
+	int ret;
 
-		mutex_lock(&stream->mutex);
-		ret = uvc_video_enable(stream, 1);
-		mutex_unlock(&stream->mutex);
-		if (ret < 0)
+	ret = uvc_ctrl_begin(chain);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+		ret = uvc_ctrl_set(chain, ctrl);
+		if (ret < 0) {
+			uvc_ctrl_rollback(handle);
+			ctrls->error_idx = commit ? ctrls->count : i;
 			return ret;
-		break;
+		}
 	}
 
-	case VIDIOC_STREAMOFF:
-	{
-		int *type = arg;
+	ctrls->error_idx = 0;
 
-		if (*type != stream->type)
-			return -EINVAL;
+	if (commit)
+		return uvc_ctrl_commit(handle, ctrls->controls, ctrls->count);
+	else
+		return uvc_ctrl_rollback(handle);
+}
 
-		ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
-		if (ret < 0)
-			return ret;
+static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh,
+				 struct v4l2_ext_controls *ctrls)
+{
+	struct uvc_fh *handle = fh;
 
-		if (!uvc_has_privileges(handle))
-			return -EBUSY;
+	return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, true);
+}
+
+static int uvc_ioctl_try_ext_ctrls(struct file *file, void *fh,
+				   struct v4l2_ext_controls *ctrls)
+{
+	struct uvc_fh *handle = fh;
+
+	return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, false);
+}
 
-		return uvc_video_enable(stream, 0);
+static int uvc_ioctl_querymenu(struct file *file, void *fh,
+			       struct v4l2_querymenu *qm)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
+
+	return uvc_query_v4l2_menu(chain, qm);
+}
+
+static int uvc_ioctl_cropcap(struct file *file, void *fh,
+			     struct v4l2_cropcap *ccap)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+
+	if (ccap->type != stream->type)
+		return -EINVAL;
+
+	ccap->bounds.left = 0;
+	ccap->bounds.top = 0;
+	mutex_lock(&stream->mutex);
+	ccap->bounds.width = stream->cur_frame->wWidth;
+	ccap->bounds.height = stream->cur_frame->wHeight;
+	mutex_unlock(&stream->mutex);
+
+	ccap->defrect = ccap->bounds;
+
+	ccap->pixelaspect.numerator = 1;
+	ccap->pixelaspect.denominator = 1;
+	return 0;
+}
+
+static int uvc_ioctl_g_parm(struct file *file, void *fh,
+			    struct v4l2_streamparm *parm)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+
+	return uvc_v4l2_get_streamparm(stream, parm);
+}
+
+static int uvc_ioctl_s_parm(struct file *file, void *fh,
+			    struct v4l2_streamparm *parm)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	int ret;
+
+	ret = uvc_acquire_privileges(handle);
+	if (ret < 0)
+		return ret;
+
+	return uvc_v4l2_set_streamparm(stream, parm);
+}
+
+static int uvc_ioctl_enum_framesizes(struct file *file, void *fh,
+				     struct v4l2_frmsizeenum *fsize)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	struct uvc_format *format = NULL;
+	struct uvc_frame *frame;
+	int i;
+
+	/* Look for the given pixel format */
+	for (i = 0; i < stream->nformats; i++) {
+		if (stream->format[i].fcc == fsize->pixel_format) {
+			format = &stream->format[i];
+			break;
+		}
 	}
+	if (format == NULL)
+		return -EINVAL;
 
-	case VIDIOC_SUBSCRIBE_EVENT:
-	{
-		struct v4l2_event_subscription *sub = arg;
+	if (fsize->index >= format->nframes)
+		return -EINVAL;
 
-		switch (sub->type) {
-		case V4L2_EVENT_CTRL:
-			return v4l2_event_subscribe(&handle->vfh, sub, 0,
-						    &uvc_ctrl_sub_ev_ops);
-		default:
-			return -EINVAL;
+	frame = &format->frame[fsize->index];
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete.width = frame->wWidth;
+	fsize->discrete.height = frame->wHeight;
+	return 0;
+}
+
+static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
+					 struct v4l2_frmivalenum *fival)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_streaming *stream = handle->stream;
+	struct uvc_format *format = NULL;
+	struct uvc_frame *frame = NULL;
+	int i;
+
+	/* Look for the given pixel format and frame size */
+	for (i = 0; i < stream->nformats; i++) {
+		if (stream->format[i].fcc == fival->pixel_format) {
+			format = &stream->format[i];
+			break;
 		}
 	}
+	if (format == NULL)
+		return -EINVAL;
 
-	case VIDIOC_UNSUBSCRIBE_EVENT:
-		return v4l2_event_unsubscribe(&handle->vfh, arg);
+	for (i = 0; i < format->nframes; i++) {
+		if (format->frame[i].wWidth == fival->width &&
+		    format->frame[i].wHeight == fival->height) {
+			frame = &format->frame[i];
+			break;
+		}
+	}
+	if (frame == NULL)
+		return -EINVAL;
 
-	case VIDIOC_DQEVENT:
-		return v4l2_event_dequeue(&handle->vfh, arg,
-					  file->f_flags & O_NONBLOCK);
+	if (frame->bFrameIntervalType) {
+		if (fival->index >= frame->bFrameIntervalType)
+			return -EINVAL;
 
-	/* Analog video standards make no sense for digital cameras. */
-	case VIDIOC_ENUMSTD:
-	case VIDIOC_QUERYSTD:
-	case VIDIOC_G_STD:
-	case VIDIOC_S_STD:
+		fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+		fival->discrete.numerator =
+			frame->dwFrameInterval[fival->index];
+		fival->discrete.denominator = 10000000;
+		uvc_simplify_fraction(&fival->discrete.numerator,
+			&fival->discrete.denominator, 8, 333);
+	} else {
+		fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+		fival->stepwise.min.numerator = frame->dwFrameInterval[0];
+		fival->stepwise.min.denominator = 10000000;
+		fival->stepwise.max.numerator = frame->dwFrameInterval[1];
+		fival->stepwise.max.denominator = 10000000;
+		fival->stepwise.step.numerator = frame->dwFrameInterval[2];
+		fival->stepwise.step.denominator = 10000000;
+		uvc_simplify_fraction(&fival->stepwise.min.numerator,
+			&fival->stepwise.min.denominator, 8, 333);
+		uvc_simplify_fraction(&fival->stepwise.max.numerator,
+			&fival->stepwise.max.denominator, 8, 333);
+		uvc_simplify_fraction(&fival->stepwise.step.numerator,
+			&fival->stepwise.step.denominator, 8, 333);
+	}
 
-	case VIDIOC_OVERLAY:
+	return 0;
+}
 
-	case VIDIOC_ENUMAUDIO:
-	case VIDIOC_ENUMAUDOUT:
+static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh,
+				     const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_CTRL:
+		return v4l2_event_subscribe(fh, sub, 0, &uvc_ctrl_sub_ev_ops);
+	default:
+		return -EINVAL;
+	}
+}
 
-	case VIDIOC_ENUMOUTPUT:
-		uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
-		return -ENOTTY;
+static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio,
+			      unsigned int cmd, void *arg)
+{
+	struct uvc_fh *handle = fh;
+	struct uvc_video_chain *chain = handle->chain;
 
+	switch (cmd) {
+	/* Dynamic controls. */
 	case UVCIOC_CTRL_MAP:
 		return uvc_ioctl_ctrl_map(chain, arg);
 
@@ -1105,23 +1187,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		return uvc_xu_ctrl_query(chain, arg);
 
 	default:
-		uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);
 		return -ENOTTY;
 	}
-
-	return ret;
-}
-
-static long uvc_v4l2_ioctl(struct file *file,
-		     unsigned int cmd, unsigned long arg)
-{
-	if (uvc_trace_param & UVC_TRACE_IOCTL) {
-		uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl(");
-		v4l_printk_ioctl(NULL, cmd);
-		printk(")\n");
-	}
-
-	return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
 }
 
 #ifdef CONFIG_COMPAT
@@ -1304,7 +1371,7 @@ static long uvc_v4l2_compat_ioctl32(struct file *file,
 
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
-	ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg);
+	ret = video_ioctl2(file, cmd, (unsigned long)&karg);
 	set_fs(old_fs);
 
 	if (ret < 0)
@@ -1365,11 +1432,48 @@ static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
 }
 #endif
 
+const struct v4l2_ioctl_ops uvc_ioctl_ops = {
+	.vidioc_querycap = uvc_ioctl_querycap,
+	.vidioc_enum_fmt_vid_cap = uvc_ioctl_enum_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_out = uvc_ioctl_enum_fmt_vid_out,
+	.vidioc_g_fmt_vid_cap = uvc_ioctl_g_fmt_vid_cap,
+	.vidioc_g_fmt_vid_out = uvc_ioctl_g_fmt_vid_out,
+	.vidioc_s_fmt_vid_cap = uvc_ioctl_s_fmt_vid_cap,
+	.vidioc_s_fmt_vid_out = uvc_ioctl_s_fmt_vid_out,
+	.vidioc_try_fmt_vid_cap = uvc_ioctl_try_fmt_vid_cap,
+	.vidioc_try_fmt_vid_out = uvc_ioctl_try_fmt_vid_out,
+	.vidioc_reqbufs = uvc_ioctl_reqbufs,
+	.vidioc_querybuf = uvc_ioctl_querybuf,
+	.vidioc_qbuf = uvc_ioctl_qbuf,
+	.vidioc_dqbuf = uvc_ioctl_dqbuf,
+	.vidioc_create_bufs = uvc_ioctl_create_bufs,
+	.vidioc_streamon = uvc_ioctl_streamon,
+	.vidioc_streamoff = uvc_ioctl_streamoff,
+	.vidioc_enum_input = uvc_ioctl_enum_input,
+	.vidioc_g_input = uvc_ioctl_g_input,
+	.vidioc_s_input = uvc_ioctl_s_input,
+	.vidioc_queryctrl = uvc_ioctl_queryctrl,
+	.vidioc_g_ctrl = uvc_ioctl_g_ctrl,
+	.vidioc_s_ctrl = uvc_ioctl_s_ctrl,
+	.vidioc_g_ext_ctrls = uvc_ioctl_g_ext_ctrls,
+	.vidioc_s_ext_ctrls = uvc_ioctl_s_ext_ctrls,
+	.vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls,
+	.vidioc_querymenu = uvc_ioctl_querymenu,
+	.vidioc_cropcap = uvc_ioctl_cropcap,
+	.vidioc_g_parm = uvc_ioctl_g_parm,
+	.vidioc_s_parm = uvc_ioctl_s_parm,
+	.vidioc_enum_framesizes = uvc_ioctl_enum_framesizes,
+	.vidioc_enum_frameintervals = uvc_ioctl_enum_frameintervals,
+	.vidioc_subscribe_event = uvc_ioctl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_default = uvc_ioctl_default,
+};
+
 const struct v4l2_file_operations uvc_fops = {
 	.owner		= THIS_MODULE,
 	.open		= uvc_v4l2_open,
 	.release	= uvc_v4l2_release,
-	.unlocked_ioctl	= uvc_v4l2_ioctl,
+	.unlocked_ioctl	= video_ioctl2,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl32	= uvc_v4l2_compat_ioctl32,
 #endif
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 2600c96..53db7ed 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -580,7 +580,6 @@ struct uvc_driver {
 #define UVC_TRACE_FORMAT	(1 << 3)
 #define UVC_TRACE_CAPTURE	(1 << 4)
 #define UVC_TRACE_CALLS		(1 << 5)
-#define UVC_TRACE_IOCTL		(1 << 6)
 #define UVC_TRACE_FRAME		(1 << 7)
 #define UVC_TRACE_SUSPEND	(1 << 8)
 #define UVC_TRACE_STATUS	(1 << 9)
@@ -654,6 +653,7 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 }
 
 /* V4L2 interface */
+extern const struct v4l2_ioctl_ops uvc_ioctl_ops;
 extern const struct v4l2_file_operations uvc_fops;
 
 /* Media controller */
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 03/11] uvcvideo: Add V4L2 debug module parameter
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 01/11] v4l2: get/set prio using video_dev prio structure Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 02/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 14:39   ` Hans Verkuil
  2014-10-31 13:54 ` [PATCH v2 04/11] uvcvideo: Set buffer field to V4L2_FIELD_NONE Laurent Pinchart
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

Add a new debug module parameter and use it to initialize the V4L2 debug
level for all video devices.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_driver.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 30163432..1cae974 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -34,6 +34,7 @@
 unsigned int uvc_clock_param = CLOCK_MONOTONIC;
 unsigned int uvc_no_drop_param;
 static unsigned int uvc_quirks_param = -1;
+static unsigned int uvc_debug_param;
 unsigned int uvc_trace_param;
 unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
 
@@ -1763,6 +1764,7 @@ static int uvc_register_video(struct uvc_device *dev,
 	vdev->ioctl_ops = &uvc_ioctl_ops;
 	vdev->release = uvc_release;
 	vdev->prio = &stream->chain->prio;
+	vdev->debug = uvc_debug_param;
 	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
 		vdev->vfl_dir = VFL_DIR_TX;
 	strlcpy(vdev->name, dev->name, sizeof vdev->name);
@@ -2080,6 +2082,8 @@ static int uvc_clock_param_set(const char *val, struct kernel_param *kp)
 module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
 		  &uvc_clock_param, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(clock, "Video buffers timestamp clock");
+module_param_named(debug, uvc_debug_param, uint, S_IRUGO);
+MODULE_PARM_DESC(debug, "V4L2 debug level");
 module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
 module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 04/11] uvcvideo: Set buffer field to V4L2_FIELD_NONE
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (2 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 03/11] uvcvideo: Add V4L2 debug module parameter Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 05/11] uvcvideo: Separate video and queue enable/disable operations Laurent Pinchart
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

The driver doesn't support interlaced video, set field to
V4L2_FIELD_NONE for all vb2 buffers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_video.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index df81b9c..b9c7dee 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1021,6 +1021,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
 
 		uvc_video_get_ts(&ts);
 
+		buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
 		buf->buf.v4l2_buf.sequence = stream->sequence;
 		buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
 		buf->buf.v4l2_buf.timestamp.tv_usec =
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 05/11] uvcvideo: Separate video and queue enable/disable operations
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (3 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 04/11] uvcvideo: Set buffer field to V4L2_FIELD_NONE Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 06/11] uvcvideo: Add function to convert from queue to stream Laurent Pinchart
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

In order to make use of the vb2 queue start/stop_streaming operations
the video and queue enable/disable operations need to be split, as the
vb2 queue will need to enable and disable video instead of the other way
around.

Also move buffer queue disable outside of uvc_video_resume() to remove
all queue disable operations out of uvc_video.c.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_driver.c | 16 ++++++++++++----
 drivers/media/usb/uvc/uvc_v4l2.c   | 15 ++++++++++++---
 drivers/media/usb/uvc/uvc_video.c  | 22 ++--------------------
 3 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 1cae974..a0b163a 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1735,6 +1735,11 @@ static int uvc_register_video(struct uvc_device *dev,
 	struct video_device *vdev;
 	int ret;
 
+	/* Initialize the video buffers queue. */
+	ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+	if (ret)
+		return ret;
+
 	/* Initialize the streaming interface with default streaming
 	 * parameters.
 	 */
@@ -2010,14 +2015,13 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
 {
 	struct uvc_device *dev = usb_get_intfdata(intf);
 	struct uvc_streaming *stream;
+	int ret = 0;
 
 	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
 		intf->cur_altsetting->desc.bInterfaceNumber);
 
 	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
 	    UVC_SC_VIDEOCONTROL) {
-		int ret = 0;
-
 		if (reset) {
 			ret = uvc_ctrl_restore_values(dev);
 			if (ret < 0)
@@ -2033,8 +2037,12 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
 	}
 
 	list_for_each_entry(stream, &dev->streams, list) {
-		if (stream->intf == intf)
-			return uvc_video_resume(stream, reset);
+		if (stream->intf == intf) {
+			ret = uvc_video_resume(stream, reset);
+			if (ret < 0)
+				uvc_queue_enable(&stream->queue, 0);
+			return ret;
+		}
 	}
 
 	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index a16fe21..e8bf4f1 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -532,6 +532,7 @@ static int uvc_v4l2_release(struct file *file)
 	/* Only free resources if this is a privileged handle. */
 	if (uvc_has_privileges(handle)) {
 		uvc_video_enable(stream, 0);
+		uvc_queue_enable(&stream->queue, 0);
 		uvc_free_buffers(&stream->queue);
 	}
 
@@ -766,7 +767,15 @@ static int uvc_ioctl_streamon(struct file *file, void *fh,
 		return -EBUSY;
 
 	mutex_lock(&stream->mutex);
+	ret = uvc_queue_enable(&stream->queue, 1);
+	if (ret < 0)
+		goto done;
+
 	ret = uvc_video_enable(stream, 1);
+	if (ret < 0)
+		uvc_queue_enable(&stream->queue, 0);
+
+done:
 	mutex_unlock(&stream->mutex);
 
 	return ret;
@@ -777,7 +786,6 @@ static int uvc_ioctl_streamoff(struct file *file, void *fh,
 {
 	struct uvc_fh *handle = fh;
 	struct uvc_streaming *stream = handle->stream;
-	int ret;
 
 	if (type != stream->type)
 		return -EINVAL;
@@ -786,10 +794,11 @@ static int uvc_ioctl_streamoff(struct file *file, void *fh,
 		return -EBUSY;
 
 	mutex_lock(&stream->mutex);
-	ret = uvc_video_enable(stream, 0);
+	uvc_video_enable(stream, 0);
+	uvc_queue_enable(&stream->queue, 0);
 	mutex_unlock(&stream->mutex);
 
-	return ret;
+	return 0;
 }
 
 static int uvc_ioctl_enum_input(struct file *file, void *fh,
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index b9c7dee..9637e8b 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1735,19 +1735,13 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset)
 	uvc_video_clock_reset(stream);
 
 	ret = uvc_commit_video(stream, &stream->ctrl);
-	if (ret < 0) {
-		uvc_queue_enable(&stream->queue, 0);
+	if (ret < 0)
 		return ret;
-	}
 
 	if (!uvc_queue_streaming(&stream->queue))
 		return 0;
 
-	ret = uvc_init_video(stream, GFP_NOIO);
-	if (ret < 0)
-		uvc_queue_enable(&stream->queue, 0);
-
-	return ret;
+	return uvc_init_video(stream, GFP_NOIO);
 }
 
 /* ------------------------------------------------------------------------
@@ -1779,11 +1773,6 @@ int uvc_video_init(struct uvc_streaming *stream)
 
 	atomic_set(&stream->active, 0);
 
-	/* Initialize the video buffers queue. */
-	ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
-	if (ret)
-		return ret;
-
 	/* Alternate setting 0 should be the default, yet the XBox Live Vision
 	 * Cam (and possibly other devices) crash or otherwise misbehave if
 	 * they don't receive a SET_INTERFACE request before any other video
@@ -1890,7 +1879,6 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
 			usb_clear_halt(stream->dev->udev, pipe);
 		}
 
-		uvc_queue_enable(&stream->queue, 0);
 		uvc_video_clock_cleanup(stream);
 		return 0;
 	}
@@ -1899,10 +1887,6 @@ 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;
-
 	/* Commit the streaming parameters. */
 	ret = uvc_commit_video(stream, &stream->ctrl);
 	if (ret < 0)
@@ -1917,8 +1901,6 @@ 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_video_clock_cleanup(stream);
 
 	return ret;
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 06/11] uvcvideo: Add function to convert from queue to stream
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (4 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 05/11] uvcvideo: Separate video and queue enable/disable operations Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 07/11] uvcvideo: Implement vb2 queue start and stop stream operations Laurent Pinchart
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

Factorize the container_of() call into an inline function and update
callers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_queue.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 6e92d20..9703655 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -36,6 +36,12 @@
  * the driver.
  */
 
+static inline struct uvc_streaming *
+uvc_queue_to_stream(struct uvc_video_queue *queue)
+{
+	return container_of(queue, struct uvc_streaming, queue);
+}
+
 /* -----------------------------------------------------------------------------
  * videobuf2 queue operations
  */
@@ -45,8 +51,7 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-	struct uvc_streaming *stream =
-			container_of(queue, struct uvc_streaming, queue);
+	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
 
 	/* Make sure the image size is large enough. */
 	if (fmt && fmt->fmt.pix.sizeimage < stream->ctrl.dwMaxVideoFrameSize)
@@ -109,8 +114,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
 static void uvc_buffer_finish(struct vb2_buffer *vb)
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-	struct uvc_streaming *stream =
-			container_of(queue, struct uvc_streaming, queue);
+	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
 	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 
 	if (vb->state == VB2_BUF_STATE_DONE)
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 07/11] uvcvideo: Implement vb2 queue start and stop stream operations
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (5 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 06/11] uvcvideo: Add function to convert from queue to stream Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 08/11] uvcvideo: Don't stop the stream twice at file handle release Laurent Pinchart
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

To work propertly the videobuf2 core code needs to be in charge of
stream start/stop control. Implement the start_streaming and
stop_streaming vb2 operations and move video enable/disable code to
them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_queue.c | 43 +++++++++++++++++++++++++--------------
 drivers/media/usb/uvc/uvc_v4l2.c  | 10 ---------
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 9703655..7582470 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -135,6 +135,29 @@ static void uvc_wait_finish(struct vb2_queue *vq)
 	mutex_lock(&queue->mutex);
 }
 
+static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
+
+	queue->buf_used = 0;
+
+	return uvc_video_enable(stream, 1);
+}
+
+static void uvc_stop_streaming(struct vb2_queue *vq)
+{
+	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
+	unsigned long flags;
+
+	uvc_video_enable(stream, 0);
+
+	spin_lock_irqsave(&queue->irqlock, flags);
+	INIT_LIST_HEAD(&queue->irqqueue);
+	spin_unlock_irqrestore(&queue->irqlock, flags);
+}
+
 static struct vb2_ops uvc_queue_qops = {
 	.queue_setup = uvc_queue_setup,
 	.buf_prepare = uvc_buffer_prepare,
@@ -142,6 +165,8 @@ static struct vb2_ops uvc_queue_qops = {
 	.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,
 };
 
 int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
@@ -310,27 +335,15 @@ int uvc_queue_allocated(struct uvc_video_queue *queue)
  */
 int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 {
-	unsigned long flags;
 	int ret;
 
 	mutex_lock(&queue->mutex);
-	if (enable) {
-		ret = vb2_streamon(&queue->queue, queue->queue.type);
-		if (ret < 0)
-			goto done;
 
-		queue->buf_used = 0;
-	} else {
+	if (enable)
+		ret = vb2_streamon(&queue->queue, queue->queue.type);
+	else
 		ret = vb2_streamoff(&queue->queue, queue->queue.type);
-		if (ret < 0)
-			goto done;
-
-		spin_lock_irqsave(&queue->irqlock, flags);
-		INIT_LIST_HEAD(&queue->irqqueue);
-		spin_unlock_irqrestore(&queue->irqlock, flags);
-	}
 
-done:
 	mutex_unlock(&queue->mutex);
 	return ret;
 }
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index e8bf4f1..4619fd6 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -531,7 +531,6 @@ static int uvc_v4l2_release(struct file *file)
 
 	/* Only free resources if this is a privileged handle. */
 	if (uvc_has_privileges(handle)) {
-		uvc_video_enable(stream, 0);
 		uvc_queue_enable(&stream->queue, 0);
 		uvc_free_buffers(&stream->queue);
 	}
@@ -768,14 +767,6 @@ static int uvc_ioctl_streamon(struct file *file, void *fh,
 
 	mutex_lock(&stream->mutex);
 	ret = uvc_queue_enable(&stream->queue, 1);
-	if (ret < 0)
-		goto done;
-
-	ret = uvc_video_enable(stream, 1);
-	if (ret < 0)
-		uvc_queue_enable(&stream->queue, 0);
-
-done:
 	mutex_unlock(&stream->mutex);
 
 	return ret;
@@ -794,7 +785,6 @@ static int uvc_ioctl_streamoff(struct file *file, void *fh,
 		return -EBUSY;
 
 	mutex_lock(&stream->mutex);
-	uvc_video_enable(stream, 0);
 	uvc_queue_enable(&stream->queue, 0);
 	mutex_unlock(&stream->mutex);
 
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 08/11] uvcvideo: Don't stop the stream twice at file handle release
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (6 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 07/11] uvcvideo: Implement vb2 queue start and stop stream operations Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 09/11] uvcvideo: Rename uvc_alloc_buffers to uvc_request_buffers Laurent Pinchart
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

When releasing the file handle the driver calls the vb2_queue_release
which turns the stream off. There's thus no need to turn the stream off
explicitly beforehand.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_queue.c | 14 +++++++-------
 drivers/media/usb/uvc/uvc_v4l2.c  |  6 ++----
 drivers/media/usb/uvc/uvcvideo.h  |  2 +-
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 7582470..708478f 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -194,6 +194,13 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
 	return 0;
 }
 
+void uvc_queue_release(struct uvc_video_queue *queue)
+{
+	mutex_lock(&queue->mutex);
+	vb2_queue_release(&queue->queue);
+	mutex_unlock(&queue->mutex);
+}
+
 /* -----------------------------------------------------------------------------
  * V4L2 queue operations
  */
@@ -210,13 +217,6 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue,
 	return ret ? ret : rb->count;
 }
 
-void uvc_free_buffers(struct uvc_video_queue *queue)
-{
-	mutex_lock(&queue->mutex);
-	vb2_queue_release(&queue->queue);
-	mutex_unlock(&queue->mutex);
-}
-
 int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
 {
 	int ret;
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 4619fd6..1b6b6db 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -530,10 +530,8 @@ 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_queue_enable(&stream->queue, 0);
-		uvc_free_buffers(&stream->queue);
-	}
+	if (uvc_has_privileges(handle))
+		uvc_queue_release(&stream->queue);
 
 	/* Release the file handle. */
 	uvc_dismiss_privileges(handle);
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 53db7ed..344aede 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -623,9 +623,9 @@ extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
 /* Video buffers queue management. */
 extern int uvc_queue_init(struct uvc_video_queue *queue,
 		enum v4l2_buf_type type, int drop_corrupted);
+extern void uvc_queue_release(struct uvc_video_queue *queue);
 extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
 		struct v4l2_requestbuffers *rb);
-extern void uvc_free_buffers(struct uvc_video_queue *queue);
 extern int uvc_query_buffer(struct uvc_video_queue *queue,
 		struct v4l2_buffer *v4l2_buf);
 extern int uvc_create_buffers(struct uvc_video_queue *queue,
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 09/11] uvcvideo: Rename uvc_alloc_buffers to uvc_request_buffers
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (7 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 08/11] uvcvideo: Don't stop the stream twice at file handle release Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 10/11] uvcvideo: Rename and split uvc_queue_enable to uvc_queue_stream(on|off) Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 11/11] uvcvideo: Give back all buffers to userspace when stopping the stream Laurent Pinchart
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

This brings the function name in line with the V4L2 API terminology.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_queue.c | 4 ++--
 drivers/media/usb/uvc/uvc_v4l2.c  | 2 +-
 drivers/media/usb/uvc/uvcvideo.h  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 708478f..5c11de0 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -205,8 +205,8 @@ void uvc_queue_release(struct uvc_video_queue *queue)
  * V4L2 queue operations
  */
 
-int uvc_alloc_buffers(struct uvc_video_queue *queue,
-		      struct v4l2_requestbuffers *rb)
+int uvc_request_buffers(struct uvc_video_queue *queue,
+			struct v4l2_requestbuffers *rb)
 {
 	int ret;
 
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 1b6b6db..5ba023b 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -690,7 +690,7 @@ static int uvc_ioctl_reqbufs(struct file *file, void *fh,
 		return ret;
 
 	mutex_lock(&stream->mutex);
-	ret = uvc_alloc_buffers(&stream->queue, rb);
+	ret = uvc_request_buffers(&stream->queue, rb);
 	mutex_unlock(&stream->mutex);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 344aede..2dc247a 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -624,7 +624,7 @@ extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
 extern int uvc_queue_init(struct uvc_video_queue *queue,
 		enum v4l2_buf_type type, int drop_corrupted);
 extern void uvc_queue_release(struct uvc_video_queue *queue);
-extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
+extern int uvc_request_buffers(struct uvc_video_queue *queue,
 		struct v4l2_requestbuffers *rb);
 extern int uvc_query_buffer(struct uvc_video_queue *queue,
 		struct v4l2_buffer *v4l2_buf);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 10/11] uvcvideo: Rename and split uvc_queue_enable to uvc_queue_stream(on|off)
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (8 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 09/11] uvcvideo: Rename uvc_alloc_buffers to uvc_request_buffers Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  2014-10-31 13:54 ` [PATCH v2 11/11] uvcvideo: Give back all buffers to userspace when stopping the stream Laurent Pinchart
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

This brings the function name in line with the V4L2 API terminology and
allows removing the duplicate queue type check.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_driver.c |  3 ++-
 drivers/media/usb/uvc/uvc_queue.c  | 53 ++++++++++++++++----------------------
 drivers/media/usb/uvc/uvc_v4l2.c   | 10 ++-----
 drivers/media/usb/uvc/uvcvideo.h   |  5 +++-
 4 files changed, 30 insertions(+), 41 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index a0b163a..71f85ed 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2040,7 +2040,8 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
 		if (stream->intf == intf) {
 			ret = uvc_video_resume(stream, reset);
 			if (ret < 0)
-				uvc_queue_enable(&stream->queue, 0);
+				uvc_queue_streamoff(&stream->queue,
+						    stream->queue.queue.type);
 			return ret;
 		}
 	}
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 5c11de0..c295c5c 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -263,6 +263,28 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
 	return ret;
 }
 
+int uvc_queue_streamon(struct uvc_video_queue *queue, enum v4l2_buf_type type)
+{
+	int ret;
+
+	mutex_lock(&queue->mutex);
+	ret = vb2_streamon(&queue->queue, type);
+	mutex_unlock(&queue->mutex);
+
+	return ret;
+}
+
+int uvc_queue_streamoff(struct uvc_video_queue *queue, enum v4l2_buf_type type)
+{
+	int ret;
+
+	mutex_lock(&queue->mutex);
+	ret = vb2_streamoff(&queue->queue, type);
+	mutex_unlock(&queue->mutex);
+
+	return ret;
+}
+
 int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
 {
 	int ret;
@@ -318,37 +340,6 @@ int uvc_queue_allocated(struct uvc_video_queue *queue)
 }
 
 /*
- * Enable or disable the video buffers queue.
- *
- * The queue must be enabled before starting video acquisition and must be
- * disabled after stopping it. This ensures that the video buffers queue
- * state can be properly initialized before buffers are accessed from the
- * interrupt handler.
- *
- * Enabling the video queue returns -EBUSY if the queue is already enabled.
- *
- * Disabling the video queue cancels the queue and removes all buffers from
- * the main 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)
-{
-	int ret;
-
-	mutex_lock(&queue->mutex);
-
-	if (enable)
-		ret = vb2_streamon(&queue->queue, queue->queue.type);
-	else
-		ret = vb2_streamoff(&queue->queue, queue->queue.type);
-
-	mutex_unlock(&queue->mutex);
-	return ret;
-}
-
-/*
  * Cancel the video buffers queue.
  *
  * Cancelling the queue marks all buffers on the irq queue as erroneous,
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 5ba023b..9c5cbcf 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -757,14 +757,11 @@ static int uvc_ioctl_streamon(struct file *file, void *fh,
 	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_queue_enable(&stream->queue, 1);
+	ret = uvc_queue_streamon(&stream->queue, type);
 	mutex_unlock(&stream->mutex);
 
 	return ret;
@@ -776,14 +773,11 @@ static int uvc_ioctl_streamoff(struct file *file, void *fh,
 	struct uvc_fh *handle = fh;
 	struct uvc_streaming *stream = handle->stream;
 
-	if (type != stream->type)
-		return -EINVAL;
-
 	if (!uvc_has_privileges(handle))
 		return -EBUSY;
 
 	mutex_lock(&stream->mutex);
-	uvc_queue_enable(&stream->queue, 0);
+	uvc_queue_streamoff(&stream->queue, type);
 	mutex_unlock(&stream->mutex);
 
 	return 0;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 2dc247a..f0a04b5 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -634,7 +634,10 @@ extern int uvc_queue_buffer(struct uvc_video_queue *queue,
 		struct v4l2_buffer *v4l2_buf);
 extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
 		struct v4l2_buffer *v4l2_buf, int nonblocking);
-extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
+extern int uvc_queue_streamon(struct uvc_video_queue *queue,
+			      enum v4l2_buf_type type);
+extern int uvc_queue_streamoff(struct uvc_video_queue *queue,
+			       enum v4l2_buf_type type);
 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);
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 11/11] uvcvideo: Give back all buffers to userspace when stopping the stream
  2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
                   ` (9 preceding siblings ...)
  2014-10-31 13:54 ` [PATCH v2 10/11] uvcvideo: Rename and split uvc_queue_enable to uvc_queue_stream(on|off) Laurent Pinchart
@ 2014-10-31 13:54 ` Laurent Pinchart
  10 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 13:54 UTC (permalink / raw)
  To: linux-media

videobuf2 requires drivers to give back ownership of all queue buffers
in the stop_streaming operation. Mark all queued buffers as done in the
error state.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/usb/uvc/uvc_queue.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index c295c5c..0ad442c 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -42,6 +42,23 @@ uvc_queue_to_stream(struct uvc_video_queue *queue)
 	return container_of(queue, struct uvc_streaming, queue);
 }
 
+/*
+ * Give back all queued buffers to videobuf2 and userspace in the error state.
+ *
+ * This function must be called with the queue spinlock held.
+ */
+static void __uvc_queue_cancel(struct uvc_video_queue *queue)
+{
+	while (!list_empty(&queue->irqqueue)) {
+		struct uvc_buffer *buf = list_first_entry(&queue->irqqueue,
+							  struct uvc_buffer,
+							  queue);
+		list_del(&buf->queue);
+		buf->state = UVC_BUF_STATE_ERROR;
+		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+	}
+}
+
 /* -----------------------------------------------------------------------------
  * videobuf2 queue operations
  */
@@ -154,7 +171,7 @@ static void uvc_stop_streaming(struct vb2_queue *vq)
 	uvc_video_enable(stream, 0);
 
 	spin_lock_irqsave(&queue->irqlock, flags);
-	INIT_LIST_HEAD(&queue->irqqueue);
+	__uvc_queue_cancel(queue);
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 }
 
@@ -353,17 +370,10 @@ int uvc_queue_allocated(struct uvc_video_queue *queue)
  */
 void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
 {
-	struct uvc_buffer *buf;
 	unsigned long flags;
 
 	spin_lock_irqsave(&queue->irqlock, flags);
-	while (!list_empty(&queue->irqqueue)) {
-		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
-				       queue);
-		list_del(&buf->queue);
-		buf->state = UVC_BUF_STATE_ERROR;
-		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
-	}
+	__uvc_queue_cancel(queue);
 	/* This must be protected by the irqlock spinlock to avoid race
 	 * conditions between uvc_buffer_queue and the disconnection event that
 	 * could result in an interruptible wait in uvc_dequeue_buffer. Do not
-- 
2.0.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 03/11] uvcvideo: Add V4L2 debug module parameter
  2014-10-31 13:54 ` [PATCH v2 03/11] uvcvideo: Add V4L2 debug module parameter Laurent Pinchart
@ 2014-10-31 14:39   ` Hans Verkuil
  2014-10-31 14:43     ` Laurent Pinchart
  0 siblings, 1 reply; 14+ messages in thread
From: Hans Verkuil @ 2014-10-31 14:39 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media

On 10/31/2014 02:54 PM, Laurent Pinchart wrote:
> Add a new debug module parameter and use it to initialize the V4L2 debug
> level for all video devices.

This patch is unnecessary and can be dropped. You can dynamically set it through
echo 1 >/sys/class/video4linux/videoX/debug.

Drivers shouldn't touch debug themselves.

Regards,

	Hans

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/usb/uvc/uvc_driver.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
> index 30163432..1cae974 100644
> --- a/drivers/media/usb/uvc/uvc_driver.c
> +++ b/drivers/media/usb/uvc/uvc_driver.c
> @@ -34,6 +34,7 @@
>  unsigned int uvc_clock_param = CLOCK_MONOTONIC;
>  unsigned int uvc_no_drop_param;
>  static unsigned int uvc_quirks_param = -1;
> +static unsigned int uvc_debug_param;
>  unsigned int uvc_trace_param;
>  unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
>  
> @@ -1763,6 +1764,7 @@ static int uvc_register_video(struct uvc_device *dev,
>  	vdev->ioctl_ops = &uvc_ioctl_ops;
>  	vdev->release = uvc_release;
>  	vdev->prio = &stream->chain->prio;
> +	vdev->debug = uvc_debug_param;
>  	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
>  		vdev->vfl_dir = VFL_DIR_TX;
>  	strlcpy(vdev->name, dev->name, sizeof vdev->name);
> @@ -2080,6 +2082,8 @@ static int uvc_clock_param_set(const char *val, struct kernel_param *kp)
>  module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
>  		  &uvc_clock_param, S_IRUGO|S_IWUSR);
>  MODULE_PARM_DESC(clock, "Video buffers timestamp clock");
> +module_param_named(debug, uvc_debug_param, uint, S_IRUGO);
> +MODULE_PARM_DESC(debug, "V4L2 debug level");
>  module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
>  MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
>  module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 03/11] uvcvideo: Add V4L2 debug module parameter
  2014-10-31 14:39   ` Hans Verkuil
@ 2014-10-31 14:43     ` Laurent Pinchart
  0 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-10-31 14:43 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media

Hi Hans,

On Friday 31 October 2014 15:39:04 Hans Verkuil wrote:
> On 10/31/2014 02:54 PM, Laurent Pinchart wrote:
> > Add a new debug module parameter and use it to initialize the V4L2 debug
> > level for all video devices.
> 
> This patch is unnecessary and can be dropped. You can dynamically set it
> through echo 1 >/sys/class/video4linux/videoX/debug.
> 
> Drivers shouldn't touch debug themselves.

Good point and sorry for the noise. I'll drop the patch.

> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/media/usb/uvc/uvc_driver.c | 4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/drivers/media/usb/uvc/uvc_driver.c
> > b/drivers/media/usb/uvc/uvc_driver.c index 30163432..1cae974 100644
> > --- a/drivers/media/usb/uvc/uvc_driver.c
> > +++ b/drivers/media/usb/uvc/uvc_driver.c
> > @@ -34,6 +34,7 @@
> > 
> >  unsigned int uvc_clock_param = CLOCK_MONOTONIC;
> >  unsigned int uvc_no_drop_param;
> >  static unsigned int uvc_quirks_param = -1;
> > 
> > +static unsigned int uvc_debug_param;
> > 
> >  unsigned int uvc_trace_param;
> >  unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
> > 
> > @@ -1763,6 +1764,7 @@ static int uvc_register_video(struct uvc_device
> > *dev,
> > 
> >  	vdev->ioctl_ops = &uvc_ioctl_ops;
> >  	vdev->release = uvc_release;
> >  	vdev->prio = &stream->chain->prio;
> > 
> > +	vdev->debug = uvc_debug_param;
> > 
> >  	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
> >  	
> >  		vdev->vfl_dir = VFL_DIR_TX;
> >  	
> >  	strlcpy(vdev->name, dev->name, sizeof vdev->name);
> > 
> > @@ -2080,6 +2082,8 @@ static int uvc_clock_param_set(const char *val,
> > struct kernel_param *kp)> 
> >  module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
> >  
> >  		  &uvc_clock_param, S_IRUGO|S_IWUSR);
> >  
> >  MODULE_PARM_DESC(clock, "Video buffers timestamp clock");
> > 
> > +module_param_named(debug, uvc_debug_param, uint, S_IRUGO);
> > +MODULE_PARM_DESC(debug, "V4L2 debug level");
> > 
> >  module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
> >  MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
> >  module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-10-31 14:43 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-31 13:54 [PATCH v2 00/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 01/11] v4l2: get/set prio using video_dev prio structure Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 02/11] uvcvideo: Move to video_ioctl2 Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 03/11] uvcvideo: Add V4L2 debug module parameter Laurent Pinchart
2014-10-31 14:39   ` Hans Verkuil
2014-10-31 14:43     ` Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 04/11] uvcvideo: Set buffer field to V4L2_FIELD_NONE Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 05/11] uvcvideo: Separate video and queue enable/disable operations Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 06/11] uvcvideo: Add function to convert from queue to stream Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 07/11] uvcvideo: Implement vb2 queue start and stop stream operations Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 08/11] uvcvideo: Don't stop the stream twice at file handle release Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 09/11] uvcvideo: Rename uvc_alloc_buffers to uvc_request_buffers Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 10/11] uvcvideo: Rename and split uvc_queue_enable to uvc_queue_stream(on|off) Laurent Pinchart
2014-10-31 13:54 ` [PATCH v2 11/11] uvcvideo: Give back all buffers to userspace when stopping the stream Laurent Pinchart

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).