If device allocation fails, retry the attach process, i.e. reset and initialize

the device again. Makes Axel's USB stick work and might also help with other
(broken) devices.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36234 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2010-04-13 18:26:26 +00:00
parent a1b2e9e959
commit 696914f907

View File

@ -218,60 +218,65 @@ Hub::Explore(change_item **changeList)
// new device attached! // new device attached!
TRACE_ALWAYS("port %ld: new device connected\n", i); TRACE_ALWAYS("port %ld: new device connected\n", i);
// wait some time for the device to power up int32 retry = 2;
snooze(USB_DELAY_DEVICE_POWER_UP); while (retry--) {
// wait some time for the device to power up
snooze(USB_DELAY_DEVICE_POWER_UP);
// reset the port, this will also enable it // reset the port, this will also enable it
result = ResetPort(i); result = ResetPort(i);
if (result < B_OK) { if (result < B_OK) {
TRACE_ERROR("resetting port %ld failed\n", i); TRACE_ERROR("resetting port %ld failed\n", i);
continue; break;
} }
result = UpdatePortStatus(i); result = UpdatePortStatus(i);
if (result < B_OK) if (result < B_OK)
continue; break;
if ((fPortStatus[i].status & PORT_STATUS_CONNECTION) == 0) { if ((fPortStatus[i].status & PORT_STATUS_CONNECTION) == 0) {
// device has vanished after reset, ignore // device has vanished after reset, ignore
TRACE("device disappeared on reset\n"); TRACE("device disappeared on reset\n");
continue; break;
} }
if (fChildren[i] != NULL) { if (fChildren[i] != NULL) {
TRACE_ERROR("new device on a port that is already in use\n"); TRACE_ERROR("new device on a port that is already in "
fChildren[i]->Changed(changeList, false); "use\n");
fChildren[i] = NULL; fChildren[i]->Changed(changeList, false);
} fChildren[i] = NULL;
}
usb_speed speed = USB_SPEED_FULLSPEED; usb_speed speed = USB_SPEED_FULLSPEED;
if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED) if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED)
speed = USB_SPEED_LOWSPEED; speed = USB_SPEED_LOWSPEED;
if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED) if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED)
speed = USB_SPEED_HIGHSPEED; speed = USB_SPEED_HIGHSPEED;
// either let the device inherit our addresses (if we are // either let the device inherit our addresses (if we are
// already potentially using a transaction translator) or set // already potentially using a transaction translator) or
// ourselfs as the hub when we might become the transaction // set ourselfs as the hub when we might become the
// translator for the device. // transaction translator for the device.
int8 hubAddress = HubAddress(); int8 hubAddress = HubAddress();
uint8 hubPort = HubPort(); uint8 hubPort = HubPort();
if (Speed() == USB_SPEED_HIGHSPEED) { if (Speed() == USB_SPEED_HIGHSPEED) {
hubAddress = DeviceAddress(); hubAddress = DeviceAddress();
hubPort = i + 1; hubPort = i + 1;
} }
Device *newDevice = GetBusManager()->AllocateDevice(this, Device *newDevice = GetBusManager()->AllocateDevice(this,
hubAddress, hubPort, speed); hubAddress, hubPort, speed);
if (newDevice) { if (newDevice) {
newDevice->Changed(changeList, true); newDevice->Changed(changeList, true);
fChildren[i] = newDevice; fChildren[i] = newDevice;
} else { break;
// the device failed to setup correctly, disable the port } else {
// so that the device doesn't get in the way of future // the device failed to setup correctly, disable the
// addressing. // port so that the device doesn't get in the way of
DisablePort(i); // future addressing.
DisablePort(i);
}
} }
} else { } else {
// Device removed... // Device removed...