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:
@@ -106,8 +106,10 @@ Hub::~Hub()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i]));
|
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]);
|
GetBusManager()->FreeDevice(fChildren[i]);
|
||||||
|
GetStack()->RescanDrivers(rescanList);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete fInterruptPipe;
|
delete fInterruptPipe;
|
||||||
@@ -207,6 +209,7 @@ Hub::Explore()
|
|||||||
USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, i + 1,
|
USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, i + 1,
|
||||||
0, NULL, 0, NULL);
|
0, NULL, 0, NULL);
|
||||||
|
|
||||||
|
rescan_item *rescanList = NULL;
|
||||||
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
|
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
|
||||||
// new device attached!
|
// new device attached!
|
||||||
TRACE(("USB Hub %d: new device connected\n", DeviceAddress()));
|
TRACE(("USB Hub %d: new device connected\n", DeviceAddress()));
|
||||||
@@ -234,13 +237,15 @@ Hub::Explore()
|
|||||||
|
|
||||||
// Remove previous device first
|
// Remove previous device first
|
||||||
TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), 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()) {
|
if (Lock()) {
|
||||||
GetBusManager()->FreeDevice(fChildren[i]);
|
GetBusManager()->FreeDevice(fChildren[i]);
|
||||||
fChildren[i] = NULL;
|
fChildren[i] = NULL;
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetStack()->RescanDrivers(rescanList);
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_speed speed = USB_SPEED_FULLSPEED;
|
usb_speed speed = USB_SPEED_FULLSPEED;
|
||||||
@@ -254,7 +259,8 @@ Hub::Explore()
|
|||||||
if (newDevice && Lock()) {
|
if (newDevice && Lock()) {
|
||||||
fChildren[i] = newDevice;
|
fChildren[i] = newDevice;
|
||||||
Unlock();
|
Unlock();
|
||||||
GetStack()->NotifyDeviceChange(fChildren[i], true);
|
GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, true);
|
||||||
|
GetStack()->RescanDrivers(rescanList);
|
||||||
} else {
|
} else {
|
||||||
if (newDevice)
|
if (newDevice)
|
||||||
GetBusManager()->FreeDevice(newDevice);
|
GetBusManager()->FreeDevice(newDevice);
|
||||||
@@ -271,13 +277,15 @@ Hub::Explore()
|
|||||||
TRACE(("USB Hub %d: device removed\n", DeviceAddress()));
|
TRACE(("USB Hub %d: device removed\n", DeviceAddress()));
|
||||||
if (fChildren[i]) {
|
if (fChildren[i]) {
|
||||||
TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), 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()) {
|
if (Lock()) {
|
||||||
GetBusManager()->FreeDevice(fChildren[i]);
|
GetBusManager()->FreeDevice(fChildren[i]);
|
||||||
fChildren[i] = NULL;
|
fChildren[i] = NULL;
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetStack()->RescanDrivers(rescanList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ Pipe::Pipe(Object *parent, int8 deviceAddress, uint8 endpointAddress,
|
|||||||
|
|
||||||
Pipe::~Pipe()
|
Pipe::~Pipe()
|
||||||
{
|
{
|
||||||
|
CancelQueuedTransfers();
|
||||||
GetBusManager()->NotifyPipeChange(this, USB_CHANGE_DESTROYED);
|
GetBusManager()->NotifyPipeChange(this, USB_CHANGE_DESTROYED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +309,7 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value,
|
|||||||
if (actualLength)
|
if (actualLength)
|
||||||
*actualLength = 0;
|
*actualLength = 0;
|
||||||
|
|
||||||
// ToDo: cancel the transfer at the bus manager
|
CancelQueuedTransfers();
|
||||||
return B_TIMED_OUT;
|
return B_TIMED_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ Stack::Stack()
|
|||||||
if (!fAllocator || fAllocator->InitCheck() < B_OK) {
|
if (!fAllocator || fAllocator->InitCheck() < B_OK) {
|
||||||
TRACE_ERROR(("USB Stack: failed to allocate the allocator\n"));
|
TRACE_ERROR(("USB Stack: failed to allocate the allocator\n"));
|
||||||
delete fAllocator;
|
delete fAllocator;
|
||||||
|
fAllocator = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +269,7 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size,
|
|||||||
|
|
||||||
|
|
||||||
void
|
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"));
|
TRACE(("USB Stack: device %s\n", added ? "added" : "removed"));
|
||||||
|
|
||||||
@@ -279,27 +280,46 @@ Stack::NotifyDeviceChange(Device *device, bool added)
|
|||||||
&element->cookies, added);
|
&element->cookies, added);
|
||||||
|
|
||||||
if (result >= B_OK) {
|
if (result >= B_OK) {
|
||||||
|
rescan_item *item = new(std::nothrow) rescan_item;
|
||||||
|
if (!item)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item->name = element->driver_name;
|
||||||
|
if (element->republish_driver_name)
|
||||||
|
item->name = element->republish_driver_name;
|
||||||
|
|
||||||
|
item->link = *rescanList;
|
||||||
|
*rescanList = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
element = element->link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Stack::RescanDrivers(rescan_item *rescanItem)
|
||||||
|
{
|
||||||
|
while (rescanItem) {
|
||||||
// the device is supported by this driver. it either got notified
|
// 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
|
// 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
|
// case we will rescan the driver so it either is loaded and can
|
||||||
// scan for supported devices or its publish_devices hook will be
|
// scan for supported devices or its publish_devices hook will be
|
||||||
// called to expose new devices.
|
// called to expose changed devices.
|
||||||
const char *name = element->driver_name;
|
|
||||||
if (element->republish_driver_name)
|
|
||||||
name = element->republish_driver_name;
|
|
||||||
|
|
||||||
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
|
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
// the R5 way to republish a device in devfs
|
// the R5 way to republish a device in devfs
|
||||||
int devFS = open("/dev", O_WRONLY);
|
int devFS = open("/dev", O_WRONLY);
|
||||||
write(devFS, name, strlen(name));
|
write(devFS, rescanItem->name, strlen(rescanItem->name));
|
||||||
close(devFS);
|
close(devFS);
|
||||||
#else
|
#else
|
||||||
// use the private devfs API under Haiku
|
// use the private devfs API under Haiku
|
||||||
//devfs_rescan_driver(name);
|
//devfs_rescan_driver(name);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
element = element->link;
|
rescan_item *next = rescanItem->link;
|
||||||
|
delete rescanItem;
|
||||||
|
rescanItem = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,12 @@ struct usb_driver_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct rescan_item {
|
||||||
|
const char *name;
|
||||||
|
rescan_item *link;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
USB_SPEED_LOWSPEED = 0,
|
USB_SPEED_LOWSPEED = 0,
|
||||||
USB_SPEED_FULLSPEED,
|
USB_SPEED_FULLSPEED,
|
||||||
@@ -113,7 +119,9 @@ public:
|
|||||||
size_t size, const char *name);
|
size_t size, const char *name);
|
||||||
|
|
||||||
void NotifyDeviceChange(Device *device,
|
void NotifyDeviceChange(Device *device,
|
||||||
|
rescan_item **rescanList,
|
||||||
bool added);
|
bool added);
|
||||||
|
void RescanDrivers(rescan_item *rescanItem);
|
||||||
|
|
||||||
// USB API
|
// USB API
|
||||||
status_t RegisterDriver(const char *driverName,
|
status_t RegisterDriver(const char *driverName,
|
||||||
|
|||||||
Reference in New Issue
Block a user