Implement debounce sequence according to USB 2.0 specs.

This replaces waiting a fixed time of 300ms for the device power to
stabilize. In the ideal case this reduces the boot time by 200ms per
connected device (including internal hubs).

This is very similar to what Linux implements and we use the same time
values. An interval of 25ms is used to check for connection state
changes, the stable time is at least 100ms as per the USB specs and the
whole process times out after 1.5 seconds.
This commit is contained in:
Michael Lotz 2013-04-28 03:19:20 +02:00
parent e94d7e41e8
commit 827c7224a0
3 changed files with 48 additions and 3 deletions

View File

@ -221,8 +221,13 @@ Hub::Explore(change_item **changeList)
int32 retry = 2; int32 retry = 2;
while (retry--) { while (retry--) {
// wait some time for the device to power up // wait for stable device power
snooze(USB_DELAY_DEVICE_POWER_UP); result = _DebouncePort(i);
if (result != B_OK) {
TRACE_ERROR("debouncing port %" B_PRId32
" failed: %s\n", i, strerror(result));
break;
}
// reset the port, this will also enable it // reset the port, this will also enable it
result = ResetPort(i); result = ResetPort(i);
@ -433,3 +438,38 @@ Hub::BuildDeviceName(char *string, uint32 *index, size_t bufferSize,
return B_OK; return B_OK;
} }
status_t
Hub::_DebouncePort(uint8 index)
{
uint32 timeout = 0;
uint32 stableTime = 0;
while (timeout < USB_DEBOUNCE_TIMEOUT) {
snooze(USB_DEBOUNCE_CHECK_INTERVAL);
timeout += USB_DEBOUNCE_CHECK_INTERVAL;
status_t result = UpdatePortStatus(index);
if (result != B_OK)
return result;
if ((fPortStatus[index].change & PORT_STATUS_CONNECTION) == 0) {
stableTime += USB_DEBOUNCE_CHECK_INTERVAL;
if (stableTime >= USB_DEBOUNCE_STABLE_TIME)
return B_OK;
continue;
}
// clear the connection change and reset stable time
result = DefaultPipe()->SendRequest(USB_REQTYPE_CLASS
| USB_REQTYPE_OTHER_OUT, USB_REQUEST_CLEAR_FEATURE,
C_PORT_CONNECTION, index + 1, 0, NULL, 0, NULL);
if (result != B_OK)
return result;
TRACE("got connection change during debounce, resetting stable time\n");
stableTime = 0;
}
return B_TIMED_OUT;
}

View File

@ -610,6 +610,8 @@ virtual status_t BuildDeviceName(char *string,
Device *device); Device *device);
private: private:
status_t _DebouncePort(uint8 index);
InterruptPipe * fInterruptPipe; InterruptPipe * fInterruptPipe;
usb_hub_descriptor fHubDescriptor; usb_hub_descriptor fHubDescriptor;

View File

@ -19,7 +19,6 @@
#define USB_MAX_PORT_COUNT 16 #define USB_MAX_PORT_COUNT 16
#define USB_DELAY_BUS_RESET 100000 #define USB_DELAY_BUS_RESET 100000
#define USB_DELAY_DEVICE_POWER_UP 300000
#define USB_DELAY_HUB_POWER_UP 200000 #define USB_DELAY_HUB_POWER_UP 200000
#define USB_DELAY_PORT_RESET 50000 #define USB_DELAY_PORT_RESET 50000
#define USB_DELAY_PORT_RESET_RECOVERY 250000 #define USB_DELAY_PORT_RESET_RECOVERY 250000
@ -28,6 +27,10 @@
#define USB_DELAY_SET_CONFIGURATION 50000 #define USB_DELAY_SET_CONFIGURATION 50000
#define USB_DELAY_HUB_EXPLORE 1000000 #define USB_DELAY_HUB_EXPLORE 1000000
#define USB_DEBOUNCE_TIMEOUT 1500000
#define USB_DEBOUNCE_CHECK_INTERVAL 25000
#define USB_DEBOUNCE_STABLE_TIME 100000
// For bandwidth calculation // For bandwidth calculation
#define USB_BW_HOST_DELAY 1000 #define USB_BW_HOST_DELAY 1000
#define USB_BW_SETUP_LOW_SPEED_PORT_DELAY 333 #define USB_BW_SETUP_LOW_SPEED_PORT_DELAY 333