On Wed, Feb 20, 2002 at 04:48:01PM -0800, Greg KH wrote:
>
> [EMAIL PROTECTED], 2002-02-20 15:54:14-08:00, [EMAIL PROTECTED]
> usb hub:
> - fix problem with us not delaying for any ammount of time after a new device
> has been powered up, as the USB spec indicates should happen.
>
> drivers/usb/hub.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 50 insertions(+), 3 deletions(-)
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.377 -> 1.378
# drivers/usb/hub.c 1.17 -> 1.18
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/02/20 [EMAIL PROTECTED] 1.378
# usb hub:
# - fix problem with us not delaying for any ammount of time after a new device
# has been powered up, as the USB spec indicates should happen.
# --------------------------------------------
#
diff -Nru a/drivers/usb/hub.c b/drivers/usb/hub.c
--- a/drivers/usb/hub.c Wed Feb 20 16:55:28 2002
+++ b/drivers/usb/hub.c Wed Feb 20 16:55:28 2002
@@ -644,6 +644,49 @@
port + 1, hub->devpath, ret);
}
+/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
+ *
+ * Between connect detection and reset signaling there must be a delay
+ * of 100ms at least for debounce and power-settling. The corresponding
+ * timer shall restart whenever the downstream port detects a disconnect.
+ *
+ * Apparently there are some bluetooth and irda-dongles and a number
+ * of low-speed devices which require longer delays of about 200-400ms.
+ * Not covered by the spec - but easy to deal with.
+ *
+ * This implementation uses 400ms minimum debounce timeout and checks
+ * every 10ms for transient disconnects to restart the delay.
+ */
+
+#define HUB_DEBOUNCE_TIMEOUT 400
+#define HUB_DEBOUNCE_STEP 10
+
+/* return: -1 on error, 0 on success, 1 on disconnect. */
+static int usb_hub_port_debounce(struct usb_device *hub, int port)
+{
+ int ret;
+ unsigned delay_time;
+ u16 portchange, portstatus;
+
+ for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; /* empty */ ) {
+
+ /* wait debounce step increment */
+ wait_ms(HUB_DEBOUNCE_STEP);
+
+ ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
+ if (ret < 0)
+ return -1;
+
+ if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
+ usb_clear_port_feature(hub, port+1,
+USB_PORT_FEAT_C_CONNECTION);
+ delay_time = 0;
+ }
+ else
+ delay_time += HUB_DEBOUNCE_STEP;
+ }
+ return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
+}
+
static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
u16 portstatus, u16 portchange)
{
@@ -671,12 +714,16 @@
return;
}
+ if (usb_hub_port_debounce(hub, port)) {
+ err("connect-debounce failed, port %d disabled", port+1);
+ usb_hub_port_disable(hub, port);
+ return;
+ }
+
/* Some low speed devices have problems with the quick delay, so */
/* be a bit pessimistic with those devices. RHbug #23670 */
- if (portstatus & USB_PORT_STAT_LOW_SPEED) {
- wait_ms(400);
+ if (portstatus & USB_PORT_STAT_LOW_SPEED)
delay = HUB_LONG_RESET_TIME;
- }
down(&usb_address0_sem);
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel