diff options
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r-- | drivers/media/video/uvc/uvc_queue.c | 13 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 19 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 5 |
3 files changed, 23 insertions, 14 deletions
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 133c78d113ac..e9928a415086 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -78,12 +78,14 @@ | |||
78 | * | 78 | * |
79 | */ | 79 | */ |
80 | 80 | ||
81 | void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) | 81 | void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, |
82 | int drop_corrupted) | ||
82 | { | 83 | { |
83 | mutex_init(&queue->mutex); | 84 | mutex_init(&queue->mutex); |
84 | spin_lock_init(&queue->irqlock); | 85 | spin_lock_init(&queue->irqlock); |
85 | INIT_LIST_HEAD(&queue->mainqueue); | 86 | INIT_LIST_HEAD(&queue->mainqueue); |
86 | INIT_LIST_HEAD(&queue->irqqueue); | 87 | INIT_LIST_HEAD(&queue->irqqueue); |
88 | queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0; | ||
87 | queue->type = type; | 89 | queue->type = type; |
88 | } | 90 | } |
89 | 91 | ||
@@ -435,8 +437,10 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable) | |||
435 | uvc_queue_cancel(queue, 0); | 437 | uvc_queue_cancel(queue, 0); |
436 | INIT_LIST_HEAD(&queue->mainqueue); | 438 | INIT_LIST_HEAD(&queue->mainqueue); |
437 | 439 | ||
438 | for (i = 0; i < queue->count; ++i) | 440 | for (i = 0; i < queue->count; ++i) { |
441 | queue->buffer[i].error = 0; | ||
439 | queue->buffer[i].state = UVC_BUF_STATE_IDLE; | 442 | queue->buffer[i].state = UVC_BUF_STATE_IDLE; |
443 | } | ||
440 | 444 | ||
441 | queue->flags &= ~UVC_QUEUE_STREAMING; | 445 | queue->flags &= ~UVC_QUEUE_STREAMING; |
442 | } | 446 | } |
@@ -488,8 +492,8 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
488 | struct uvc_buffer *nextbuf; | 492 | struct uvc_buffer *nextbuf; |
489 | unsigned long flags; | 493 | unsigned long flags; |
490 | 494 | ||
491 | if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && | 495 | if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { |
492 | buf->buf.length != buf->buf.bytesused) { | 496 | buf->error = 0; |
493 | buf->state = UVC_BUF_STATE_QUEUED; | 497 | buf->state = UVC_BUF_STATE_QUEUED; |
494 | buf->buf.bytesused = 0; | 498 | buf->buf.bytesused = 0; |
495 | return buf; | 499 | return buf; |
@@ -497,6 +501,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
497 | 501 | ||
498 | spin_lock_irqsave(&queue->irqlock, flags); | 502 | spin_lock_irqsave(&queue->irqlock, flags); |
499 | list_del(&buf->queue); | 503 | list_del(&buf->queue); |
504 | buf->error = 0; | ||
500 | buf->state = UVC_BUF_STATE_DONE; | 505 | buf->state = UVC_BUF_STATE_DONE; |
501 | if (!list_empty(&queue->irqqueue)) | 506 | if (!list_empty(&queue->irqqueue)) |
502 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | 507 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 53f3ef4635eb..e27cf0d3b6d9 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -555,6 +555,9 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, | |||
555 | if (urb->iso_frame_desc[i].status < 0) { | 555 | if (urb->iso_frame_desc[i].status < 0) { |
556 | uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " | 556 | uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " |
557 | "lost (%d).\n", urb->iso_frame_desc[i].status); | 557 | "lost (%d).\n", urb->iso_frame_desc[i].status); |
558 | /* Mark the buffer as faulty. */ | ||
559 | if (buf != NULL) | ||
560 | buf->error = 1; | ||
558 | continue; | 561 | continue; |
559 | } | 562 | } |
560 | 563 | ||
@@ -579,8 +582,14 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, | |||
579 | uvc_video_decode_end(stream, buf, mem, | 582 | uvc_video_decode_end(stream, buf, mem, |
580 | urb->iso_frame_desc[i].actual_length); | 583 | urb->iso_frame_desc[i].actual_length); |
581 | 584 | ||
582 | if (buf->state == UVC_BUF_STATE_READY) | 585 | if (buf->state == UVC_BUF_STATE_READY) { |
586 | if (buf->buf.length != buf->buf.bytesused && | ||
587 | !(stream->cur_format->flags & | ||
588 | UVC_FMT_FLAG_COMPRESSED)) | ||
589 | buf->error = 1; | ||
590 | |||
583 | buf = uvc_queue_next_buffer(&stream->queue, buf); | 591 | buf = uvc_queue_next_buffer(&stream->queue, buf); |
592 | } | ||
584 | } | 593 | } |
585 | } | 594 | } |
586 | 595 | ||
@@ -1104,7 +1113,7 @@ int uvc_video_init(struct uvc_streaming *stream) | |||
1104 | atomic_set(&stream->active, 0); | 1113 | atomic_set(&stream->active, 0); |
1105 | 1114 | ||
1106 | /* Initialize the video buffers queue. */ | 1115 | /* Initialize the video buffers queue. */ |
1107 | uvc_queue_init(&stream->queue, stream->type); | 1116 | uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param); |
1108 | 1117 | ||
1109 | /* Alternate setting 0 should be the default, yet the XBox Live Vision | 1118 | /* Alternate setting 0 should be the default, yet the XBox Live Vision |
1110 | * Cam (and possibly other devices) crash or otherwise misbehave if | 1119 | * Cam (and possibly other devices) crash or otherwise misbehave if |
@@ -1197,12 +1206,6 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) | |||
1197 | return 0; | 1206 | return 0; |
1198 | } | 1207 | } |
1199 | 1208 | ||
1200 | if ((stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) || | ||
1201 | uvc_no_drop_param) | ||
1202 | stream->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; | ||
1203 | else | ||
1204 | stream->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; | ||
1205 | |||
1206 | ret = uvc_queue_enable(&stream->queue, 1); | 1209 | ret = uvc_queue_enable(&stream->queue, 1); |
1207 | if (ret < 0) | 1210 | if (ret < 0) |
1208 | return ret; | 1211 | return ret; |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index ac272456fbfd..bdacf3beabf5 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -379,11 +379,12 @@ struct uvc_buffer { | |||
379 | struct list_head queue; | 379 | struct list_head queue; |
380 | wait_queue_head_t wait; | 380 | wait_queue_head_t wait; |
381 | enum uvc_buffer_state state; | 381 | enum uvc_buffer_state state; |
382 | unsigned int error; | ||
382 | }; | 383 | }; |
383 | 384 | ||
384 | #define UVC_QUEUE_STREAMING (1 << 0) | 385 | #define UVC_QUEUE_STREAMING (1 << 0) |
385 | #define UVC_QUEUE_DISCONNECTED (1 << 1) | 386 | #define UVC_QUEUE_DISCONNECTED (1 << 1) |
386 | #define UVC_QUEUE_DROP_INCOMPLETE (1 << 2) | 387 | #define UVC_QUEUE_DROP_CORRUPTED (1 << 2) |
387 | 388 | ||
388 | struct uvc_video_queue { | 389 | struct uvc_video_queue { |
389 | enum v4l2_buf_type type; | 390 | enum v4l2_buf_type type; |
@@ -562,7 +563,7 @@ extern struct uvc_driver uvc_driver; | |||
562 | 563 | ||
563 | /* Video buffers queue management. */ | 564 | /* Video buffers queue management. */ |
564 | extern void uvc_queue_init(struct uvc_video_queue *queue, | 565 | extern void uvc_queue_init(struct uvc_video_queue *queue, |
565 | enum v4l2_buf_type type); | 566 | enum v4l2_buf_type type, int drop_corrupted); |
566 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, | 567 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, |
567 | unsigned int nbuffers, unsigned int buflength); | 568 | unsigned int nbuffers, unsigned int buflength); |
568 | extern int uvc_free_buffers(struct uvc_video_queue *queue); | 569 | extern int uvc_free_buffers(struct uvc_video_queue *queue); |