|
@@ -441,7 +441,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
|
|
|
if (fid != stream->last_fid && buf->buf.bytesused != 0) {
|
|
|
uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
|
|
|
"toggled).\n");
|
|
|
- buf->state = UVC_BUF_STATE_DONE;
|
|
|
+ buf->state = UVC_BUF_STATE_READY;
|
|
|
return -EAGAIN;
|
|
|
}
|
|
|
|
|
@@ -470,7 +470,7 @@ static void uvc_video_decode_data(struct uvc_streaming *stream,
|
|
|
/* Complete the current frame if the buffer size was exceeded. */
|
|
|
if (len > maxlen) {
|
|
|
uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
|
|
|
- buf->state = UVC_BUF_STATE_DONE;
|
|
|
+ buf->state = UVC_BUF_STATE_READY;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -482,7 +482,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream,
|
|
|
uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
|
|
|
if (data[0] == len)
|
|
|
uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
|
|
|
- buf->state = UVC_BUF_STATE_DONE;
|
|
|
+ buf->state = UVC_BUF_STATE_READY;
|
|
|
if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID)
|
|
|
stream->last_fid ^= UVC_STREAM_FID;
|
|
|
}
|
|
@@ -568,8 +568,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
|
|
|
uvc_video_decode_end(stream, buf, mem,
|
|
|
urb->iso_frame_desc[i].actual_length);
|
|
|
|
|
|
- if (buf->state == UVC_BUF_STATE_DONE ||
|
|
|
- buf->state == UVC_BUF_STATE_ERROR)
|
|
|
+ if (buf->state == UVC_BUF_STATE_READY)
|
|
|
buf = uvc_queue_next_buffer(&stream->queue, buf);
|
|
|
}
|
|
|
}
|
|
@@ -627,8 +626,7 @@ static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream,
|
|
|
if (!stream->bulk.skip_payload && buf != NULL) {
|
|
|
uvc_video_decode_end(stream, buf, stream->bulk.header,
|
|
|
stream->bulk.payload_size);
|
|
|
- if (buf->state == UVC_BUF_STATE_DONE ||
|
|
|
- buf->state == UVC_BUF_STATE_ERROR)
|
|
|
+ if (buf->state == UVC_BUF_STATE_READY)
|
|
|
buf = uvc_queue_next_buffer(&stream->queue,
|
|
|
buf);
|
|
|
}
|
|
@@ -669,7 +667,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
|
|
|
stream->bulk.payload_size == stream->bulk.max_payload_size) {
|
|
|
if (buf->buf.bytesused == stream->queue.buf_used) {
|
|
|
stream->queue.buf_used = 0;
|
|
|
- buf->state = UVC_BUF_STATE_DONE;
|
|
|
+ buf->state = UVC_BUF_STATE_READY;
|
|
|
uvc_queue_next_buffer(&stream->queue, buf);
|
|
|
stream->last_fid ^= UVC_STREAM_FID;
|
|
|
}
|
|
@@ -924,10 +922,8 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
|
|
|
static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
|
|
|
{
|
|
|
struct usb_interface *intf = stream->intf;
|
|
|
- struct usb_host_interface *alts;
|
|
|
- struct usb_host_endpoint *ep = NULL;
|
|
|
- int intfnum = stream->intfnum;
|
|
|
- unsigned int bandwidth, psize, i;
|
|
|
+ struct usb_host_endpoint *ep;
|
|
|
+ unsigned int i;
|
|
|
int ret;
|
|
|
|
|
|
stream->last_fid = -1;
|
|
@@ -936,6 +932,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
|
|
|
stream->bulk.payload_size = 0;
|
|
|
|
|
|
if (intf->num_altsetting > 1) {
|
|
|
+ struct usb_host_endpoint *best_ep = NULL;
|
|
|
+ unsigned int best_psize = 3 * 1024;
|
|
|
+ unsigned int bandwidth;
|
|
|
+ unsigned int uninitialized_var(altsetting);
|
|
|
+ int intfnum = stream->intfnum;
|
|
|
+
|
|
|
/* Isochronous endpoint, select the alternate setting. */
|
|
|
bandwidth = stream->ctrl.dwMaxPayloadTransferSize;
|
|
|
|
|
@@ -949,6 +951,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < intf->num_altsetting; ++i) {
|
|
|
+ struct usb_host_interface *alts;
|
|
|
+ unsigned int psize;
|
|
|
+
|
|
|
alts = &intf->altsetting[i];
|
|
|
ep = uvc_find_endpoint(alts,
|
|
|
stream->header.bEndpointAddress);
|
|
@@ -958,21 +963,27 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
|
|
|
/* Check if the bandwidth is high enough. */
|
|
|
psize = le16_to_cpu(ep->desc.wMaxPacketSize);
|
|
|
psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
|
|
|
- if (psize >= bandwidth)
|
|
|
- break;
|
|
|
+ if (psize >= bandwidth && psize <= best_psize) {
|
|
|
+ altsetting = i;
|
|
|
+ best_psize = psize;
|
|
|
+ best_ep = ep;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (i >= intf->num_altsetting) {
|
|
|
+ if (best_ep == NULL) {
|
|
|
uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting "
|
|
|
"for requested bandwidth.\n");
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
- ret = usb_set_interface(stream->dev->udev, intfnum, i);
|
|
|
+ uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u "
|
|
|
+ "(%u B/frame bandwidth).\n", altsetting, best_psize);
|
|
|
+
|
|
|
+ ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- ret = uvc_init_video_isoc(stream, ep, gfp_flags);
|
|
|
+ ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);
|
|
|
} else {
|
|
|
/* Bulk endpoint, proceed to URB initialization. */
|
|
|
ep = uvc_find_endpoint(&intf->altsetting[0],
|