From d2e77702cb5dd62760e99aa66141abfcb2c54e80 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 12 Aug 2007 12:04:41 +0000 Subject: [PATCH] Change the way notify hooks and rescans are handeled. The rescans are now delayed to after all notify hooks are called (like in BeOS). This also ensures that the rescans do not happen while the devices are not yet added or already removed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21905 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/bus_managers/usb/Hub.cpp | 16 ++++-- src/add-ons/kernel/bus_managers/usb/Pipe.cpp | 3 +- src/add-ons/kernel/bus_managers/usb/Stack.cpp | 56 +++++++++++++------ src/add-ons/kernel/bus_managers/usb/usb_p.h | 8 +++ 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 415a02acca..6d47058922 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -106,8 +106,10 @@ Hub::~Hub() continue; TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i])); - GetStack()->NotifyDeviceChange(fChildren[i], false); + rescan_item *rescanList = NULL; + GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, false); GetBusManager()->FreeDevice(fChildren[i]); + GetStack()->RescanDrivers(rescanList); } delete fInterruptPipe; @@ -207,6 +209,7 @@ Hub::Explore() USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, i + 1, 0, NULL, 0, NULL); + rescan_item *rescanList = NULL; if (fPortStatus[i].status & PORT_STATUS_CONNECTION) { // new device attached! TRACE(("USB Hub %d: new device connected\n", DeviceAddress())); @@ -234,13 +237,15 @@ Hub::Explore() // Remove previous device first TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i])); - GetStack()->NotifyDeviceChange(fChildren[i], false); + GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, false); if (Lock()) { GetBusManager()->FreeDevice(fChildren[i]); fChildren[i] = NULL; Unlock(); } + + GetStack()->RescanDrivers(rescanList); } usb_speed speed = USB_SPEED_FULLSPEED; @@ -254,7 +259,8 @@ Hub::Explore() if (newDevice && Lock()) { fChildren[i] = newDevice; Unlock(); - GetStack()->NotifyDeviceChange(fChildren[i], true); + GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, true); + GetStack()->RescanDrivers(rescanList); } else { if (newDevice) GetBusManager()->FreeDevice(newDevice); @@ -271,13 +277,15 @@ Hub::Explore() TRACE(("USB Hub %d: device removed\n", DeviceAddress())); if (fChildren[i]) { TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i])); - GetStack()->NotifyDeviceChange(fChildren[i], false); + GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, false); if (Lock()) { GetBusManager()->FreeDevice(fChildren[i]); fChildren[i] = NULL; Unlock(); } + + GetStack()->RescanDrivers(rescanList); } } } diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index 1f7471dfff..37a24518e2 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -26,6 +26,7 @@ Pipe::Pipe(Object *parent, int8 deviceAddress, uint8 endpointAddress, Pipe::~Pipe() { + CancelQueuedTransfers(); GetBusManager()->NotifyPipeChange(this, USB_CHANGE_DESTROYED); } @@ -308,7 +309,7 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value, if (actualLength) *actualLength = 0; - // ToDo: cancel the transfer at the bus manager + CancelQueuedTransfers(); return B_TIMED_OUT; } diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index 3660e6caeb..5e36f7a9cc 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -42,6 +42,7 @@ Stack::Stack() if (!fAllocator || fAllocator->InitCheck() < B_OK) { TRACE_ERROR(("USB Stack: failed to allocate the allocator\n")); delete fAllocator; + fAllocator = NULL; return; } @@ -268,7 +269,7 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size, void -Stack::NotifyDeviceChange(Device *device, bool added) +Stack::NotifyDeviceChange(Device *device, rescan_item **rescanList, bool added) { TRACE(("USB Stack: device %s\n", added ? "added" : "removed")); @@ -279,24 +280,16 @@ Stack::NotifyDeviceChange(Device *device, bool added) &element->cookies, added); if (result >= B_OK) { - // the device is supported by this driver. it either got notified - // already by the hooks or it is not loaded at this time. in any - // case we will rescan the driver so it either is loaded and can - // scan for supported devices or its publish_devices hook will be - // called to expose new devices. - const char *name = element->driver_name; - if (element->republish_driver_name) - name = element->republish_driver_name; + rescan_item *item = new(std::nothrow) rescan_item; + if (!item) + return; -#ifndef HAIKU_TARGET_PLATFORM_HAIKU - // the R5 way to republish a device in devfs - int devFS = open("/dev", O_WRONLY); - write(devFS, name, strlen(name)); - close(devFS); -#else - // use the private devfs API under Haiku - //devfs_rescan_driver(name); -#endif + item->name = element->driver_name; + if (element->republish_driver_name) + item->name = element->republish_driver_name; + + item->link = *rescanList; + *rescanList = item; } element = element->link; @@ -304,6 +297,33 @@ Stack::NotifyDeviceChange(Device *device, bool added) } +void +Stack::RescanDrivers(rescan_item *rescanItem) +{ + while (rescanItem) { + // the device is supported by this driver. it either got notified + // already by the hooks or it is not loaded at this time. in any + // case we will rescan the driver so it either is loaded and can + // scan for supported devices or its publish_devices hook will be + // called to expose changed devices. + +#ifndef HAIKU_TARGET_PLATFORM_HAIKU + // the R5 way to republish a device in devfs + int devFS = open("/dev", O_WRONLY); + write(devFS, rescanItem->name, strlen(rescanItem->name)); + close(devFS); +#else + // use the private devfs API under Haiku + //devfs_rescan_driver(name); +#endif + + rescan_item *next = rescanItem->link; + delete rescanItem; + rescanItem = next; + } +} + + status_t Stack::RegisterDriver(const char *driverName, const usb_support_descriptor *descriptors, 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 d6806f6494..a11ed9912a 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -60,6 +60,12 @@ struct usb_driver_info { }; +struct rescan_item { + const char *name; + rescan_item *link; +}; + + typedef enum { USB_SPEED_LOWSPEED = 0, USB_SPEED_FULLSPEED, @@ -113,7 +119,9 @@ public: size_t size, const char *name); void NotifyDeviceChange(Device *device, + rescan_item **rescanList, bool added); + void RescanDrivers(rescan_item *rescanItem); // USB API status_t RegisterDriver(const char *driverName,