Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 02 Feb 2015 08:52:46 +0100
From:      Hans Petter Selasky <hps@selasky.org>
To:        Kohji Okuno <okuno.kohji@jp.panasonic.com>
Cc:        freebsd-usb@freebsd.org
Subject:   Re: [Bug?] Control Transfers in xHCI
Message-ID:  <54CF2CCE.9090101@selasky.org>
In-Reply-To: <20150202.100611.2049338919815112954.okuno.kohji@jp.panasonic.com>
References:  <54CA4BE3.2090706@selasky.org>	<20150129195714.GA3683@dchagin.static.corbina.net>	<54CA9144.4030601@selasky.org> <20150202.100611.2049338919815112954.okuno.kohji@jp.panasonic.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------000306000605080001060004
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

Please find updated patch. The control_rem is pre-decremented and not 
post-decremented.

--HPS

--------------000306000605080001060004
Content-Type: text/x-patch;
 name="xhci.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="xhci.patch"

Index: sys/dev/usb/controller/xhci.c
===================================================================
--- sys/dev/usb/controller/xhci.c	(revision 277724)
+++ sys/dev/usb/controller/xhci.c	(working copy)
@@ -1866,6 +1866,15 @@
 				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE);
 				if (temp->direction == UE_DIR_IN)
 					dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+				/*
+				 * Section 3.2.9 in the XHCI
+				 * specification about control
+				 * transfers says that we should use a
+				 * normal-TRB if there are more TRBs
+				 * extending the data-stage
+				 * TRB. Update the "trb_type".
+				 */
+				temp->trb_type = XHCI_TRB_TYPE_NORMAL;
 				break;
 			case XHCI_TRB_TYPE_STATUS_STAGE:
 				dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
@@ -2106,7 +2115,8 @@
 		mult = 1;
 		temp.isoc_delta = 0;
 		temp.isoc_frame = 0;
-		temp.trb_type = XHCI_TRB_TYPE_DATA_STAGE;
+		temp.trb_type = xfer->flags_int.control_did_data ?
+		    XHCI_TRB_TYPE_NORMAL : XHCI_TRB_TYPE_DATA_STAGE;
 	} else {
 		x = 0;
 		mult = 1;
Index: sys/dev/usb/usb_core.h
===================================================================
--- sys/dev/usb/usb_core.h	(revision 277724)
+++ sys/dev/usb/usb_core.h	(working copy)
@@ -101,6 +101,7 @@
 					 * sent */
 	uint8_t	control_act:1;		/* set if control transfer is active */
 	uint8_t	control_stall:1;	/* set if control transfer should be stalled */
+	uint8_t control_did_data:1;	/* set if control data has been sent */
 
 	uint8_t	short_frames_ok:1;	/* filtered version */
 	uint8_t	short_xfer_ok:1;	/* filtered version */
Index: sys/dev/usb/usb_transfer.c
===================================================================
--- sys/dev/usb/usb_transfer.c	(revision 277724)
+++ sys/dev/usb/usb_transfer.c	(working copy)
@@ -1409,6 +1409,28 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	usbd_control_transfer_did_data
+ *
+ * This function returns non-zero if a control endpoint has done the
+ * first DATA packet after the SETUP packet.  Else it returns zero.
+ *------------------------------------------------------------------------*/
+static uint8_t
+usbd_control_transfer_did_data(struct usb_xfer *xfer)
+{
+	struct usb_device_request req;
+
+	/* SETUP packet is not yet sent */
+	if (xfer->flags_int.control_hdr != 0)
+		return (0);
+
+	/* copy out the USB request header */
+	usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
+
+	/* compare remainder to the initial value */
+	return (xfer->flags_int.control_rem != UGETW(req.wLength));
+}
+
+/*------------------------------------------------------------------------*
  *	usbd_setup_ctrl_transfer
  *
  * This function handles initialisation of control transfers. Control
@@ -1513,6 +1535,11 @@
 		len = (xfer->sumlen - sizeof(struct usb_device_request));
 	}
 
+	/* update did data flag */
+
+	xfer->flags_int.control_did_data =
+	    usbd_control_transfer_did_data(xfer);
+
 	/* check if there is a length mismatch */
 
 	if (len > xfer->flags_int.control_rem) {

--------------000306000605080001060004--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?54CF2CCE.9090101>