Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 3 commits
  • 1 file changed
  • 0 commit comments
  • 2 contributors
Commits on Nov 15, 2011
@wpwrak wpwrak softusb: remove compiler warning about unused variable 0decd11
@wpwrak wpwrak softusb: implement the reset recovery interval
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.
6c4bb3f
@sbourdeauducq sbourdeauducq USB: send SOFs and keepalives on both ports and immediately after reset f6c7474
Showing with 75 additions and 21 deletions.
  1. +75 −21 softusb-input/main.c
View
96 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,12 +449,6 @@ 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)) {
- /* send SOF */
- unsigned char usb_buffer[3];
- make_usb_token(USB_PID_SOF, frame_nr, usb_buffer);
- usb_tx(usb_buffer, 3);
- }
switch(p->state) {
case PORT_STATE_DISCONNECTED: {
char linestat;
@@ -478,14 +475,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;
@@ -609,10 +613,54 @@ static void port_service(struct port_status *p, char name)
static const char banner[] PROGMEM = "softusb-input v"VERSION"\n";
+static void sof()
+{
+ unsigned char mask;
+ unsigned char usb_buffer[3];
+
+ mask = 0;
+ if(port_a.full_speed && (port_a.state > PORT_STATE_BUS_RESET))
+ mask |= 0x01;
+ if(port_b.full_speed && (port_b.state > PORT_STATE_BUS_RESET))
+ mask |= 0x02;
+ if(mask != 0) {
+ wio8(SIE_TX_LOW_SPEED, 0);
+ wio8(SIE_SEL_TX, mask);
+ make_usb_token(USB_PID_SOF, frame_nr, usb_buffer);
+ usb_tx(usb_buffer, 3);
+ }
+}
+
+static void keepalive()
+{
+ unsigned char mask;
+
+ mask = 0;
+ if(!port_a.full_speed && (port_a.state == PORT_STATE_RESET_WAIT))
+ mask |= 0x01;
+ if(!port_b.full_speed && (port_b.state == PORT_STATE_RESET_WAIT))
+ mask |= 0x02;
+ if(mask != 0) {
+ wio8(SIE_TX_LOW_SPEED, 1);
+ wio8(SIE_SEL_TX, mask);
+ wio8(SIE_GENERATE_EOP, 1);
+ while(rio8(SIE_TX_BUSY));
+ }
+}
+
+static void set_rx_speed()
+{
+ unsigned char mask;
+
+ mask = 0;
+ if(!port_a.full_speed) mask |= 0x01;
+ if(!port_b.full_speed) mask |= 0x02;
+ wio8(SIE_LOW_SPEED, mask);
+}
+
int main()
{
unsigned char i;
- unsigned char mask;
print_string(banner);
@@ -622,14 +670,17 @@ int main()
while((rio8(TIMER1) < 0xbb) || (rio8(TIMER0) < 0x70));
wio8(TIMER0, 0);
+ sof();
+ keepalive();
+
/*
- * set RX speed bits
+ * wait extra time to allow the USB cable
+ * capacitance to discharge (otherwise some disconnects
+ * aren't properly detected)
*/
- mask = 0;
- if(!port_a.full_speed) mask |= 0x01;
- if(!port_b.full_speed) mask |= 0x02;
- wio8(SIE_LOW_SPEED, mask);
-
+ for(i=0;i<128;i++)
+ asm("nop");
+
wio8(SIE_SEL_RX, 0);
wio8(SIE_SEL_TX, 0x01);
port_service(&port_a, 'A');
@@ -637,6 +688,9 @@ int main()
wio8(SIE_SEL_RX, 1);
wio8(SIE_SEL_TX, 0x02);
port_service(&port_b, 'B');
+
+ /* set RX speed for new detected devices */
+ set_rx_speed();
frame_nr = (frame_nr + 1) & 0x7ff;
}

No commit comments for this range

Something went wrong with that request. Please try again.