Greg:
This patch changes the mechanism used for detecting devices that were
already connected to a hub at the time the hub was activated. This can
occur in several different circumstances:
when the hub is configured for the first time,
when the hub is reset following a malfunction,
when the hub is resumed.
The patch mainly addresses the third possibility, although it also handles
the other two. The scenario I have in mind is waking up from a system
suspend, where the user has plugged in a new USB device while the system
was asleep, and for some reason the hub no longer has a record of the
connect change on that port. (Maybe the BIOS or the boot kernel has
interfered.) At any rate, the patch causes the hub driver to scan all
ports in the reactivated hub, and if it finds a connected port with no
child device already allocated then it pretends there was a connect-change
event on that port.
This will serve to take care of ports with new devices attached that the
driver doesn't know about. The existing resume code already handles the
case of ports that used to have a device but don't any longer. The
remaining case, where different devices are attached to the port before
suspending and after resuming, still needs to be handled. The resume code
should call the same "descriptors changed" check used by usb_reset_device.
That's a patch for another day.
Alan Stern
Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
===== drivers/usb/core/hub.c 1.229 vs edited =====
--- 1.229/drivers/usb/core/hub.c 2005-01-14 11:28:39 -05:00
+++ edited/drivers/usb/core/hub.c 2005-01-26 11:51:23 -05:00
@@ -459,6 +459,7 @@
int status;
hub->quiescing = 0;
+ hub->activating = 1;
status = usb_submit_urb(hub->urb, GFP_NOIO);
if (status < 0)
dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -466,7 +467,6 @@
schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
/* scan all ports ASAP */
- hub->event_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 1;
kick_khubd(hub);
}
@@ -689,7 +689,6 @@
hub->indicator [0] = INDICATOR_CYCLE;
hub_power_on(hub);
- hub->change_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 2;
hub_activate(hub);
return 0;
@@ -2635,7 +2634,7 @@
for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
connect_change = test_bit(i, hub->change_bits);
if (!test_and_clear_bit(i, hub->event_bits) &&
- !connect_change)
+ !connect_change && !hub->activating)
continue;
ret = hub_port_status(hub, i,
@@ -2643,6 +2642,11 @@
if (ret < 0)
continue;
+ if (hub->activating && !hdev->children[i-1] &&
+ (portstatus &
+ USB_PORT_STAT_CONNECTION))
+ connect_change = 1;
+
if (portchange & USB_PORT_STAT_C_CONNECTION) {
clear_port_feature(hdev, i,
USB_PORT_FEAT_C_CONNECTION);
@@ -2732,6 +2736,8 @@
hub_power_on(hub);
}
}
+
+ hub->activating = 0;
loop:
usb_unlock_device(hdev);
===== drivers/usb/core/hub.h 1.43 vs edited =====
--- 1.43/drivers/usb/core/hub.h 2005-01-11 12:14:56 -05:00
+++ edited/drivers/usb/core/hub.h 2005-01-26 11:50:09 -05:00
@@ -215,6 +215,7 @@
u8 power_budget; /* in 2mA units; or zero */
unsigned quiescing:1;
+ unsigned activating:1;
unsigned has_indicators:1;
enum hub_led_mode indicator[USB_MAXCHILDREN];
-------------------------------------------------------
This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting
Tool for open source databases. Create drag-&-drop reports. Save time
by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc.
Download a FREE copy at http://www.intelliview.com/go/osdn_nl
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel