}
/*
- * look for an input transfer endpoint in an alternate setting
+ * look for an input transfer endpoint in an alternate setting.
+ *
+ * If xfer_ep is invalid, return the first valid ep found, otherwise
+ * look for exactly the ep with address equal to xfer_ep.
*/
static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
- int xfer)
+ int xfer, int xfer_ep)
{
struct usb_host_endpoint *ep;
int i, attr;
attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (attr == xfer
&& ep->desc.wMaxPacketSize != 0
- && usb_endpoint_dir_in(&ep->desc))
+ && usb_endpoint_dir_in(&ep->desc)
+ && (xfer_ep < 0 || ep->desc.bEndpointAddress == xfer_ep))
return ep;
}
return NULL;
found = 0;
for (j = 0; j < nbalt; j++) {
ep = alt_xfer(&intf->altsetting[j],
- USB_ENDPOINT_XFER_ISOC);
+ USB_ENDPOINT_XFER_ISOC,
+ gspca_dev->xfer_ep);
if (ep == NULL)
continue;
if (ep->desc.bInterval == 0) {
/* if bulk or the subdriver forced an altsetting, get the endpoint */
if (gspca_dev->alt != 0) {
gspca_dev->alt--; /* (previous version compatibility) */
- ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+ ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer,
+ gspca_dev->xfer_ep);
if (ep == NULL) {
pr_err("bad altsetting %d\n", gspca_dev->alt);
return -EIO;
if (!gspca_dev->cam.no_urb_create) {
PDEBUG(D_STREAM, "init transfer alt %d", alt);
ret = create_urbs(gspca_dev,
- alt_xfer(&intf->altsetting[alt], xfer));
+ alt_xfer(&intf->altsetting[alt], xfer,
+ gspca_dev->xfer_ep));
if (ret < 0) {
destroy_urbs(gspca_dev);
goto out;
}
gspca_dev->dev = dev;
gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
+ gspca_dev->xfer_ep = -1;
/* check if any audio device */
if (dev->actconfig->desc.bNumInterfaces != 1) {