aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc/uvc_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/uvc/uvc_queue.c')
-rw-r--r--drivers/media/video/uvc/uvc_queue.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 5646a6a32939..42546342e97d 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -79,12 +79,13 @@
79 * 79 *
80 */ 80 */
81 81
82void uvc_queue_init(struct uvc_video_queue *queue) 82void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
83{ 83{
84 mutex_init(&queue->mutex); 84 mutex_init(&queue->mutex);
85 spin_lock_init(&queue->irqlock); 85 spin_lock_init(&queue->irqlock);
86 INIT_LIST_HEAD(&queue->mainqueue); 86 INIT_LIST_HEAD(&queue->mainqueue);
87 INIT_LIST_HEAD(&queue->irqqueue); 87 INIT_LIST_HEAD(&queue->irqqueue);
88 queue->type = type;
88} 89}
89 90
90/* 91/*
@@ -132,7 +133,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
132 queue->buffer[i].buf.index = i; 133 queue->buffer[i].buf.index = i;
133 queue->buffer[i].buf.m.offset = i * bufsize; 134 queue->buffer[i].buf.m.offset = i * bufsize;
134 queue->buffer[i].buf.length = buflength; 135 queue->buffer[i].buf.length = buflength;
135 queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 136 queue->buffer[i].buf.type = queue->type;
136 queue->buffer[i].buf.sequence = 0; 137 queue->buffer[i].buf.sequence = 0;
137 queue->buffer[i].buf.field = V4L2_FIELD_NONE; 138 queue->buffer[i].buf.field = V4L2_FIELD_NONE;
138 queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; 139 queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
@@ -226,7 +227,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue,
226 227
227 uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); 228 uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
228 229
229 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || 230 if (v4l2_buf->type != queue->type ||
230 v4l2_buf->memory != V4L2_MEMORY_MMAP) { 231 v4l2_buf->memory != V4L2_MEMORY_MMAP) {
231 uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " 232 uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
232 "and/or memory (%u).\n", v4l2_buf->type, 233 "and/or memory (%u).\n", v4l2_buf->type,
@@ -249,6 +250,13 @@ int uvc_queue_buffer(struct uvc_video_queue *queue,
249 goto done; 250 goto done;
250 } 251 }
251 252
253 if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
254 v4l2_buf->bytesused > buf->buf.length) {
255 uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
256 ret = -EINVAL;
257 goto done;
258 }
259
252 spin_lock_irqsave(&queue->irqlock, flags); 260 spin_lock_irqsave(&queue->irqlock, flags);
253 if (queue->flags & UVC_QUEUE_DISCONNECTED) { 261 if (queue->flags & UVC_QUEUE_DISCONNECTED) {
254 spin_unlock_irqrestore(&queue->irqlock, flags); 262 spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -256,7 +264,11 @@ int uvc_queue_buffer(struct uvc_video_queue *queue,
256 goto done; 264 goto done;
257 } 265 }
258 buf->state = UVC_BUF_STATE_QUEUED; 266 buf->state = UVC_BUF_STATE_QUEUED;
259 buf->buf.bytesused = 0; 267 if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
268 buf->buf.bytesused = 0;
269 else
270 buf->buf.bytesused = v4l2_buf->bytesused;
271
260 list_add_tail(&buf->stream, &queue->mainqueue); 272 list_add_tail(&buf->stream, &queue->mainqueue);
261 list_add_tail(&buf->queue, &queue->irqqueue); 273 list_add_tail(&buf->queue, &queue->irqqueue);
262 spin_unlock_irqrestore(&queue->irqlock, flags); 274 spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -289,7 +301,7 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue,
289 struct uvc_buffer *buf; 301 struct uvc_buffer *buf;
290 int ret = 0; 302 int ret = 0;
291 303
292 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || 304 if (v4l2_buf->type != queue->type ||
293 v4l2_buf->memory != V4L2_MEMORY_MMAP) { 305 v4l2_buf->memory != V4L2_MEMORY_MMAP) {
294 uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " 306 uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
295 "and/or memory (%u).\n", v4l2_buf->type, 307 "and/or memory (%u).\n", v4l2_buf->type,
@@ -397,6 +409,7 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
397 } 409 }
398 queue->sequence = 0; 410 queue->sequence = 0;
399 queue->flags |= UVC_QUEUE_STREAMING; 411 queue->flags |= UVC_QUEUE_STREAMING;
412 queue->buf_used = 0;
400 } else { 413 } else {
401 uvc_queue_cancel(queue, 0); 414 uvc_queue_cancel(queue, 0);
402 INIT_LIST_HEAD(&queue->mainqueue); 415 INIT_LIST_HEAD(&queue->mainqueue);