diff mbox

[take,2] V4L: videobuf-core.c VIDIOC_QBUF should return video buffer flags

Message ID 200908311458.54406.tuukka.o.toivonen@nokia.com (mailing list archive)
State RFC
Headers show

Commit Message

Tuukka.O Toivonen Aug. 31, 2009, 11:58 a.m. UTC
When user space queues a buffer using VIDIOC_QBUF, the kernel
should set flags in struct v4l2_buffer as specified in the V4L2
documentation.
---
 drivers/media/video/videobuf-core.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

Comments

Laurent Pinchart Sept. 1, 2009, 8:56 a.m. UTC | #1
On Monday 31 August 2009 13:58:54 Tuukka.O Toivonen wrote:
> When user space queues a buffer using VIDIOC_QBUF, the kernel
> should set flags in struct v4l2_buffer as specified in the V4L2
> documentation.

You forgot your SoB line.

> ---
>  drivers/media/video/videobuf-core.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/media/video/videobuf-core.c
> b/drivers/media/video/videobuf-core.c index b7b0584..1322056 100644
> --- a/drivers/media/video/videobuf-core.c
> +++ b/drivers/media/video/videobuf-core.c
> @@ -477,6 +477,7 @@ int videobuf_qbuf(struct videobuf_queue *q,
>  	struct videobuf_buffer *buf;
>  	enum v4l2_field field;
>  	unsigned long flags = 0;
> +	__u32 buffer_flags = b->flags;

Is that safe ? What if userspace sets bogus flags ? What about hardcoding the 
flags to V4L2_BUF_FLAG_QUEUED (| V4L2_BUF_FLAG_MAPPED when buf->map is not 
NULL) instead, like videobuf_status does ?

>  	int retval;
>
>  	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
> @@ -531,6 +532,8 @@ int videobuf_qbuf(struct videobuf_queue *q,
>  				   "but buffer addr is zero!\n");
>  			goto done;
>  		}
> +		buffer_flags |= V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
> +		buffer_flags &= ~V4L2_BUF_FLAG_DONE;
>  		break;
>  	case V4L2_MEMORY_USERPTR:
>  		if (b->length < buf->bsize) {
> @@ -541,6 +544,8 @@ int videobuf_qbuf(struct videobuf_queue *q,
>  		    buf->baddr != b->m.userptr)
>  			q->ops->buf_release(q, buf);
>  		buf->baddr = b->m.userptr;
> +		buffer_flags |= V4L2_BUF_FLAG_QUEUED;
> +		buffer_flags &= ~(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE);
>  		break;
>  	case V4L2_MEMORY_OVERLAY:
>  		buf->boff = b->m.offset;
> @@ -564,6 +569,8 @@ int videobuf_qbuf(struct videobuf_queue *q,
>  		q->ops->buf_queue(q, buf);
>  		spin_unlock_irqrestore(q->irqlock, flags);
>  	}
> +
> +	b->flags = buffer_flags;
>  	dprintk(1, "qbuf: succeded\n");
>  	retval = 0;
>  	wake_up_interruptible_sync(&q->wait);
Tuukka.O Toivonen Sept. 1, 2009, 10:58 a.m. UTC | #2
On Tuesday 01 September 2009 11:56:19 ext Laurent Pinchart wrote:
> On Monday 31 August 2009 13:58:54 Tuukka.O Toivonen wrote:
> > When user space queues a buffer using VIDIOC_QBUF, the kernel
> > should set flags in struct v4l2_buffer as specified in the V4L2
> > documentation.
> 
> You forgot your SoB line.

My bad.

> > +	__u32 buffer_flags = b->flags;
> 
> Is that safe ? What if userspace sets bogus flags ? 

What else userspace should expect than garbage in, garbage out?
Now this sets and clears exactly what V4L2 spec says it should, should
we clear all other flags also?

What about other fields that are not mentioned in the VIDIOC_QBUF
documentation for input buffers, like bytesused, timestamp, etc.?
Should VIDIOC_QBUF clear those also?

- Tuukka
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index b7b0584..1322056 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -477,6 +477,7 @@  int videobuf_qbuf(struct videobuf_queue *q,
 	struct videobuf_buffer *buf;
 	enum v4l2_field field;
 	unsigned long flags = 0;
+	__u32 buffer_flags = b->flags;
 	int retval;
 
 	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
@@ -531,6 +532,8 @@  int videobuf_qbuf(struct videobuf_queue *q,
 				   "but buffer addr is zero!\n");
 			goto done;
 		}
+		buffer_flags |= V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
+		buffer_flags &= ~V4L2_BUF_FLAG_DONE;
 		break;
 	case V4L2_MEMORY_USERPTR:
 		if (b->length < buf->bsize) {
@@ -541,6 +544,8 @@  int videobuf_qbuf(struct videobuf_queue *q,
 		    buf->baddr != b->m.userptr)
 			q->ops->buf_release(q, buf);
 		buf->baddr = b->m.userptr;
+		buffer_flags |= V4L2_BUF_FLAG_QUEUED;
+		buffer_flags &= ~(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE);
 		break;
 	case V4L2_MEMORY_OVERLAY:
 		buf->boff = b->m.offset;
@@ -564,6 +569,8 @@  int videobuf_qbuf(struct videobuf_queue *q,
 		q->ops->buf_queue(q, buf);
 		spin_unlock_irqrestore(q->irqlock, flags);
 	}
+
+	b->flags = buffer_flags;
 	dprintk(1, "qbuf: succeded\n");
 	retval = 0;
 	wake_up_interruptible_sync(&q->wait);