From c4cce7277c297a0a5a78c69a20375182522296e1 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 18 Jan 2007 22:25:02 +0000 Subject: [PATCH] * 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 --- .../kernel/bus_managers/usb/BusManager.cpp | 103 ++++++++---- .../kernel/bus_managers/usb/Device.cpp | 68 ++++---- src/add-ons/kernel/bus_managers/usb/Hub.cpp | 113 +++++++++---- src/add-ons/kernel/bus_managers/usb/Pipe.cpp | 30 ++-- src/add-ons/kernel/bus_managers/usb/Stack.cpp | 157 ++++++++++-------- src/add-ons/kernel/bus_managers/usb/usb.cpp | 38 ++--- src/add-ons/kernel/bus_managers/usb/usb_p.h | 21 ++- .../kernel/bus_managers/usb/usbspec_p.h | 10 +- 8 files changed, 337 insertions(+), 203 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp index 23769e987c..2360165a2f 100644 --- a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp +++ b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp @@ -15,7 +15,7 @@ BusManager::BusManager(Stack *stack) fRootHub(NULL) { 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; } @@ -26,6 +26,7 @@ BusManager::BusManager(Stack *stack) // Clear the device map for (int32 i = 0; i < 128; i++) fDeviceMap[i] = false; + fDeviceIndex = 0; // Set the default pipes to NULL (these will be created when needed) for (int32 i = 0; i <= USB_SPEED_MAX; i++) @@ -41,6 +42,7 @@ BusManager::~BusManager() benaphore_destroy(&fLock); for (int32 i = 0; i <= USB_SPEED_MAX; i++) delete fDefaultPipes[i]; + delete fRootObject; } @@ -74,35 +76,60 @@ BusManager::AllocateAddress() if (!Lock()) return -1; - int8 deviceAddress = -1; - for (int32 i = 1; i < 128; i++) { - if (fDeviceMap[i] == false) { - deviceAddress = i; - fDeviceMap[i] = true; - break; + int8 tries = 127; + int8 address = fDeviceIndex; + while (tries-- > 0) { + if (fDeviceMap[address] == false) { + fDeviceIndex = (address + 1) % 127; + 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(); - return deviceAddress; } 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) int8 deviceAddress = AllocateAddress(); 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; } - 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); - + 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; } @@ -126,7 +153,8 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed) } 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; } @@ -143,19 +171,20 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed) size_t actualLength = 0; usb_device_descriptor deviceDescriptor; - TRACE(("usb BusManager::AllocateNewDevice(): getting the device descriptor\n")); + TRACE(("USB BusManager: getting the device descriptor\n")); pipe.SendRequest( USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type USB_REQUEST_GET_DESCRIPTOR, // request USB_DESCRIPTOR_DEVICE << 8, // value 0, // index - 8, // length + 8, // length (void *)&deviceDescriptor, // buffer 8, // buffer length &actualLength); // actual length 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; } @@ -170,16 +199,18 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed) // Create a new instance based on the type (Hub or Device) 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, deviceAddress, speed); 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; } 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; return NULL; } @@ -187,16 +218,18 @@ BusManager::AllocateNewDevice(Hub *parent, usb_speed speed) 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, deviceAddress, speed); 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; } 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; 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 BusManager::Start() { @@ -234,24 +275,22 @@ BusManager::NotifyPipeChange(Pipe *pipe, usb_change change) return B_ERROR; } + ControlPipe * BusManager::_GetDefaultPipe(usb_speed speed) { if (!Lock()) return NULL; - if (fDefaultPipes[speed] == NULL) { fDefaultPipes[speed] = new(std::nothrow) ControlPipe(fRootObject, - 0, 0, speed, 8); - if (!fDefaultPipes[speed]) { - TRACE_ERROR(("usb BusManager: failed to allocate default pipe\n")); - Unlock(); - return NULL; - } + 0, 0, speed, 8); } - + + if (!fDefaultPipes[speed]) { + TRACE_ERROR(("USB BusManager: failed to allocate default pipe for speed %d\n", speed)); + } + Unlock(); - return fDefaultPipes[speed]; } diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index 8e5fe15c38..d70ec1d09f 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -20,17 +20,15 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, fSpeed(speed), fDeviceAddress(deviceAddress) { - TRACE(("USB Device: new device\n")); + TRACE(("USB Device %d: creating device\n", fDeviceAddress)); fDefaultPipe = new(std::nothrow) ControlPipe(this, deviceAddress, 0, fSpeed, fDeviceDescriptor.max_packet_size_0); 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; } - fMaxPacketIn[0] = fMaxPacketOut[0] = fDeviceDescriptor.max_packet_size_0; - // Get the device descriptor // We already have a part of it, but we want it all size_t actualLength; @@ -38,7 +36,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, (void *)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength); 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; } @@ -62,7 +60,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, fConfigurations = (usb_configuration_info *)malloc( fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info)); 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; } @@ -77,7 +75,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, 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(("\tdescriptor_type:.....0x%02x\n", configDescriptor.descriptor_type)); TRACE(("\ttotal_length:........%d\n", configDescriptor.total_length)); @@ -263,11 +261,11 @@ Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID, USB_REQUEST_GET_DESCRIPTOR, // request (descriptorType << 8) | index, // value languageID, // index - dataLength, // length + dataLength, // length data, // buffer dataLength, // buffer length actualLength); // actual length -} +} const usb_configuration_info * @@ -320,7 +318,7 @@ Device::SetConfigurationAt(uint8 index) USB_REQUEST_SET_CONFIGURATION, // request fConfigurations[index].descr->configuration_value, // value 0, // index - 0, // length + 0, // length NULL, // buffer 0, // buffer length NULL); // actual length @@ -388,7 +386,7 @@ Device::Unconfigure(bool atDeviceLevel) USB_REQUEST_SET_CONFIGURATION, // request 0, // value 0, // index - 0, // length + 0, // length NULL, // buffer 0, // buffer length NULL); // actual length @@ -404,7 +402,7 @@ Device::Unconfigure(bool atDeviceLevel) usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[0].active; for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) { - usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i]; + usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i]; delete (Pipe *)GetStack()->GetObject(endpoint->handle); endpoint->handle = 0; } @@ -426,11 +424,7 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors, uint32 supportDescriptorCount, const usb_notify_hooks *hooks, usb_driver_cookie **cookies, bool added) { - TRACE(("USB Device ReportDevice\n")); - if ((added && hooks->device_added == NULL) - || (!added && hooks->device_removed == NULL)) - return B_BAD_VALUE; - + TRACE(("USB Device %d: reporting device\n", fDeviceAddress)); bool supported = false; if (supportDescriptorCount == 0 || supportDescriptors == NULL) supported = true; @@ -441,7 +435,7 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors, || (supportDescriptors[i].product != 0 && fDeviceDescriptor.product_id != supportDescriptors[i].product)) continue; - + if ((supportDescriptors[i].dev_class == 0 || fDeviceDescriptor.device_class == supportDescriptors[i].dev_class) && (supportDescriptors[i].dev_subclass == 0 @@ -469,17 +463,26 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors, } } - if (supported) { - usb_id id = USBID(); - if (added) { - usb_driver_cookie *cookie = new(std::nothrow) usb_driver_cookie; - status_t result = hooks->device_added(id, &cookie->cookie); + if (!supported) + return B_UNSUPPORTED; + + if ((added && hooks->device_added == NULL) + || (!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->link = *cookies; *cookies = cookie; - return result; - } - + } else + delete cookie; + } else { usb_driver_cookie **pointer = cookies; usb_driver_cookie *cookie = *cookies; while (cookie) { @@ -489,15 +492,18 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors, cookie = cookie->link; } - if (cookie) { - hooks->device_removed(cookie->cookie); - *pointer = cookie->link; - delete cookie; + if (!cookie) { + // the device is supported, but there is no cookie. this most + // probably means that the device_added hook above failed. return B_OK; } + + hooks->device_removed(cookie->cookie); + *pointer = cookie->link; + delete cookie; } - return B_UNSUPPORTED; + return B_OK; } diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index d87a983f0e..d7acaa1dba 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -15,36 +15,41 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed) : Device(parent, desc, deviceAddress, speed) { - TRACE(("USB Hub is being initialised\n")); + TRACE(("USB Hub %d: creating hub\n", DeviceAddress())); if (!fInitOK) { - TRACE_ERROR(("USB Hub: Device failed to initialize\n")); + TRACE_ERROR(("USB Hub %d: device failed to initialize\n", DeviceAddress())); return; } // Set to false again for the hub init. 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++) fChildren[i] = NULL; 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; } - TRACE(("USB Hub: Getting hub descriptor...\n")); + TRACE(("USB Hub %d: Getting hub descriptor...\n", DeviceAddress())); size_t actualLength; status_t status = GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0, (void *)&fHubDescriptor, sizeof(usb_hub_descriptor), &actualLength); // we need at least 8 bytes 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; } - 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(("\tdescriptor_type:.....0x%02x\n", fHubDescriptor.descriptor_type)); 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); 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; } @@ -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); 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 snooze(fHubDescriptor.power_on_to_power_good * 2000); 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); 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; } @@ -124,7 +162,7 @@ Hub::ResetPort(uint8 index) } 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; } @@ -136,7 +174,7 @@ Hub::ResetPort(uint8 index) // wait for 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; } @@ -146,7 +184,7 @@ Hub::Explore() { for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { 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; continue; } @@ -157,8 +195,8 @@ Hub::Explore() #ifdef TRACE_USB 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: device at port %d: 0x%08x\n", i, fChildren[i])); + TRACE(("USB Hub %d: port %ld: status: 0x%04x; change: 0x%04x\n", DeviceAddress(), i, fPortStatus[i].status, fPortStatus[i].change)); + TRACE(("USB Hub %d: device at port %ld: 0x%08lx\n", DeviceAddress(), i, fChildren[i])); } #endif @@ -170,7 +208,7 @@ Hub::Explore() if (fPortStatus[i].status & PORT_STATUS_CONNECTION) { // 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 snooze(USB_DELAY_DEVICE_POWER_UP); @@ -186,7 +224,7 @@ Hub::Explore() if ((fPortStatus[i].status & PORT_STATUS_CONNECTION) == 0) { // 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; } @@ -196,13 +234,16 @@ Hub::Explore() if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED) speed = USB_SPEED_HIGHSPEED; - Device *newDevice = GetBusManager()->AllocateNewDevice(this, - speed); + Device *newDevice = GetBusManager()->AllocateDevice(this, speed); - if (newDevice) { + if (newDevice && Lock()) { fChildren[i] = newDevice; + Unlock(); GetStack()->NotifyDeviceChange(fChildren[i], true); } else { + if (newDevice) + GetBusManager()->FreeDevice(newDevice); + // the device failed to setup correctly, disable the port // so that the device doesn't get in the way of future // addressing. @@ -212,40 +253,44 @@ Hub::Explore() } } else { // Device removed... - TRACE(("USB Hub Explore(): Device removed\n")); + TRACE(("USB Hub %d: device removed\n", DeviceAddress())); 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); - 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 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, USB_REQUEST_CLEAR_FEATURE, C_PORT_ENABLE, i + 1, 0, NULL, 0, NULL); } 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, USB_REQUEST_CLEAR_FEATURE, C_PORT_SUSPEND, i + 1, 0, NULL, 0, NULL); } 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, USB_REQUEST_CLEAR_FEATURE, C_PORT_OVER_CURRENT, i + 1, 0, NULL, 0, NULL); } 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, USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, i + 1, 0, NULL, 0, NULL); @@ -266,7 +311,7 @@ void Hub::InterruptCallback(void *cookie, status_t status, void *data, size_t actualLength) { - TRACE(("USB Hub: interrupt callback!\n")); + TRACE(("USB Hub %d: interrupt callback!\n", ((Hub *)data)->DeviceAddress())); } @@ -279,11 +324,11 @@ Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID, USB_REQUEST_GET_DESCRIPTOR, // request (descriptorType << 8) | index, // value languageID, // index - dataLength, // length + dataLength, // length data, // buffer dataLength, // buffer length actualLength); // actual length -} +} status_t @@ -291,13 +336,16 @@ Hub::ReportDevice(usb_support_descriptor *supportDescriptors, uint32 supportDescriptorCount, const usb_notify_hooks *hooks, usb_driver_cookie **cookies, bool added) { - TRACE(("USB Hub ReportDevice\n")); + TRACE(("USB Hub %d: reporting hub\n", DeviceAddress())); // Report ourselfs first status_t result = Device::ReportDevice(supportDescriptors, supportDescriptorCount, hooks, cookies, added); // Then report all of our children + if (!Lock()) + return B_ERROR; + for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { if (!fChildren[i]) continue; @@ -307,6 +355,7 @@ Hub::ReportDevice(usb_support_descriptor *supportDescriptors, result = B_OK; } + Unlock(); return result; } diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index e77b9abd68..fe057e3450 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -41,7 +41,7 @@ Pipe::SubmitTransfer(Transfer *transfer) status_t Pipe::CancelQueuedTransfers() { - TRACE_ERROR(("Pipe: cancelling transfers is not implemented!\n")); + TRACE_ERROR(("USB Pipe: cancelling transfers is not implemented!\n")); return B_ERROR; } @@ -120,7 +120,7 @@ InterruptPipe::QueueInterrupt(void *data, size_t dataLength, transfer->SetData((uint8 *)data, dataLength); transfer->SetCallback(callback, callbackCookie); - status_t result = SubmitTransfer(transfer); + status_t result = GetBusManager()->SubmitTransfer(transfer); if (result < B_OK) delete transfer; return result; @@ -151,7 +151,7 @@ BulkPipe::QueueBulk(void *data, size_t dataLength, usb_callback_func callback, transfer->SetData((uint8 *)data, dataLength); transfer->SetCallback(callback, callbackCookie); - status_t result = SubmitTransfer(transfer); + status_t result = GetBusManager()->SubmitTransfer(transfer); if (result < B_OK) delete transfer; return result; @@ -169,7 +169,7 @@ BulkPipe::QueueBulkV(iovec *vector, size_t vectorCount, transfer->SetVector(vector, vectorCount); transfer->SetCallback(callback, callbackCookie); - status_t result = SubmitTransfer(transfer); + status_t result = GetBusManager()->SubmitTransfer(transfer); if (result < B_OK) delete transfer; return result; @@ -261,7 +261,7 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value, size_t *actualLength) { 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) return B_NO_MORE_SEMS; @@ -272,11 +272,21 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value, return result; } - // the sem will be released in the callback after - // the result data was filled into the provided struct - acquire_sem(transferResult.notify_sem); - delete_sem(transferResult.notify_sem); + // the sem will be released in the callback after the result data was + // filled into the provided struct. use a 5 seconds timeout to avoid + // hanging applications. + 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) *actualLength = transferResult.actual_length; @@ -320,7 +330,7 @@ ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value, transfer->SetData((uint8 *)data, dataLength); transfer->SetCallback(callback, callbackCookie); - status_t result = SubmitTransfer(transfer); + status_t result = GetBusManager()->SubmitTransfer(transfer); if (result < B_OK) delete transfer; return result; diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index c5469fa429..1c8d4c72eb 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -13,6 +13,9 @@ #include "usb_p.h" #include "PhysicalMemoryAllocator.h" +#ifdef HAIKU_TARGET_PLATFORM_HAIKU +#include +#endif Stack::Stack() : fExploreThread(-1), @@ -23,10 +26,10 @@ Stack::Stack() fObjectArray(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) { - TRACE_ERROR(("usb stack: failed to create benaphore lock\n")); + if (benaphore_init(&fLock, "usb stack lock") < B_OK) { + TRACE_ERROR(("USB Stack: failed to create benaphore lock\n")); return; } @@ -37,7 +40,7 @@ Stack::Stack() fAllocator = new(std::nothrow) PhysicalMemoryAllocator("USB Stack Allocator", 8, B_PAGE_SIZE * 4, 64); 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; return; } @@ -47,10 +50,10 @@ Stack::Stack() char moduleName[B_PATH_NAME_LENGTH]; 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) { bufferSize = sizeof(moduleName); - TRACE(("usb stack: Found module %s\n", moduleName)); + TRACE(("USB Stack: found module %s\n", moduleName)); host_controller_info *module = NULL; if (get_module(moduleName, (module_info **)&module) != B_OK) @@ -59,16 +62,11 @@ Stack::Stack() if (module->add_to(this) < B_OK) continue; - TRACE(("usb stack: module %s successfully loaded\n", moduleName)); + TRACE(("USB Stack: module %s successfully loaded\n", moduleName)); } 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")); + TRACE_ERROR(("USB Stack: no bus managers available\n")); return; } @@ -99,7 +97,7 @@ Stack::~Stack() } delete fAllocator; -} +} status_t @@ -132,16 +130,22 @@ Stack::GetUSBID(Object *object) if (!Lock()) return 0; - if (fObjectIndex >= fObjectMaxCount) { - Unlock(); - return 0; + uint32 id = fObjectIndex; + uint32 tries = fObjectMaxCount; + 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++; - fObjectArray[id] = object; + TRACE_ERROR(("USB Stack: the stack did run out of usb_ids\n")); Unlock(); - - return (usb_id)id; + return 0; } @@ -152,7 +156,7 @@ Stack::PutUSBID(usb_id id) return; 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(); return; } @@ -169,14 +173,14 @@ Stack::GetObject(usb_id id) return NULL; 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(); return NULL; } Object *result = fObjectArray[id]; - Unlock(); + Unlock(); return result; } @@ -187,9 +191,6 @@ 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) @@ -197,7 +198,6 @@ Stack::ExploreThread(void *data) } stack->fFirstExploreDone = true; - benaphore_unlock(&stack->fExploreLock); snooze(USB_DELAY_HUB_EXPLORE); } @@ -228,7 +228,7 @@ Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, size_t size) status_t Stack::FreeChunk(void *logicalAddress, void *physicalAddress, size_t size) -{ +{ return fAllocator->Deallocate(size, logicalAddress, physicalAddress); } @@ -237,7 +237,7 @@ area_id Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size, 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; 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); 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; } @@ -253,7 +253,7 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size, status_t result = get_memory_map(logAddress, size, &physicalEntry, 1); if (result < B_OK) { 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; } @@ -264,7 +264,7 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size, if (physicalAddress) *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)); return area; } @@ -273,24 +273,33 @@ Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size, void 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; while (element) { - if ((added && element->notify_hooks.device_added != NULL) - || (!added && element->notify_hooks.device_removed != NULL)) { - status_t result = device->ReportDevice(element->support_descriptors, - element->support_descriptor_count, - &element->notify_hooks, &element->cookies, added); + status_t result = device->ReportDevice(element->support_descriptors, + element->support_descriptor_count, &element->notify_hooks, + &element->cookies, added); - if (result == B_OK) { - const char *name = element->driver_name; - if (element->republish_driver_name) - name = element->republish_driver_name; - int devFS = open("/dev", O_WRONLY); - write(devFS, name, strlen(name)); - close(devFS); - } + 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; + +#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; @@ -303,10 +312,39 @@ Stack::RegisterDriver(const char *driverName, const usb_support_descriptor *descriptors, 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; - if (!info) + if (!info) { + Unlock(); return B_NO_MEMORY; + } info->driver_name = strdup(driverName); info->republish_driver_name = strdup(republishDriverName); @@ -321,11 +359,6 @@ Stack::RegisterDriver(const char *driverName, info->cookies = NULL; info->link = NULL; - if (!Lock()) { - delete info; - return B_ERROR; - } - if (fDriverList) { usb_driver_info *element = fDriverList; while (element->link) @@ -343,16 +376,11 @@ Stack::RegisterDriver(const char *driverName, status_t 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; 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(); @@ -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_removed = hooks->device_removed; - benaphore_unlock(&fExploreLock); return B_OK; } @@ -380,16 +407,11 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks) status_t 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; 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(); @@ -401,7 +423,6 @@ Stack::UninstallNotify(const char *driverName) element->notify_hooks.device_added = NULL; element->notify_hooks.device_removed = NULL; - benaphore_unlock(&fExploreLock); return B_OK; } diff --git a/src/add-ons/kernel/bus_managers/usb/usb.cpp b/src/add-ons/kernel/bus_managers/usb/usb.cpp index 221ccdf730..89aee7eb6a 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb.cpp +++ b/src/add-ons/kernel/bus_managers/usb/usb.cpp @@ -43,7 +43,7 @@ bus_std_ops(int32 op, ...) } case B_MODULE_UNINIT: - TRACE(("usb_module: bus module: uninit\n")); + TRACE(("usb_module: uninit\n")); delete gUSBStack; gUSBStack = NULL; break; @@ -83,7 +83,7 @@ uninstall_notify(const char *driverName) const usb_device_descriptor * 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) return NULL; @@ -95,7 +95,7 @@ get_device_descriptor(usb_device device) const usb_configuration_info * 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) return NULL; @@ -107,7 +107,7 @@ get_nth_configuration(usb_device device, uint index) const usb_configuration_info * 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) return NULL; @@ -120,7 +120,7 @@ status_t set_configuration(usb_device device, 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; @@ -132,7 +132,7 @@ set_configuration(usb_device device, status_t 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; @@ -144,7 +144,7 @@ set_alt_interface(usb_device device, const usb_interface_info *interface) status_t 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); if (!object) return B_DEV_INVALID_PIPE; @@ -156,7 +156,7 @@ set_feature(usb_id handle, uint16 selector) status_t 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); if (!object) return B_DEV_INVALID_PIPE; @@ -168,7 +168,7 @@ clear_feature(usb_id handle, uint16 selector) status_t 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) return B_BAD_VALUE; @@ -184,7 +184,7 @@ status_t get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID, 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; @@ -198,7 +198,7 @@ status_t send_request(usb_device device, uint8 requestType, uint8 request, 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 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, 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); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) return B_DEV_INVALID_PIPE; @@ -227,7 +227,7 @@ status_t queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, 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); if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -241,7 +241,7 @@ status_t queue_bulk(usb_pipe pipe, void *data, size_t dataLength, 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); if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -255,7 +255,7 @@ status_t queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, 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); if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 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, 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); if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -286,7 +286,7 @@ status_t set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, 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); if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -299,7 +299,7 @@ set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, status_t 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); if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) return B_DEV_INVALID_PIPE; @@ -311,7 +311,7 @@ cancel_queued_transfers(usb_pipe pipe) status_t 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) { case 'DNAM': { 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 2e6181a388..03f36fc651 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -15,7 +15,6 @@ #include "BeOSCompatibility.h" -//#define TRACE_USB #ifdef TRACE_USB #define TRACE(x) dprintf x #define TRACE_ERROR(x) dprintf x @@ -135,7 +134,6 @@ static int32 ExploreThread(void *data); bool fStopThreads; benaphore fLock; - benaphore fExploreLock; PhysicalMemoryAllocator *fAllocator; uint32 fObjectIndex; @@ -149,7 +147,7 @@ static int32 ExploreThread(void *data); /* * This class manages a bus. It is created by the Stack object * after a host controller gives positive feedback on whether the hardware - * is found. + * is found. */ class BusManager { public: @@ -162,8 +160,11 @@ virtual status_t InitCheck(); void Unlock(); int8 AllocateAddress(); - Device *AllocateNewDevice(Hub *parent, + void FreeAddress(int8 address); + + Device *AllocateDevice(Hub *parent, usb_speed speed); + void FreeDevice(Device *device); virtual status_t Start(); virtual status_t Stop(); @@ -185,7 +186,10 @@ private: ControlPipe *_GetDefaultPipe(usb_speed); benaphore fLock; + bool fDeviceMap[128]; + int8 fDeviceIndex; + ControlPipe *fDefaultPipes[USB_SPEED_MAX + 1]; Hub *fRootHub; Object *fRootObject; @@ -410,6 +414,7 @@ virtual status_t GetDescriptor(uint8 descriptorType, void *data, size_t dataLength, size_t *actualLength); + int8 DeviceAddress() const { return fDeviceAddress; }; const usb_device_descriptor *DeviceDescriptor() const; const usb_configuration_info *Configuration() const; @@ -442,8 +447,6 @@ private: usb_configuration_info *fCurrentConfiguration; usb_speed fSpeed; int8 fDeviceAddress; - size_t fMaxPacketIn[16]; - size_t fMaxPacketOut[16]; ControlPipe *fDefaultPipe; }; @@ -454,6 +457,10 @@ public: usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed); +virtual ~Hub(); + + bool Lock(); + void Unlock(); virtual uint32 Type() { return USB_OBJECT_DEVICE | USB_OBJECT_HUB; }; @@ -480,6 +487,8 @@ virtual status_t BuildDeviceName(char *string, Device *device); private: + benaphore fLock; + InterruptPipe *fInterruptPipe; usb_hub_descriptor fHubDescriptor; diff --git a/src/add-ons/kernel/bus_managers/usb/usbspec_p.h b/src/add-ons/kernel/bus_managers/usb/usbspec_p.h index 7efcefabb0..4945b3745e 100644 --- a/src/add-ons/kernel/bus_managers/usb/usbspec_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usbspec_p.h @@ -41,11 +41,11 @@ struct memory_chunk struct usb_request_data { - uint8 RequestType; - uint8 Request; - uint16 Value; - uint16 Index; - uint16 Length; + uint8 RequestType; + uint8 Request; + uint16 Value; + uint16 Index; + uint16 Length; };