diff --git a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp index 19dab22d72..72a73dae70 100644 --- a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp +++ b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp @@ -12,8 +12,7 @@ BusManager::BusManager(Stack *stack) : fInitOK(false), - fRootHub(NULL), - fExploreThread(-1) + fRootHub(NULL) { if (benaphore_init(&fLock, "usb busmanager lock") < B_OK) { TRACE_ERROR(("usb BusManager: failed to create busmanager lock\n")); @@ -73,27 +72,6 @@ BusManager::Unlock() } -/* - This is the 'main' function of the explore thread, which keeps track of - the hub states. -*/ -int32 -BusManager::ExploreThread(void *data) -{ - Hub *rootHub = (Hub *)data; - if (!rootHub) - return B_ERROR; - - snooze(USB_DELAY_FIRST_EXPLORE); - while (true) { - rootHub->Explore(); - snooze(USB_DELAY_HUB_EXPLORE); - } - - return B_OK; -} - - int8 BusManager::AllocateAddress() { @@ -229,23 +207,13 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed) status_t BusManager::Start() { - TRACE(("usb BusManager::Start()\n")); - if (InitCheck() != B_OK) - return InitCheck(); - - if (fExploreThread < 0) { - fExploreThread = spawn_kernel_thread(ExploreThread, - "usb busmanager explore", B_LOW_PRIORITY, (void *)fRootHub); - } - - return resume_thread(fExploreThread); + return B_OK; } status_t BusManager::Stop() { - // ToDo: implement (should end the explore thread) return B_OK; } diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index 168ad5f638..7ad76fbf4a 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -15,7 +15,10 @@ Stack::Stack() - : fObjectIndex(1), + : fExploreThread(-1), + fFirstExploreDone(false), + fStopThreads(false), + fObjectIndex(1), fObjectMaxCount(1024), fObjectArray(NULL), fDriverList(NULL) @@ -58,13 +61,33 @@ Stack::Stack() TRACE(("usb stack: module %s successfully loaded\n", moduleName)); } - if (fBusManagers.Count() == 0) + if (fBusManagers.Count() == 0) { + TRACE_ERROR(("usb stack: no bus managers available\n")); return; + } + + if (benaphore_init(&fExploreLock, "usb explore lock") < B_OK) { + TRACE_ERROR(("usb stack: failed to create benaphore explore lock\n")); + return; + } + + 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); } Stack::~Stack() { + int32 result; + fStopThreads = true; + wait_for_thread(fExploreThread, &result); + Lock(); benaphore_destroy(&fLock); @@ -157,6 +180,30 @@ Stack::GetObject(usb_id id) } +int32 +Stack::ExploreThread(void *data) +{ + Stack *stack = (Stack *)data; + + while (!stack->fStopThreads) { + if (benaphore_lock(&stack->fExploreLock) != B_OK) + continue; + + for (int32 i = 0; i < stack->fBusManagers.Count(); i++) { + Hub *rootHub = stack->fBusManagers.ElementAt(i)->GetRootHub(); + if (rootHub) + rootHub->Explore(); + } + + stack->fFirstExploreDone = true; + benaphore_unlock(&stack->fExploreLock); + snooze(USB_DELAY_HUB_EXPLORE); + } + + return B_OK; +} + + void Stack::AddBusManager(BusManager *busManager) { @@ -300,13 +347,15 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks) usb_driver_info *element = fDriverList; while (element) { if (strcmp(element->driver_name, driverName) == 0) { + // ensure that no devices are added/removed while we are + // reporting devices + if (benaphore_lock(&fExploreLock) != B_OK) + return B_ERROR; + // inform driver about any already present devices for (int32 i = 0; i < fBusManagers.Count(); i++) { Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub(); if (rootHub) { - // Ensure that all devices are already recognized - rootHub->Explore(); - // Report device will recurse down the whole tree rootHub->ReportDevice(element->support_descriptors, element->support_descriptor_count, hooks, @@ -316,6 +365,7 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks) element->notify_hooks.device_added = hooks->device_added; element->notify_hooks.device_removed = hooks->device_removed; + benaphore_unlock(&fExploreLock); return B_OK; } @@ -330,12 +380,15 @@ status_t Stack::UninstallNotify(const char *driverName) { TRACE(("usb stack: uninstalling notify hooks for driver \"%s\"\n", driverName)); - if (!Lock()) - return B_ERROR; usb_driver_info *element = fDriverList; while (element) { if (strcmp(element->driver_name, driverName) == 0) { + // ensure that no devices are added/removed while we are + // reporting devices + if (benaphore_lock(&fExploreLock) != B_OK) + return B_ERROR; + // trigger the device removed hook for (int32 i = 0; i < fBusManagers.Count(); i++) { Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub(); @@ -347,13 +400,12 @@ Stack::UninstallNotify(const char *driverName) element->notify_hooks.device_added = NULL; element->notify_hooks.device_removed = NULL; - Unlock(); + benaphore_unlock(&fExploreLock); return B_OK; } element = element->link; } - Unlock(); return B_NAME_NOT_FOUND; } diff --git a/src/add-ons/kernel/bus_managers/usb/usb_p.h b/src/add-ons/kernel/bus_managers/usb/usb_p.h index 71d1f4d9d4..448ab1f9f9 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -127,9 +127,15 @@ public: status_t UninstallNotify(const char *driverName); private: +static int32 ExploreThread(void *data); + Vector fBusManagers; + thread_id fExploreThread; + bool fFirstExploreDone; + bool fStopThreads; benaphore fLock; + benaphore fExploreLock; PhysicalMemoryAllocator *fAllocator; uint32 fObjectIndex; @@ -176,13 +182,10 @@ protected: bool fInitOK; private: -static int32 ExploreThread(void *data); - benaphore fLock; bool fDeviceMap[128]; ControlPipe *fDefaultPipes[USB_SPEED_MAX + 1]; Hub *fRootHub; - thread_id fExploreThread; Object *fRootObject; };