diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index d7acaa1dba..415a02acca 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -13,10 +13,15 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed) - : Device(parent, desc, deviceAddress, speed) + : Device(parent, desc, deviceAddress, speed), + fInterruptPipe(NULL) { TRACE(("USB Hub %d: creating hub\n", DeviceAddress())); + memset(&fHubDescriptor, 0, sizeof(fHubDescriptor)); + for (int32 i = 0; i < 8; i++) + fChildren[i] = NULL; + if (!fInitOK) { TRACE_ERROR(("USB Hub %d: device failed to initialize\n", DeviceAddress())); return; @@ -30,9 +35,6 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, return; } - for (int32 i = 0; i < 8; i++) - fChildren[i] = NULL; - if (fDeviceDescriptor.device_class != 9) { TRACE_ERROR(("USB Hub %d: wrong class! bailing out\n", DeviceAddress())); return; @@ -58,6 +60,11 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, TRACE(("\tdevice_removeable:...0x%02x\n", fHubDescriptor.device_removeable)); TRACE(("\tpower_control_mask:..0x%02x\n", fHubDescriptor.power_control_mask)); + if (fHubDescriptor.num_ports > 8) { + TRACE(("USB Hub %d: hub supports more ports than we do (%d vs. 8)\n", DeviceAddress(), fHubDescriptor.num_ports)); + fHubDescriptor.num_ports = 8; + } + Object *object = GetStack()->GetObject(Configuration()->interface->active->endpoint[0].handle); if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) { TRACE_ERROR(("USB Hub %d: no interrupt pipe found\n", DeviceAddress())); @@ -183,12 +190,6 @@ void Hub::Explore() { for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { - if (i >= 8) { - TRACE(("USB Hub %d: hub supports more ports than we do (%d)\n", DeviceAddress(), fHubDescriptor.num_ports)); - fHubDescriptor.num_ports = 8; - continue; - } - status_t result = UpdatePortStatus(i); if (result < B_OK) continue; @@ -228,6 +229,20 @@ Hub::Explore() continue; } + if (fChildren[i]) { + TRACE_ERROR(("USB Hub %d: new device on a port that is already in use\n", DeviceAddress())); + + // Remove previous device first + TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i])); + GetStack()->NotifyDeviceChange(fChildren[i], false); + + if (Lock()) { + GetBusManager()->FreeDevice(fChildren[i]); + fChildren[i] = NULL; + Unlock(); + } + } + usb_speed speed = USB_SPEED_FULLSPEED; if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED) speed = USB_SPEED_LOWSPEED; diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index 2cd4cdbbbf..3660e6caeb 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -75,11 +75,6 @@ Stack::Stack() fExploreThread = spawn_kernel_thread(ExploreThread, "usb explore", B_LOW_PRIORITY, this); resume_thread(fExploreThread); - - // wait for the first explore to complete - // this ensures that we get all initial devices under InstallNotify - while (!fFirstExploreDone) - snooze(1000); } @@ -380,6 +375,11 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks) { TRACE(("USB Stack: installing notify hooks for driver \"%s\"\n", driverName)); + // wait for the first explore to complete + // this ensures that we get all initial devices + while (!fFirstExploreDone) + snooze(1000); + usb_driver_info *element = fDriverList; while (element) { if (strcmp(element->driver_name, driverName) == 0) {