On Tue, Apr 22, 2014 at 05:49:03PM -0500, Matt DeVillier wrote: > From: Matt DeVillier <matt.devillier@xxxxxxxxx> > > Change the I/O endpoint handling of the mceusb driver to respect the > endpoint type reported by device (bulk/interrupt), rather than > treating all endpoints as type interrupt, which breaks devices using > bulk endpoints when connected to a xhci controller. Accordingly, > change the function calls to initialize an endpoint's transfer pipe > and urb handlers to use the correct function based on the endpoint > type. > > Signed-off-by: Matt DeVillier <matt.devillier@xxxxxxxxx> > --- > This is a continuation of the work started in patch #21648 > Patch compiled and tested against linux-media git master. Backported > and tested against 3.14.1 stable as well. > --- > --- mceusb.c.orig 2014-04-22 13:48:51.186259472 -0500 > +++ mceusb.c 2014-04-22 14:46:12.378347584 -0500 > @@ -747,11 +747,17 @@ static void mce_request_packet(struct mc > } > > /* outbound data */ > - pipe = usb_sndintpipe(ir->usbdev, > - ir->usb_ep_out->bEndpointAddress); > - usb_fill_int_urb(async_urb, ir->usbdev, pipe, > - async_buf, size, mce_async_callback, > - ir, ir->usb_ep_out->bInterval); > + if ((ir->usb_ep_out->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > + == USB_ENDPOINT_XFER_INT) { > + pipe = usb_sndintpipe(ir->usbdev, > ir->usb_ep_out->bEndpointAddress); The lines are wrapped and tabs have been replaced with spaces; your mail client messed with your patch. See https://www.kernel.org/doc/Documentation/email-clients.txt > + usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf, > + size, mce_async_callback, ir, > ir->usb_ep_out->bInterval); > + } else { > + pipe = usb_sndbulkpipe(ir->usbdev, > + ir->usb_ep_out->bEndpointAddress); > + usb_fill_bulk_urb(async_urb, ir->usbdev, pipe, async_buf, > + size, mce_async_callback, ir); > + } > memcpy(async_buf, data, size); > > } else if (urb_type == MCEUSB_RX) { > @@ -1271,38 +1277,48 @@ static int mceusb_dev_probe(struct usb_i > > if ((ep_in == NULL) > && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) > - == USB_DIR_IN) > - && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > - == USB_ENDPOINT_XFER_BULK) > - || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > - == USB_ENDPOINT_XFER_INT))) { > - > - ep_in = ep; > - ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; > - ep_in->bInterval = 1; > - dev_dbg(&intf->dev, "acceptable inbound endpoint found"); > + == USB_DIR_IN)) { > + > + if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > + == USB_ENDPOINT_XFER_BULK) { > + > + ep_in = ep; > + mce_dbg(&intf->dev, "acceptable bulk inbound > endpoint found\n"); > + } else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > + == USB_ENDPOINT_XFER_INT) { > + > + ep_in = ep; > + ep_in->bInterval = 1; > + mce_dbg(&intf->dev, "acceptable interrupt inbound > endpoint found\n"); > + } > } > > if ((ep_out == NULL) > && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) > - == USB_DIR_OUT) > - && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > - == USB_ENDPOINT_XFER_BULK) > - || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > - == USB_ENDPOINT_XFER_INT))) { > - > - ep_out = ep; > - ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; > - ep_out->bInterval = 1; > - dev_dbg(&intf->dev, "acceptable outbound endpoint found"); > + == USB_DIR_OUT)) { > + if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > + == USB_ENDPOINT_XFER_BULK) { > + ep_out = ep; > + mce_dbg(&intf->dev, "acceptable bulk outbound > endpoint found\n"); > + } else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > + == USB_ENDPOINT_XFER_INT) { > + ep_out = ep; > + ep_out->bInterval = 1; > + mce_dbg(&intf->dev, "acceptable interrupt outbound > endpoint found\n"); > + } > } > } > - if (ep_in == NULL) { > + if (ep_in == NULL || ep_out == NULL) { Although I think this is correct this is unrelated to the rest of the patch. > dev_dbg(&intf->dev, "inbound and/or endpoint not found"); > return -ENODEV; > } > > - pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); > + if ((ep_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > + == USB_ENDPOINT_XFER_INT) { > + pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); > + } else { > + pipe = usb_rcvbulkpipe(dev, ep_in->bEndpointAddress); > + } > maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); > > ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); > @@ -1343,8 +1359,14 @@ static int mceusb_dev_probe(struct usb_i > goto rc_dev_fail; > > /* wire up inbound data handler */ > - usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, > - mceusb_dev_recv, ir, ep_in->bInterval); > + if ((ep_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > + == USB_ENDPOINT_XFER_INT) { > + usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, > + mceusb_dev_recv, ir, ep_in->bInterval); > + } else { > + usb_fill_bulk_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, > + mceusb_dev_recv, ir); > + } > ir->urb_in->transfer_dma = ir->dma_in; > ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; I've tested this patch and it does fix my mceusb device with bulk endpoints on xhci. So Tested-by: Sean Young <sean@xxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html