diff options
Diffstat (limited to 'drivers/media/video/uvc/uvc_queue.c')
-rw-r--r-- | drivers/media/video/uvc/uvc_queue.c | 23 |
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 | ||
82 | void uvc_queue_init(struct uvc_video_queue *queue) | 82 | void 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); |