aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/uvc/uvc_queue.c13
-rw-r--r--drivers/media/video/uvc/uvc_video.c19
-rw-r--r--drivers/media/video/uvc/uvcvideo.h5
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
81void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) 81void 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
388struct uvc_video_queue { 389struct 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. */
564extern void uvc_queue_init(struct uvc_video_queue *queue, 565extern void uvc_queue_init(struct uvc_video_queue *queue,
565 enum v4l2_buf_type type); 566 enum v4l2_buf_type type, int drop_corrupted);
566extern int uvc_alloc_buffers(struct uvc_video_queue *queue, 567extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
567 unsigned int nbuffers, unsigned int buflength); 568 unsigned int nbuffers, unsigned int buflength);
568extern int uvc_free_buffers(struct uvc_video_queue *queue); 569extern int uvc_free_buffers(struct uvc_video_queue *queue);