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
This commit is contained in:
Michael Lotz
2007-08-12 12:04:41 +00:00
parent 154860eb4b
commit d2e77702cb
4 changed files with 60 additions and 23 deletions
+12 -4
View File
@@ -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);
}
}
}
+2 -1
View File
@@ -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;
}
+38 -18
View File
@@ -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,
@@ -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,