* Revised locking of the USB stack classes

* Implemented the Hub destructor to properly free all of its child devices
* Added FreeDevice() and FreeAddress() to the BusManager class
* Added timeout to ControlPipe::SendRequest()
* Changed how the recursive device reporting works so that it respects the support descriptors of a driver
* Enabled driver rescanning for drivers that are not currently loaded but still registered (R5 only as the devfs function is yet missing from Haiku)
* Changed the way usb_ids are handed out so that free ones are reused instead of just running out of ids
* Fixed driver registration so that each driver is only added once (and devices are reported once per driver)
* Unified debug output and fixed some warnings with debug output turned on
* Fixed some style issues and removed stray whitespaces

Overall the USB stack should now be much more reliable. It should not crash on disconnects anymore and repluging of a device should be noticed by all drivers.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19860 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2007-01-18 22:25:02 +00:00
parent dff0f5c833
commit c4cce7277c
8 changed files with 337 additions and 203 deletions
@@ -15,7 +15,7 @@ BusManager::BusManager(Stack *stack)
fRootHub(NULL) fRootHub(NULL)
{ {
if (benaphore_init(&fLock, "usb busmanager lock") < B_OK) { if (benaphore_init(&fLock, "usb busmanager lock") < B_OK) {
TRACE_ERROR(("usb BusManager: failed to create busmanager lock\n")); TRACE_ERROR(("USB BusManager: failed to create busmanager lock\n"));
return; return;
} }
@@ -26,6 +26,7 @@ BusManager::BusManager(Stack *stack)
// Clear the device map // Clear the device map
for (int32 i = 0; i < 128; i++) for (int32 i = 0; i < 128; i++)
fDeviceMap[i] = false; fDeviceMap[i] = false;
fDeviceIndex = 0;
// Set the default pipes to NULL (these will be created when needed) // Set the default pipes to NULL (these will be created when needed)
for (int32 i = 0; i <= USB_SPEED_MAX; i++) for (int32 i = 0; i <= USB_SPEED_MAX; i++)
@@ -41,6 +42,7 @@ BusManager::~BusManager()
benaphore_destroy(&fLock); benaphore_destroy(&fLock);
for (int32 i = 0; i <= USB_SPEED_MAX; i++) for (int32 i = 0; i <= USB_SPEED_MAX; i++)
delete fDefaultPipes[i]; delete fDefaultPipes[i];
delete fRootObject;
} }
@@ -74,35 +76,60 @@ BusManager::AllocateAddress()
if (!Lock()) if (!Lock())
return -1; return -1;
int8 deviceAddress = -1; int8 tries = 127;
for (int32 i = 1; i < 128; i++) { int8 address = fDeviceIndex;
if (fDeviceMap[i] == false) { while (tries-- > 0) {
deviceAddress = i; if (fDeviceMap[address] == false) {
fDeviceMap[i] = true; fDeviceIndex = (address + 1) % 127;
break; fDeviceMap[address] = true;
Unlock();
return address + 1;
} }
address = (address + 1) % 127;
} }
TRACE_ERROR(("USB BusManager: the busmanager has run out of device addresses\n"));
Unlock();
return -1;
}
void
BusManager::FreeAddress(int8 address)
{
address--;
if (address < 0)
return;
if (!Lock())
return;
if (!fDeviceMap[address]) {
TRACE_ERROR(("USB BusManager: freeing address %d which was not allocated\n", address));
}
fDeviceMap[address] = false;
Unlock(); Unlock();
return deviceAddress;
} }
Device * Device *
BusManager::AllocateNewDevice(Hub *parent, usb_speed speed) BusManager::AllocateDevice(Hub *parent, usb_speed speed)
{ {
// Check if there is a free entry in the device map (for the device number) // Check if there is a free entry in the device map (for the device number)
int8 deviceAddress = AllocateAddress(); int8 deviceAddress = AllocateAddress();
if (deviceAddress < 0) { if (deviceAddress < 0) {
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): could not get a new address\n")); TRACE_ERROR(("USB BusManager: could not allocate an address\n"));
return NULL; return NULL;
} }
TRACE(("usb BusManager::AllocateNewDevice(): setting device address to %d\n", deviceAddress)); TRACE(("USB BusManager: setting device address to %d\n", deviceAddress));
ControlPipe *defaultPipe = _GetDefaultPipe(speed); ControlPipe *defaultPipe = _GetDefaultPipe(speed);
if (!defaultPipe) { if (!defaultPipe) {
TRACE(("usb BusManager::AllocateNewDevice(): Error getting the default pipe for speed %d\n", (int)speed)); TRACE(("USB BusManager: error getting the default pipe for speed %d\n", (int)speed));
FreeAddress(deviceAddress);
return NULL; return NULL;
} }
@@ -126,7 +153,8 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed)
} }
if (result < B_OK) { if (result < B_OK) {
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): error while setting device address\n")); TRACE_ERROR(("USB BusManager: error while setting device address\n"));
FreeAddress(deviceAddress);
return NULL; return NULL;
} }
@@ -143,7 +171,7 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed)
size_t actualLength = 0; size_t actualLength = 0;
usb_device_descriptor deviceDescriptor; usb_device_descriptor deviceDescriptor;
TRACE(("usb BusManager::AllocateNewDevice(): getting the device descriptor\n")); TRACE(("USB BusManager: getting the device descriptor\n"));
pipe.SendRequest( pipe.SendRequest(
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
USB_REQUEST_GET_DESCRIPTOR, // request USB_REQUEST_GET_DESCRIPTOR, // request
@@ -155,7 +183,8 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed)
&actualLength); // actual length &actualLength); // actual length
if (actualLength != 8) { if (actualLength != 8) {
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): error while getting the device descriptor\n")); TRACE_ERROR(("USB BusManager: error while getting the device descriptor\n"));
FreeAddress(deviceAddress);
return NULL; return NULL;
} }
@@ -170,16 +199,18 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed)
// Create a new instance based on the type (Hub or Device) // Create a new instance based on the type (Hub or Device)
if (deviceDescriptor.device_class == 0x09) { if (deviceDescriptor.device_class == 0x09) {
TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n")); TRACE(("USB BusManager: creating new hub\n"));
Hub *hub = new(std::nothrow) Hub(parent, deviceDescriptor, Hub *hub = new(std::nothrow) Hub(parent, deviceDescriptor,
deviceAddress, speed); deviceAddress, speed);
if (!hub) { if (!hub) {
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate hub\n")); TRACE_ERROR(("USB BusManager: no memory to allocate hub\n"));
FreeAddress(deviceAddress);
return NULL; return NULL;
} }
if (hub->InitCheck() < B_OK) { if (hub->InitCheck() < B_OK) {
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): hub failed init check\n")); TRACE_ERROR(("USB BusManager: hub failed init check\n"));
FreeAddress(deviceAddress);
delete hub; delete hub;
return NULL; return NULL;
} }
@@ -187,16 +218,18 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed)
return (Device *)hub; return (Device *)hub;
} }
TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n")); TRACE(("USB BusManager: creating new device\n"));
Device *device = new(std::nothrow) Device(parent, deviceDescriptor, Device *device = new(std::nothrow) Device(parent, deviceDescriptor,
deviceAddress, speed); deviceAddress, speed);
if (!device) { if (!device) {
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate device\n")); TRACE_ERROR(("USB BusManager: no memory to allocate device\n"));
FreeAddress(deviceAddress);
return NULL; return NULL;
} }
if (device->InitCheck() < B_OK) { if (device->InitCheck() < B_OK) {
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): device failed init check\n")); TRACE_ERROR(("USB BusManager: device failed init check\n"));
FreeAddress(deviceAddress);
delete device; delete device;
return NULL; return NULL;
} }
@@ -205,6 +238,14 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed)
} }
void
BusManager::FreeDevice(Device *device)
{
FreeAddress(device->DeviceAddress());
delete device;
}
status_t status_t
BusManager::Start() BusManager::Start()
{ {
@@ -234,24 +275,22 @@ BusManager::NotifyPipeChange(Pipe *pipe, usb_change change)
return B_ERROR; return B_ERROR;
} }
ControlPipe * ControlPipe *
BusManager::_GetDefaultPipe(usb_speed speed) BusManager::_GetDefaultPipe(usb_speed speed)
{ {
if (!Lock()) if (!Lock())
return NULL; return NULL;
if (fDefaultPipes[speed] == NULL) { if (fDefaultPipes[speed] == NULL) {
fDefaultPipes[speed] = new(std::nothrow) ControlPipe(fRootObject, fDefaultPipes[speed] = new(std::nothrow) ControlPipe(fRootObject,
0, 0, speed, 8); 0, 0, speed, 8);
if (!fDefaultPipes[speed]) { }
TRACE_ERROR(("usb BusManager: failed to allocate default pipe\n"));
Unlock(); if (!fDefaultPipes[speed]) {
return NULL; TRACE_ERROR(("USB BusManager: failed to allocate default pipe for speed %d\n", speed));
}
} }
Unlock(); Unlock();
return fDefaultPipes[speed]; return fDefaultPipes[speed];
} }
+31 -25
View File
@@ -20,17 +20,15 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
fSpeed(speed), fSpeed(speed),
fDeviceAddress(deviceAddress) fDeviceAddress(deviceAddress)
{ {
TRACE(("USB Device: new device\n")); TRACE(("USB Device %d: creating device\n", fDeviceAddress));
fDefaultPipe = new(std::nothrow) ControlPipe(this, deviceAddress, 0, fDefaultPipe = new(std::nothrow) ControlPipe(this, deviceAddress, 0,
fSpeed, fDeviceDescriptor.max_packet_size_0); fSpeed, fDeviceDescriptor.max_packet_size_0);
if (!fDefaultPipe) { if (!fDefaultPipe) {
TRACE_ERROR(("USB Device: could not allocate default pipe\n")); TRACE_ERROR(("USB Device %d: could not allocate default pipe\n", fDeviceAddress));
return; return;
} }
fMaxPacketIn[0] = fMaxPacketOut[0] = fDeviceDescriptor.max_packet_size_0;
// Get the device descriptor // Get the device descriptor
// We already have a part of it, but we want it all // We already have a part of it, but we want it all
size_t actualLength; size_t actualLength;
@@ -38,7 +36,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
(void *)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength); (void *)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength);
if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) { if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) {
TRACE_ERROR(("USB Device: error while getting the device descriptor\n")); TRACE_ERROR(("USB Device %d: error while getting the device descriptor\n", fDeviceAddress));
return; return;
} }
@@ -62,7 +60,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
fConfigurations = (usb_configuration_info *)malloc( fConfigurations = (usb_configuration_info *)malloc(
fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info)); fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info));
if (fConfigurations == NULL) { if (fConfigurations == NULL) {
TRACE_ERROR(("USB Device: out of memory during config creations!\n")); TRACE_ERROR(("USB Device %d: out of memory during config creations!\n", fDeviceAddress));
return; return;
} }
@@ -77,7 +75,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
return; return;
} }
TRACE(("USB Device %d: configuration %d\n", fDeviceAddress, i)); TRACE(("USB Device %d: configuration %ld\n", fDeviceAddress, i));
TRACE(("\tlength:..............%d\n", configDescriptor.length)); TRACE(("\tlength:..............%d\n", configDescriptor.length));
TRACE(("\tdescriptor_type:.....0x%02x\n", configDescriptor.descriptor_type)); TRACE(("\tdescriptor_type:.....0x%02x\n", configDescriptor.descriptor_type));
TRACE(("\ttotal_length:........%d\n", configDescriptor.total_length)); TRACE(("\ttotal_length:........%d\n", configDescriptor.total_length));
@@ -426,11 +424,7 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
uint32 supportDescriptorCount, const usb_notify_hooks *hooks, uint32 supportDescriptorCount, const usb_notify_hooks *hooks,
usb_driver_cookie **cookies, bool added) usb_driver_cookie **cookies, bool added)
{ {
TRACE(("USB Device ReportDevice\n")); TRACE(("USB Device %d: reporting device\n", fDeviceAddress));
if ((added && hooks->device_added == NULL)
|| (!added && hooks->device_removed == NULL))
return B_BAD_VALUE;
bool supported = false; bool supported = false;
if (supportDescriptorCount == 0 || supportDescriptors == NULL) if (supportDescriptorCount == 0 || supportDescriptors == NULL)
supported = true; supported = true;
@@ -469,17 +463,26 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
} }
} }
if (supported) { if (!supported)
usb_id id = USBID(); return B_UNSUPPORTED;
if (added) {
usb_driver_cookie *cookie = new(std::nothrow) usb_driver_cookie; if ((added && hooks->device_added == NULL)
status_t result = hooks->device_added(id, &cookie->cookie); || (!added && hooks->device_removed == NULL)) {
// hooks are not installed, but report success to indicate that
// the driver supports the device
return B_OK;
}
usb_id id = USBID();
if (added) {
usb_driver_cookie *cookie = new(std::nothrow) usb_driver_cookie;
if (hooks->device_added(id, &cookie->cookie) >= B_OK) {
cookie->device = id; cookie->device = id;
cookie->link = *cookies; cookie->link = *cookies;
*cookies = cookie; *cookies = cookie;
return result; } else
} delete cookie;
} else {
usb_driver_cookie **pointer = cookies; usb_driver_cookie **pointer = cookies;
usb_driver_cookie *cookie = *cookies; usb_driver_cookie *cookie = *cookies;
while (cookie) { while (cookie) {
@@ -489,15 +492,18 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
cookie = cookie->link; cookie = cookie->link;
} }
if (cookie) { if (!cookie) {
hooks->device_removed(cookie->cookie); // the device is supported, but there is no cookie. this most
*pointer = cookie->link; // probably means that the device_added hook above failed.
delete cookie;
return B_OK; return B_OK;
} }
hooks->device_removed(cookie->cookie);
*pointer = cookie->link;
delete cookie;
} }
return B_UNSUPPORTED; return B_OK;
} }
+79 -30
View File
@@ -15,36 +15,41 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
usb_speed speed) usb_speed speed)
: Device(parent, desc, deviceAddress, speed) : Device(parent, desc, deviceAddress, speed)
{ {
TRACE(("USB Hub is being initialised\n")); TRACE(("USB Hub %d: creating hub\n", DeviceAddress()));
if (!fInitOK) { if (!fInitOK) {
TRACE_ERROR(("USB Hub: Device failed to initialize\n")); TRACE_ERROR(("USB Hub %d: device failed to initialize\n", DeviceAddress()));
return; return;
} }
// Set to false again for the hub init. // Set to false again for the hub init.
fInitOK = false; fInitOK = false;
if (benaphore_init(&fLock, "usb hub lock") < B_OK) {
TRACE_ERROR(("USB Hub %d: failed to create hub lock\n", DeviceAddress()));
return;
}
for (int32 i = 0; i < 8; i++) for (int32 i = 0; i < 8; i++)
fChildren[i] = NULL; fChildren[i] = NULL;
if (fDeviceDescriptor.device_class != 9) { if (fDeviceDescriptor.device_class != 9) {
TRACE_ERROR(("USB Hub: wrong class! Bailing out\n")); TRACE_ERROR(("USB Hub %d: wrong class! bailing out\n", DeviceAddress()));
return; return;
} }
TRACE(("USB Hub: Getting hub descriptor...\n")); TRACE(("USB Hub %d: Getting hub descriptor...\n", DeviceAddress()));
size_t actualLength; size_t actualLength;
status_t status = GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0, status_t status = GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
(void *)&fHubDescriptor, sizeof(usb_hub_descriptor), &actualLength); (void *)&fHubDescriptor, sizeof(usb_hub_descriptor), &actualLength);
// we need at least 8 bytes // we need at least 8 bytes
if (status < B_OK || actualLength < 8) { if (status < B_OK || actualLength < 8) {
TRACE_ERROR(("USB Hub: Error getting hub descriptor\n")); TRACE_ERROR(("USB Hub %d: Error getting hub descriptor\n", DeviceAddress()));
return; return;
} }
TRACE(("USB Hub: Hub descriptor (%d bytes):\n", actualLength)); TRACE(("USB Hub %d: hub descriptor (%ld bytes):\n", DeviceAddress(), actualLength));
TRACE(("\tlength:..............%d\n", fHubDescriptor.length)); TRACE(("\tlength:..............%d\n", fHubDescriptor.length));
TRACE(("\tdescriptor_type:.....0x%02x\n", fHubDescriptor.descriptor_type)); TRACE(("\tdescriptor_type:.....0x%02x\n", fHubDescriptor.descriptor_type));
TRACE(("\tnum_ports:...........%d\n", fHubDescriptor.num_ports)); TRACE(("\tnum_ports:...........%d\n", fHubDescriptor.num_ports));
@@ -55,7 +60,7 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
Object *object = GetStack()->GetObject(Configuration()->interface->active->endpoint[0].handle); Object *object = GetStack()->GetObject(Configuration()->interface->active->endpoint[0].handle);
if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) { if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) {
TRACE_ERROR(("USB Hub: no interrupt pipe found\n")); TRACE_ERROR(("USB Hub %d: no interrupt pipe found\n", DeviceAddress()));
return; return;
} }
@@ -72,14 +77,47 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
USB_REQUEST_SET_FEATURE, PORT_POWER, i + 1, 0, NULL, 0, NULL); USB_REQUEST_SET_FEATURE, PORT_POWER, i + 1, 0, NULL, 0, NULL);
if (status < B_OK) if (status < B_OK)
TRACE_ERROR(("USB Hub: power up failed on port %ld\n", i)); TRACE_ERROR(("USB Hub %d: power up failed on port %ld\n", DeviceAddress(), i));
} }
// Wait for power to stabilize // Wait for power to stabilize
snooze(fHubDescriptor.power_on_to_power_good * 2000); snooze(fHubDescriptor.power_on_to_power_good * 2000);
fInitOK = true; fInitOK = true;
TRACE(("USB Hub: initialised ok\n")); TRACE(("USB Hub %d: initialised ok\n", DeviceAddress()));
}
Hub::~Hub()
{
Lock();
benaphore_destroy(&fLock);
// Remove all child devices
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
if (!fChildren[i])
continue;
TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i]));
GetStack()->NotifyDeviceChange(fChildren[i], false);
GetBusManager()->FreeDevice(fChildren[i]);
}
delete fInterruptPipe;
}
bool
Hub::Lock()
{
return (benaphore_lock(&fLock) == B_OK);
}
void
Hub::Unlock()
{
benaphore_unlock(&fLock);
} }
@@ -93,7 +131,7 @@ Hub::UpdatePortStatus(uint8 index)
4, &actualLength); 4, &actualLength);
if (result < B_OK || actualLength < 4) { if (result < B_OK || actualLength < 4) {
TRACE_ERROR(("USB Hub: error updating port status\n")); TRACE_ERROR(("USB Hub %d: error updating port status\n", DeviceAddress()));
return B_ERROR; return B_ERROR;
} }
@@ -124,7 +162,7 @@ Hub::ResetPort(uint8 index)
} }
if ((fPortStatus[index].change & C_PORT_RESET) == 0) { if ((fPortStatus[index].change & C_PORT_RESET) == 0) {
TRACE_ERROR(("USB Hub: port %d won't reset\n", index)); TRACE_ERROR(("USB Hub %d: port %d won't reset\n", DeviceAddress(), index));
return B_ERROR; return B_ERROR;
} }
@@ -136,7 +174,7 @@ Hub::ResetPort(uint8 index)
// wait for reset recovery // wait for reset recovery
snooze(USB_DELAY_PORT_RESET_RECOVERY); snooze(USB_DELAY_PORT_RESET_RECOVERY);
TRACE(("USB Hub: port %d was reset successfully\n", index)); TRACE(("USB Hub %d: port %d was reset successfully\n", DeviceAddress(), index));
return B_OK; return B_OK;
} }
@@ -146,7 +184,7 @@ Hub::Explore()
{ {
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
if (i >= 8) { if (i >= 8) {
TRACE(("USB Hub: hub supports more ports than we do (%d)\n", fHubDescriptor.num_ports)); TRACE(("USB Hub %d: hub supports more ports than we do (%d)\n", DeviceAddress(), fHubDescriptor.num_ports));
fHubDescriptor.num_ports = 8; fHubDescriptor.num_ports = 8;
continue; continue;
} }
@@ -157,8 +195,8 @@ Hub::Explore()
#ifdef TRACE_USB #ifdef TRACE_USB
if (fPortStatus[i].change) { if (fPortStatus[i].change) {
TRACE(("USB Hub: port %d: status: 0x%04x; change: 0x%04x\n", i, fPortStatus[i].status, fPortStatus[i].change)); TRACE(("USB Hub %d: port %ld: status: 0x%04x; change: 0x%04x\n", DeviceAddress(), i, fPortStatus[i].status, fPortStatus[i].change));
TRACE(("USB Hub: device at port %d: 0x%08x\n", i, fChildren[i])); TRACE(("USB Hub %d: device at port %ld: 0x%08lx\n", DeviceAddress(), i, fChildren[i]));
} }
#endif #endif
@@ -170,7 +208,7 @@ Hub::Explore()
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) { if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
// new device attached! // new device attached!
TRACE(("USB Hub: Explore(): New device connected\n")); TRACE(("USB Hub %d: new device connected\n", DeviceAddress()));
// wait some time for the device to power up // wait some time for the device to power up
snooze(USB_DELAY_DEVICE_POWER_UP); snooze(USB_DELAY_DEVICE_POWER_UP);
@@ -186,7 +224,7 @@ Hub::Explore()
if ((fPortStatus[i].status & PORT_STATUS_CONNECTION) == 0) { if ((fPortStatus[i].status & PORT_STATUS_CONNECTION) == 0) {
// device has vanished after reset, ignore // device has vanished after reset, ignore
TRACE(("USB Hub: device disappeared on reset\n")); TRACE(("USB Hub %d: device disappeared on reset\n", DeviceAddress()));
continue; continue;
} }
@@ -196,13 +234,16 @@ Hub::Explore()
if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED) if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED)
speed = USB_SPEED_HIGHSPEED; speed = USB_SPEED_HIGHSPEED;
Device *newDevice = GetBusManager()->AllocateNewDevice(this, Device *newDevice = GetBusManager()->AllocateDevice(this, speed);
speed);
if (newDevice) { if (newDevice && Lock()) {
fChildren[i] = newDevice; fChildren[i] = newDevice;
Unlock();
GetStack()->NotifyDeviceChange(fChildren[i], true); GetStack()->NotifyDeviceChange(fChildren[i], true);
} else { } else {
if (newDevice)
GetBusManager()->FreeDevice(newDevice);
// the device failed to setup correctly, disable the port // the device failed to setup correctly, disable the port
// so that the device doesn't get in the way of future // so that the device doesn't get in the way of future
// addressing. // addressing.
@@ -212,40 +253,44 @@ Hub::Explore()
} }
} else { } else {
// Device removed... // Device removed...
TRACE(("USB Hub Explore(): Device removed\n")); TRACE(("USB Hub %d: device removed\n", DeviceAddress()));
if (fChildren[i]) { if (fChildren[i]) {
TRACE(("USB Hub: removing device 0x%08x\n", fChildren[i])); TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i]));
GetStack()->NotifyDeviceChange(fChildren[i], false); GetStack()->NotifyDeviceChange(fChildren[i], false);
delete fChildren[i];
fChildren[i] = NULL; if (Lock()) {
GetBusManager()->FreeDevice(fChildren[i]);
fChildren[i] = NULL;
Unlock();
}
} }
} }
} }
// other port changes we do not really handle, report and clear them // other port changes we do not really handle, report and clear them
if (fPortStatus[i].change & PORT_STATUS_ENABLE) { if (fPortStatus[i].change & PORT_STATUS_ENABLE) {
TRACE_ERROR(("USB Hub Explore(): port %ld %sabled\n", i, (fPortStatus[i].status & PORT_STATUS_ENABLE) ? "en" : "dis")); TRACE_ERROR(("USB Hub %d: port %ld %sabled\n", DeviceAddress(), i, (fPortStatus[i].status & PORT_STATUS_ENABLE) ? "en" : "dis"));
DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE, C_PORT_ENABLE, i + 1, USB_REQUEST_CLEAR_FEATURE, C_PORT_ENABLE, i + 1,
0, NULL, 0, NULL); 0, NULL, 0, NULL);
} }
if (fPortStatus[i].change & PORT_STATUS_SUSPEND) { if (fPortStatus[i].change & PORT_STATUS_SUSPEND) {
TRACE_ERROR(("USB Hub Explore(): port %ld is %ssuspended\n", i, (fPortStatus[i].status & PORT_STATUS_SUSPEND) ? "" : "not ")); TRACE_ERROR(("USB Hub %d: port %ld is %ssuspended\n", DeviceAddress(), i, (fPortStatus[i].status & PORT_STATUS_SUSPEND) ? "" : "not "));
DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE, C_PORT_SUSPEND, i + 1, USB_REQUEST_CLEAR_FEATURE, C_PORT_SUSPEND, i + 1,
0, NULL, 0, NULL); 0, NULL, 0, NULL);
} }
if (fPortStatus[i].change & PORT_STATUS_OVER_CURRENT) { if (fPortStatus[i].change & PORT_STATUS_OVER_CURRENT) {
TRACE_ERROR(("USB Hub Explore(): port %ld is %sin an over current state\n", i, (fPortStatus[i].status & PORT_STATUS_OVER_CURRENT) ? "" : "not ")); TRACE_ERROR(("USB Hub %d: port %ld is %sin an over current state\n", DeviceAddress(), i, (fPortStatus[i].status & PORT_STATUS_OVER_CURRENT) ? "" : "not "));
DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE, C_PORT_OVER_CURRENT, i + 1, USB_REQUEST_CLEAR_FEATURE, C_PORT_OVER_CURRENT, i + 1,
0, NULL, 0, NULL); 0, NULL, 0, NULL);
} }
if (fPortStatus[i].change & PORT_RESET) { if (fPortStatus[i].change & PORT_RESET) {
TRACE_ERROR(("USB Hub Explore(): port %ld was reset\n", i)); TRACE_ERROR(("USB Hub %d: port %ld was reset\n", DeviceAddress(), i));
DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, i + 1, USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, i + 1,
0, NULL, 0, NULL); 0, NULL, 0, NULL);
@@ -266,7 +311,7 @@ void
Hub::InterruptCallback(void *cookie, status_t status, void *data, Hub::InterruptCallback(void *cookie, status_t status, void *data,
size_t actualLength) size_t actualLength)
{ {
TRACE(("USB Hub: interrupt callback!\n")); TRACE(("USB Hub %d: interrupt callback!\n", ((Hub *)data)->DeviceAddress()));
} }
@@ -291,13 +336,16 @@ Hub::ReportDevice(usb_support_descriptor *supportDescriptors,
uint32 supportDescriptorCount, const usb_notify_hooks *hooks, uint32 supportDescriptorCount, const usb_notify_hooks *hooks,
usb_driver_cookie **cookies, bool added) usb_driver_cookie **cookies, bool added)
{ {
TRACE(("USB Hub ReportDevice\n")); TRACE(("USB Hub %d: reporting hub\n", DeviceAddress()));
// Report ourselfs first // Report ourselfs first
status_t result = Device::ReportDevice(supportDescriptors, status_t result = Device::ReportDevice(supportDescriptors,
supportDescriptorCount, hooks, cookies, added); supportDescriptorCount, hooks, cookies, added);
// Then report all of our children // Then report all of our children
if (!Lock())
return B_ERROR;
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
if (!fChildren[i]) if (!fChildren[i])
continue; continue;
@@ -307,6 +355,7 @@ Hub::ReportDevice(usb_support_descriptor *supportDescriptors,
result = B_OK; result = B_OK;
} }
Unlock();
return result; return result;
} }
+20 -10
View File
@@ -41,7 +41,7 @@ Pipe::SubmitTransfer(Transfer *transfer)
status_t status_t
Pipe::CancelQueuedTransfers() Pipe::CancelQueuedTransfers()
{ {
TRACE_ERROR(("Pipe: cancelling transfers is not implemented!\n")); TRACE_ERROR(("USB Pipe: cancelling transfers is not implemented!\n"));
return B_ERROR; return B_ERROR;
} }
@@ -120,7 +120,7 @@ InterruptPipe::QueueInterrupt(void *data, size_t dataLength,
transfer->SetData((uint8 *)data, dataLength); transfer->SetData((uint8 *)data, dataLength);
transfer->SetCallback(callback, callbackCookie); transfer->SetCallback(callback, callbackCookie);
status_t result = SubmitTransfer(transfer); status_t result = GetBusManager()->SubmitTransfer(transfer);
if (result < B_OK) if (result < B_OK)
delete transfer; delete transfer;
return result; return result;
@@ -151,7 +151,7 @@ BulkPipe::QueueBulk(void *data, size_t dataLength, usb_callback_func callback,
transfer->SetData((uint8 *)data, dataLength); transfer->SetData((uint8 *)data, dataLength);
transfer->SetCallback(callback, callbackCookie); transfer->SetCallback(callback, callbackCookie);
status_t result = SubmitTransfer(transfer); status_t result = GetBusManager()->SubmitTransfer(transfer);
if (result < B_OK) if (result < B_OK)
delete transfer; delete transfer;
return result; return result;
@@ -169,7 +169,7 @@ BulkPipe::QueueBulkV(iovec *vector, size_t vectorCount,
transfer->SetVector(vector, vectorCount); transfer->SetVector(vector, vectorCount);
transfer->SetCallback(callback, callbackCookie); transfer->SetCallback(callback, callbackCookie);
status_t result = SubmitTransfer(transfer); status_t result = GetBusManager()->SubmitTransfer(transfer);
if (result < B_OK) if (result < B_OK)
delete transfer; delete transfer;
return result; return result;
@@ -261,7 +261,7 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value,
size_t *actualLength) size_t *actualLength)
{ {
transfer_result_data transferResult; transfer_result_data transferResult;
transferResult.notify_sem = create_sem(0, "Send Request Notify Sem"); transferResult.notify_sem = create_sem(0, "usb send request notify");
if (transferResult.notify_sem < B_OK) if (transferResult.notify_sem < B_OK)
return B_NO_MORE_SEMS; return B_NO_MORE_SEMS;
@@ -272,11 +272,21 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value,
return result; return result;
} }
// the sem will be released in the callback after // the sem will be released in the callback after the result data was
// the result data was filled into the provided struct // filled into the provided struct. use a 5 seconds timeout to avoid
acquire_sem(transferResult.notify_sem); // hanging applications.
delete_sem(transferResult.notify_sem); if (acquire_sem_etc(transferResult.notify_sem, 1, B_RELATIVE_TIMEOUT, 5000000) < B_OK) {
TRACE_ERROR(("USB ControlPipe: timeout waiting for queued request to complete\n"));
delete_sem(transferResult.notify_sem);
if (actualLength)
*actualLength = 0;
// ToDo: cancel the transfer at the bus manager
return B_TIMED_OUT;
}
delete_sem(transferResult.notify_sem);
if (actualLength) if (actualLength)
*actualLength = transferResult.actual_length; *actualLength = transferResult.actual_length;
@@ -320,7 +330,7 @@ ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value,
transfer->SetData((uint8 *)data, dataLength); transfer->SetData((uint8 *)data, dataLength);
transfer->SetCallback(callback, callbackCookie); transfer->SetCallback(callback, callbackCookie);
status_t result = SubmitTransfer(transfer); status_t result = GetBusManager()->SubmitTransfer(transfer);
if (result < B_OK) if (result < B_OK)
delete transfer; delete transfer;
return result; return result;
+87 -66
View File
@@ -13,6 +13,9 @@
#include "usb_p.h" #include "usb_p.h"
#include "PhysicalMemoryAllocator.h" #include "PhysicalMemoryAllocator.h"
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
#include <fs/devfs.h>
#endif
Stack::Stack() Stack::Stack()
: fExploreThread(-1), : fExploreThread(-1),
@@ -23,10 +26,10 @@ Stack::Stack()
fObjectArray(NULL), fObjectArray(NULL),
fDriverList(NULL) fDriverList(NULL)
{ {
TRACE(("usb stack: stack init\n")); TRACE(("USB Stack: stack init\n"));
if (benaphore_init(&fLock, "USB Stack Master Lock") < B_OK) { if (benaphore_init(&fLock, "usb stack lock") < B_OK) {
TRACE_ERROR(("usb stack: failed to create benaphore lock\n")); TRACE_ERROR(("USB Stack: failed to create benaphore lock\n"));
return; return;
} }
@@ -37,7 +40,7 @@ Stack::Stack()
fAllocator = new(std::nothrow) PhysicalMemoryAllocator("USB Stack Allocator", fAllocator = new(std::nothrow) PhysicalMemoryAllocator("USB Stack Allocator",
8, B_PAGE_SIZE * 4, 64); 8, B_PAGE_SIZE * 4, 64);
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;
return; return;
} }
@@ -47,10 +50,10 @@ Stack::Stack()
char moduleName[B_PATH_NAME_LENGTH]; char moduleName[B_PATH_NAME_LENGTH];
size_t bufferSize = sizeof(moduleName); size_t bufferSize = sizeof(moduleName);
TRACE(("usb stack: Looking for host controller modules\n")); TRACE(("USB Stack: looking for host controller modules\n"));
while(read_next_module_name(moduleList, moduleName, &bufferSize) == B_OK) { while(read_next_module_name(moduleList, moduleName, &bufferSize) == B_OK) {
bufferSize = sizeof(moduleName); bufferSize = sizeof(moduleName);
TRACE(("usb stack: Found module %s\n", moduleName)); TRACE(("USB Stack: found module %s\n", moduleName));
host_controller_info *module = NULL; host_controller_info *module = NULL;
if (get_module(moduleName, (module_info **)&module) != B_OK) if (get_module(moduleName, (module_info **)&module) != B_OK)
@@ -59,16 +62,11 @@ Stack::Stack()
if (module->add_to(this) < B_OK) if (module->add_to(this) < B_OK)
continue; continue;
TRACE(("usb stack: module %s successfully loaded\n", moduleName)); 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")); 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; return;
} }
@@ -132,16 +130,22 @@ Stack::GetUSBID(Object *object)
if (!Lock()) if (!Lock())
return 0; return 0;
if (fObjectIndex >= fObjectMaxCount) { uint32 id = fObjectIndex;
Unlock(); uint32 tries = fObjectMaxCount;
return 0; while (tries-- > 0) {
if (fObjectArray[id] == NULL) {
fObjectIndex = (id + 1) % fObjectMaxCount;
fObjectArray[id] = object;
Unlock();
return (usb_id)id;
}
id = (id + 1) % fObjectMaxCount;
} }
uint32 id = fObjectIndex++; TRACE_ERROR(("USB Stack: the stack did run out of usb_ids\n"));
fObjectArray[id] = object;
Unlock(); Unlock();
return 0;
return (usb_id)id;
} }
@@ -152,7 +156,7 @@ Stack::PutUSBID(usb_id id)
return; return;
if (id >= fObjectMaxCount) { if (id >= fObjectMaxCount) {
TRACE_ERROR(("usb stack: tried to put invalid usb_id!\n")); TRACE_ERROR(("USB Stack: tried to put an invalid usb_id\n"));
Unlock(); Unlock();
return; return;
} }
@@ -169,14 +173,14 @@ Stack::GetObject(usb_id id)
return NULL; return NULL;
if (id >= fObjectMaxCount) { if (id >= fObjectMaxCount) {
TRACE_ERROR(("usb stack: tried to get object with invalid id\n")); TRACE_ERROR(("USB Stack: tried to get object with invalid usb_id\n"));
Unlock(); Unlock();
return NULL; return NULL;
} }
Object *result = fObjectArray[id]; Object *result = fObjectArray[id];
Unlock();
Unlock();
return result; return result;
} }
@@ -187,9 +191,6 @@ Stack::ExploreThread(void *data)
Stack *stack = (Stack *)data; Stack *stack = (Stack *)data;
while (!stack->fStopThreads) { while (!stack->fStopThreads) {
if (benaphore_lock(&stack->fExploreLock) != B_OK)
continue;
for (int32 i = 0; i < stack->fBusManagers.Count(); i++) { for (int32 i = 0; i < stack->fBusManagers.Count(); i++) {
Hub *rootHub = stack->fBusManagers.ElementAt(i)->GetRootHub(); Hub *rootHub = stack->fBusManagers.ElementAt(i)->GetRootHub();
if (rootHub) if (rootHub)
@@ -197,7 +198,6 @@ Stack::ExploreThread(void *data)
} }
stack->fFirstExploreDone = true; stack->fFirstExploreDone = true;
benaphore_unlock(&stack->fExploreLock);
snooze(USB_DELAY_HUB_EXPLORE); snooze(USB_DELAY_HUB_EXPLORE);
} }
@@ -237,7 +237,7 @@ area_id
Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size, Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size,
const char *name) const char *name)
{ {
TRACE(("usb stack: allocating %ld bytes for %s\n", size, name)); TRACE(("USB Stack: allocating %ld bytes for %s\n", size, name));
void *logAddress; void *logAddress;
size = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); size = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
@@ -245,7 +245,7 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size,
B_FULL_LOCK | B_CONTIGUOUS, 0); B_FULL_LOCK | B_CONTIGUOUS, 0);
if (area < B_OK) { if (area < B_OK) {
TRACE_ERROR(("usb stack: couldn't allocate area %s\n", name)); TRACE_ERROR(("USB Stack: couldn't allocate area %s\n", name));
return B_ERROR; return B_ERROR;
} }
@@ -253,7 +253,7 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size,
status_t result = get_memory_map(logAddress, size, &physicalEntry, 1); status_t result = get_memory_map(logAddress, size, &physicalEntry, 1);
if (result < B_OK) { if (result < B_OK) {
delete_area(area); delete_area(area);
TRACE_ERROR(("usb stack: couldn't map area %s\n", name)); TRACE_ERROR(("USB Stack: couldn't map area %s\n", name));
return B_ERROR; return B_ERROR;
} }
@@ -264,7 +264,7 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size,
if (physicalAddress) if (physicalAddress)
*physicalAddress = physicalEntry.address; *physicalAddress = physicalEntry.address;
TRACE(("usb stack: area = 0x%08x, size = %ld, log = 0x%08x, phy = 0x%08x\n", TRACE(("USB Stack: area = 0x%08lx, size = %ld, log = 0x%08lx, phy = 0x%08lx\n",
area, size, logAddress, physicalEntry.address)); area, size, logAddress, physicalEntry.address));
return area; return area;
} }
@@ -273,24 +273,33 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size,
void void
Stack::NotifyDeviceChange(Device *device, bool added) Stack::NotifyDeviceChange(Device *device, bool added)
{ {
TRACE(("usb stack: device %s\n", added ? "added" : "removed")); TRACE(("USB Stack: device %s\n", added ? "added" : "removed"));
usb_driver_info *element = fDriverList; usb_driver_info *element = fDriverList;
while (element) { while (element) {
if ((added && element->notify_hooks.device_added != NULL) status_t result = device->ReportDevice(element->support_descriptors,
|| (!added && element->notify_hooks.device_removed != NULL)) { element->support_descriptor_count, &element->notify_hooks,
status_t result = device->ReportDevice(element->support_descriptors, &element->cookies, added);
element->support_descriptor_count,
&element->notify_hooks, &element->cookies, added);
if (result == B_OK) { if (result >= B_OK) {
const char *name = element->driver_name; // the device is supported by this driver. it either got notified
if (element->republish_driver_name) // already by the hooks or it is not loaded at this time. in any
name = element->republish_driver_name; // case we will rescan the driver so it either is loaded and can
int devFS = open("/dev", O_WRONLY); // scan for supported devices or its publish_devices hook will be
write(devFS, name, strlen(name)); // called to expose new devices.
close(devFS); const char *name = element->driver_name;
} if (element->republish_driver_name)
name = element->republish_driver_name;
#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
} }
element = element->link; element = element->link;
@@ -303,10 +312,39 @@ Stack::RegisterDriver(const char *driverName,
const usb_support_descriptor *descriptors, const usb_support_descriptor *descriptors,
size_t descriptorCount, const char *republishDriverName) size_t descriptorCount, const char *republishDriverName)
{ {
TRACE(("usb stack: register driver \"%s\"\n", driverName)); TRACE(("USB Stack: register driver \"%s\"\n", driverName));
if (!driverName)
return B_BAD_VALUE;
if (!Lock())
return B_ERROR;
usb_driver_info *element = fDriverList;
while (element) {
if (strcmp(element->driver_name, driverName) == 0) {
// we already have an entry for this driver, just update it
free((char *)element->republish_driver_name);
element->republish_driver_name = strdup(republishDriverName);
free(element->support_descriptors);
size_t descriptorsSize = descriptorCount * sizeof(usb_support_descriptor);
element->support_descriptors = (usb_support_descriptor *)malloc(descriptorsSize);
memcpy(element->support_descriptors, descriptors, descriptorsSize);
element->support_descriptor_count = descriptorCount;
Unlock();
return B_OK;
}
element = element->link;
}
// this is a new driver, add it to the driver list
usb_driver_info *info = new(std::nothrow) usb_driver_info; usb_driver_info *info = new(std::nothrow) usb_driver_info;
if (!info) if (!info) {
Unlock();
return B_NO_MEMORY; return B_NO_MEMORY;
}
info->driver_name = strdup(driverName); info->driver_name = strdup(driverName);
info->republish_driver_name = strdup(republishDriverName); info->republish_driver_name = strdup(republishDriverName);
@@ -321,11 +359,6 @@ Stack::RegisterDriver(const char *driverName,
info->cookies = NULL; info->cookies = NULL;
info->link = NULL; info->link = NULL;
if (!Lock()) {
delete info;
return B_ERROR;
}
if (fDriverList) { if (fDriverList) {
usb_driver_info *element = fDriverList; usb_driver_info *element = fDriverList;
while (element->link) while (element->link)
@@ -343,16 +376,11 @@ Stack::RegisterDriver(const char *driverName,
status_t status_t
Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks) Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
{ {
TRACE(("usb stack: installing notify hooks for driver \"%s\"\n", driverName)); TRACE(("USB Stack: installing notify hooks for driver \"%s\"\n", driverName));
usb_driver_info *element = fDriverList; usb_driver_info *element = fDriverList;
while (element) { while (element) {
if (strcmp(element->driver_name, driverName) == 0) { 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 // inform driver about any already present devices
for (int32 i = 0; i < fBusManagers.Count(); i++) { for (int32 i = 0; i < fBusManagers.Count(); i++) {
Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub(); Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub();
@@ -366,7 +394,6 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
element->notify_hooks.device_added = hooks->device_added; element->notify_hooks.device_added = hooks->device_added;
element->notify_hooks.device_removed = hooks->device_removed; element->notify_hooks.device_removed = hooks->device_removed;
benaphore_unlock(&fExploreLock);
return B_OK; return B_OK;
} }
@@ -380,16 +407,11 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
status_t status_t
Stack::UninstallNotify(const char *driverName) Stack::UninstallNotify(const char *driverName)
{ {
TRACE(("usb stack: uninstalling notify hooks for driver \"%s\"\n", driverName)); TRACE(("USB Stack: uninstalling notify hooks for driver \"%s\"\n", driverName));
usb_driver_info *element = fDriverList; usb_driver_info *element = fDriverList;
while (element) { while (element) {
if (strcmp(element->driver_name, driverName) == 0) { 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 // trigger the device removed hook
for (int32 i = 0; i < fBusManagers.Count(); i++) { for (int32 i = 0; i < fBusManagers.Count(); i++) {
Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub(); Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub();
@@ -401,7 +423,6 @@ Stack::UninstallNotify(const char *driverName)
element->notify_hooks.device_added = NULL; element->notify_hooks.device_added = NULL;
element->notify_hooks.device_removed = NULL; element->notify_hooks.device_removed = NULL;
benaphore_unlock(&fExploreLock);
return B_OK; return B_OK;
} }
+19 -19
View File
@@ -43,7 +43,7 @@ bus_std_ops(int32 op, ...)
} }
case B_MODULE_UNINIT: case B_MODULE_UNINIT:
TRACE(("usb_module: bus module: uninit\n")); TRACE(("usb_module: uninit\n"));
delete gUSBStack; delete gUSBStack;
gUSBStack = NULL; gUSBStack = NULL;
break; break;
@@ -83,7 +83,7 @@ uninstall_notify(const char *driverName)
const usb_device_descriptor * const usb_device_descriptor *
get_device_descriptor(usb_device device) get_device_descriptor(usb_device device)
{ {
TRACE(("usb_module: get_device_descriptor(0x%08x)\n", device)); TRACE(("usb_module: get_device_descriptor(%ld)\n", device));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL; return NULL;
@@ -95,7 +95,7 @@ get_device_descriptor(usb_device device)
const usb_configuration_info * const usb_configuration_info *
get_nth_configuration(usb_device device, uint index) get_nth_configuration(usb_device device, uint index)
{ {
TRACE(("usb_module: get_nth_configuration(0x%08x, %d)\n", device, index)); TRACE(("usb_module: get_nth_configuration(%ld, %d)\n", device, index));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL; return NULL;
@@ -107,7 +107,7 @@ get_nth_configuration(usb_device device, uint index)
const usb_configuration_info * const usb_configuration_info *
get_configuration(usb_device device) get_configuration(usb_device device)
{ {
TRACE(("usb_module: get_configuration(0x%08x)\n", device)); TRACE(("usb_module: get_configuration(%ld)\n", device));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return NULL; return NULL;
@@ -120,7 +120,7 @@ status_t
set_configuration(usb_device device, set_configuration(usb_device device,
const usb_configuration_info *configuration) const usb_configuration_info *configuration)
{ {
TRACE(("usb_module: set_configuration(0x%08x, 0x%08x)\n", device, configuration)); TRACE(("usb_module: set_configuration(%ld, 0x%08lx)\n", device, configuration));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -132,7 +132,7 @@ set_configuration(usb_device device,
status_t status_t
set_alt_interface(usb_device device, const usb_interface_info *interface) set_alt_interface(usb_device device, const usb_interface_info *interface)
{ {
TRACE(("usb_module: set_alt_interface(0x%08x, 0x%08x)\n", device, interface)); TRACE(("usb_module: set_alt_interface(%ld, 0x%08lx)\n", device, interface));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -144,7 +144,7 @@ set_alt_interface(usb_device device, const usb_interface_info *interface)
status_t status_t
set_feature(usb_id handle, uint16 selector) set_feature(usb_id handle, uint16 selector)
{ {
TRACE(("usb_module: set_feature(0x%08x, %d)\n", handle, selector)); TRACE(("usb_module: set_feature(%ld, %d)\n", handle, selector));
Object *object = gUSBStack->GetObject(handle); Object *object = gUSBStack->GetObject(handle);
if (!object) if (!object)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -156,7 +156,7 @@ set_feature(usb_id handle, uint16 selector)
status_t status_t
clear_feature(usb_id handle, uint16 selector) clear_feature(usb_id handle, uint16 selector)
{ {
TRACE(("usb_module: clear_feature(0x%08x, %d)\n", handle, selector)); TRACE(("usb_module: clear_feature(%ld, %d)\n", handle, selector));
Object *object = gUSBStack->GetObject(handle); Object *object = gUSBStack->GetObject(handle);
if (!object) if (!object)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -168,7 +168,7 @@ clear_feature(usb_id handle, uint16 selector)
status_t status_t
get_status(usb_id handle, uint16 *status) get_status(usb_id handle, uint16 *status)
{ {
TRACE(("usb_module: get_status(0x%08x, 0x%08x)\n", handle, status)); TRACE(("usb_module: get_status(%ld, 0x%08lx)\n", handle, status));
if (!status) if (!status)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -184,7 +184,7 @@ status_t
get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID, get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
void *data, size_t dataLength, size_t *actualLength) void *data, size_t dataLength, size_t *actualLength)
{ {
TRACE(("usb_module: get_descriptor(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%08x, %d, 0x%08x)\n", device, type, index, languageID, data, dataLength, actualLength)); TRACE(("usb_module: get_descriptor(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%08lx, %ld, 0x%08lx)\n", device, type, index, languageID, data, dataLength, actualLength));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -198,7 +198,7 @@ status_t
send_request(usb_device device, uint8 requestType, uint8 request, send_request(usb_device device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength) uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
{ {
TRACE(("usb_module: send_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, actualLength)); TRACE(("usb_module: send_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08lx, 0x%08lx)\n", device, requestType, request, value, index, length, data, actualLength));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -213,7 +213,7 @@ queue_request(usb_device device, uint8 requestType, uint8 request,
uint16 value, uint16 index, uint16 length, void *data, uint16 value, uint16 index, uint16 length, void *data,
usb_callback_func callback, void *callbackCookie) usb_callback_func callback, void *callbackCookie)
{ {
TRACE(("usb_module: queue_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, callback, callbackCookie)); TRACE(("usb_module: queue_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %ld, 0x%08lx, 0x%08lx, 0x%08lx)\n", device, requestType, request, value, index, length, data, callback, callbackCookie));
Object *object = gUSBStack->GetObject(device); Object *object = gUSBStack->GetObject(device);
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -227,7 +227,7 @@ status_t
queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie) usb_callback_func callback, void *callbackCookie)
{ {
TRACE(("usb_module: queue_interrupt(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie)); TRACE(("usb_module: queue_interrupt(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, callback, callbackCookie));
Object *object = gUSBStack->GetObject(pipe); Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -241,7 +241,7 @@ status_t
queue_bulk(usb_pipe pipe, void *data, size_t dataLength, queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
usb_callback_func callback, void *callbackCookie) usb_callback_func callback, void *callbackCookie)
{ {
TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie)); TRACE(("usb_module: queue_bulk(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, callback, callbackCookie));
Object *object = gUSBStack->GetObject(pipe); Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -255,7 +255,7 @@ status_t
queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
usb_callback_func callback, void *callbackCookie) usb_callback_func callback, void *callbackCookie)
{ {
TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, vector, vectorCount, callback, callbackCookie)); TRACE(("usb_module: queue_bulk(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, vector, vectorCount, callback, callbackCookie));
Object *object = gUSBStack->GetObject(pipe); Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -271,7 +271,7 @@ queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback, uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
void *callbackCookie) void *callbackCookie)
{ {
TRACE(("usb_module: queue_isochronous(0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, callbackCookie)); TRACE(("usb_module: queue_isochronous(%ld, 0x%08lx, %ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, callbackCookie));
Object *object = gUSBStack->GetObject(pipe); Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -286,7 +286,7 @@ status_t
set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
uint16 maxBufferDurationMS, uint16 sampleSize) uint16 maxBufferDurationMS, uint16 sampleSize)
{ {
TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize)); TRACE(("usb_module: set_pipe_policy(%ld, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize));
Object *object = gUSBStack->GetObject(pipe); Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -299,7 +299,7 @@ set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
status_t status_t
cancel_queued_transfers(usb_pipe pipe) cancel_queued_transfers(usb_pipe pipe)
{ {
TRACE(("usb_module: cancel_queued_transfers(0x%08x)\n", pipe)); TRACE(("usb_module: cancel_queued_transfers(%ld)\n", pipe));
Object *object = gUSBStack->GetObject(pipe); Object *object = gUSBStack->GetObject(pipe);
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
return B_DEV_INVALID_PIPE; return B_DEV_INVALID_PIPE;
@@ -311,7 +311,7 @@ cancel_queued_transfers(usb_pipe pipe)
status_t status_t
usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
{ {
TRACE(("usb_module: usb_ioctl(0x%08x, 0x%08x, %d)\n", opcode, buffer, bufferSize)); TRACE(("usb_module: usb_ioctl(0x%08lx, 0x%08lx, %ld)\n", opcode, buffer, bufferSize));
switch (opcode) { switch (opcode) {
case 'DNAM': { case 'DNAM': {
+14 -5
View File
@@ -15,7 +15,6 @@
#include "BeOSCompatibility.h" #include "BeOSCompatibility.h"
//#define TRACE_USB
#ifdef TRACE_USB #ifdef TRACE_USB
#define TRACE(x) dprintf x #define TRACE(x) dprintf x
#define TRACE_ERROR(x) dprintf x #define TRACE_ERROR(x) dprintf x
@@ -135,7 +134,6 @@ static int32 ExploreThread(void *data);
bool fStopThreads; bool fStopThreads;
benaphore fLock; benaphore fLock;
benaphore fExploreLock;
PhysicalMemoryAllocator *fAllocator; PhysicalMemoryAllocator *fAllocator;
uint32 fObjectIndex; uint32 fObjectIndex;
@@ -162,8 +160,11 @@ virtual status_t InitCheck();
void Unlock(); void Unlock();
int8 AllocateAddress(); int8 AllocateAddress();
Device *AllocateNewDevice(Hub *parent, void FreeAddress(int8 address);
Device *AllocateDevice(Hub *parent,
usb_speed speed); usb_speed speed);
void FreeDevice(Device *device);
virtual status_t Start(); virtual status_t Start();
virtual status_t Stop(); virtual status_t Stop();
@@ -185,7 +186,10 @@ private:
ControlPipe *_GetDefaultPipe(usb_speed); ControlPipe *_GetDefaultPipe(usb_speed);
benaphore fLock; benaphore fLock;
bool fDeviceMap[128]; bool fDeviceMap[128];
int8 fDeviceIndex;
ControlPipe *fDefaultPipes[USB_SPEED_MAX + 1]; ControlPipe *fDefaultPipes[USB_SPEED_MAX + 1];
Hub *fRootHub; Hub *fRootHub;
Object *fRootObject; Object *fRootObject;
@@ -410,6 +414,7 @@ virtual status_t GetDescriptor(uint8 descriptorType,
void *data, size_t dataLength, void *data, size_t dataLength,
size_t *actualLength); size_t *actualLength);
int8 DeviceAddress() const { return fDeviceAddress; };
const usb_device_descriptor *DeviceDescriptor() const; const usb_device_descriptor *DeviceDescriptor() const;
const usb_configuration_info *Configuration() const; const usb_configuration_info *Configuration() const;
@@ -442,8 +447,6 @@ private:
usb_configuration_info *fCurrentConfiguration; usb_configuration_info *fCurrentConfiguration;
usb_speed fSpeed; usb_speed fSpeed;
int8 fDeviceAddress; int8 fDeviceAddress;
size_t fMaxPacketIn[16];
size_t fMaxPacketOut[16];
ControlPipe *fDefaultPipe; ControlPipe *fDefaultPipe;
}; };
@@ -454,6 +457,10 @@ public:
usb_device_descriptor &desc, usb_device_descriptor &desc,
int8 deviceAddress, int8 deviceAddress,
usb_speed speed); usb_speed speed);
virtual ~Hub();
bool Lock();
void Unlock();
virtual uint32 Type() { return USB_OBJECT_DEVICE | USB_OBJECT_HUB; }; virtual uint32 Type() { return USB_OBJECT_DEVICE | USB_OBJECT_HUB; };
@@ -480,6 +487,8 @@ virtual status_t BuildDeviceName(char *string,
Device *device); Device *device);
private: private:
benaphore fLock;
InterruptPipe *fInterruptPipe; InterruptPipe *fInterruptPipe;
usb_hub_descriptor fHubDescriptor; usb_hub_descriptor fHubDescriptor;