|
@@ -924,10 +924,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 +934,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 +953,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 +965,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],
|