diff mbox

[v2] fix mceusb endpoint type identification/handling

Message ID 5357D6A4.4070008@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Matt DeVillier April 23, 2014, 3:05 p.m. UTC
From: Matt DeVillier <matt.devillier@gmail.com>

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@gmail.com>
Tested-by: Sean Young <sean@mess.org>
---
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.
v2 corrects some formatting issues (both with the patch itself and MUA), and 
removes a small bug fix not relevant to the core patch functionality.
---

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff -up mceusb.c{.orig,}
--- mceusb.c.orig	2014-04-22 13:48:51.186259472 -0500
+++ mceusb.c	2014-04-23 09:51:50.060107612 -0500
@@ -747,11 +747,19 @@  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);
+			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 +1279,47 @@  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) {
		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 +1360,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;