[Milkymist-devel] [PATCH 3/4] softusb: implement the reset recovery interval

Werner Almesberger werner at almesberger.net
Tue Nov 15 00:09:45 PST 2011


Sections 7.1.7.5 and 9.2.6.2 of the USB 2.0 spec say the a host has
to wait for at least 10 ms (Trstrcy) after reset before it can expect
a device to be able to receive data.

In Linux drivers/usb/core/hub.c:hub_port_reset we find this:

	/* TRSTRCY = 10 ms; plus some extra */
	msleep(10 + 40);

So let's use 50 ms.
---
 softusb-input/main.c |   28 +++++++++++++++++++---------
 1 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/softusb-input/main.c b/softusb-input/main.c
index 0f58ebd..1f76353 100644
--- a/softusb-input/main.c
+++ b/softusb-input/main.c
@@ -40,6 +40,7 @@ enum {
 enum {
 	PORT_STATE_DISCONNECTED = 0,
 	PORT_STATE_BUS_RESET,
+	PORT_STATE_RESET_WAIT,
 	PORT_STATE_SET_ADDRESS,
 	PORT_STATE_GET_DEVICE_DESCRIPTOR,
 	PORT_STATE_GET_CONFIGURATION_DESCRIPTOR,
@@ -48,6 +49,8 @@ enum {
 	PORT_STATE_UNSUPPORTED
 };
 
+#define	RESET_RECOVERY_MS	50	/* USB 2.0, 7.1.7.5: >= 10 ms */
+
 struct ep_status {
 	char ep;
 	unsigned char expected_data;
@@ -446,7 +449,7 @@ static void port_service(struct port_status *p, char name)
 		wio8(SIE_TX_LOW_SPEED, 0);
 	else
 		wio8(SIE_TX_LOW_SPEED, 1);
-	if((p->full_speed) && (p->state > PORT_STATE_BUS_RESET)) {
+	if((p->full_speed) && (p->state > PORT_STATE_RESET_WAIT)) {
 		/* send SOF */
 		unsigned char usb_buffer[3];
 		make_usb_token(USB_PID_SOF, frame_nr, usb_buffer);
@@ -478,14 +481,21 @@ static void port_service(struct port_status *p, char name)
 			break;
 		}
 		case PORT_STATE_BUS_RESET:
-			if(frame_nr == p->unreset_frame) {
-				if(name == 'A')
-					wio8(SIE_TX_BUSRESET, rio8(SIE_TX_BUSRESET) & 0x02);
-				else
-					wio8(SIE_TX_BUSRESET, rio8(SIE_TX_BUSRESET) & 0x01);
-				p->state = PORT_STATE_SET_ADDRESS;
-				p->retry_count = 0;
-			}
+			if(frame_nr != p->unreset_frame)
+				break;
+			if(name == 'A')
+				wio8(SIE_TX_BUSRESET, rio8(SIE_TX_BUSRESET) & 0x02);
+			else
+				wio8(SIE_TX_BUSRESET, rio8(SIE_TX_BUSRESET) & 0x01);
+			p->state = PORT_STATE_RESET_WAIT;
+			p->unreset_frame =
+			    (frame_nr + RESET_RECOVERY_MS) & 0x7ff;
+			break;
+		case PORT_STATE_RESET_WAIT:
+			if(frame_nr != p->unreset_frame)
+				break;
+			p->state = PORT_STATE_SET_ADDRESS;
+			p->retry_count = 0;
 			break;
 		case PORT_STATE_SET_ADDRESS: {
 			struct setup_packet packet;
-- 
1.7.0.4



More information about the Devel mailing list