From 099dab075320a7098ed48e385ceb810534befb2c Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 27 Sep 2006 19:09:01 +0000 Subject: [PATCH] * Fixed device creation. No pipes for device endpoints are created and the initial handle of all endpoints is 0. * The endpoint pipes of a configuration are now created when the configuration is actually set. * Implemented an Unconfigure() function that tears down any pipe that was created for that configuration. * Implemented the device destructor that unconfigures and frees the resources allocated for the various usb_*_info structures. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18952 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/bus_managers/usb/Device.cpp | 168 +++++++++++++----- src/add-ons/kernel/bus_managers/usb/usb_p.h | 3 +- 2 files changed, 123 insertions(+), 48 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index 5eedfdebe7..8e5fe15c38 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -18,19 +18,10 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, fConfigurations(NULL), fCurrentConfiguration(NULL), fSpeed(speed), - fDeviceAddress(deviceAddress), - fLock(-1) + fDeviceAddress(deviceAddress) { TRACE(("USB Device: new device\n")); - fLock = create_sem(1, "USB Device Lock"); - if (fLock < B_OK) { - TRACE_ERROR(("USB Device: could not create locking semaphore\n")); - return; - } - - set_sem_owner(fLock, B_SYSTEM_TEAM); - fDefaultPipe = new(std::nothrow) ControlPipe(this, deviceAddress, 0, fSpeed, fDeviceDescriptor.max_packet_size_0); if (!fDefaultPipe) { @@ -181,42 +172,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, usb_endpoint_info *endpointInfo = ¤tInterface->endpoint[currentInterface->endpoint_count - 1]; endpointInfo->descr = endpointDescriptor; - - Pipe *endpoint = NULL; - switch (endpointDescriptor->attributes & 0x03) { - case 0x00: /* Control Endpoint */ - endpoint = new(std::nothrow) ControlPipe(this, - fDeviceAddress, - endpointDescriptor->endpoint_address & 0x0f, - fSpeed, endpointDescriptor->max_packet_size); - break; - - case 0x01: /* Isochronous Endpoint */ - endpoint = new(std::nothrow) IsochronousPipe(this, - fDeviceAddress, - endpointDescriptor->endpoint_address & 0x0f, - (endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, - fSpeed, endpointDescriptor->max_packet_size); - break; - - case 0x02: /* Bulk Endpoint */ - endpoint = new(std::nothrow) BulkPipe(this, - fDeviceAddress, - endpointDescriptor->endpoint_address & 0x0f, - (endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, - fSpeed, endpointDescriptor->max_packet_size); - break; - - case 0x03: /* Interrupt Endpoint */ - endpoint = new(std::nothrow) InterruptPipe(this, - fDeviceAddress, - endpointDescriptor->endpoint_address & 0x0f, - (endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, - fSpeed, endpointDescriptor->max_packet_size); - break; - } - - endpointInfo->handle = endpoint->USBID(); + endpointInfo->handle = 0; break; } @@ -257,6 +213,37 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, } +Device::~Device() +{ + // Destroy open endpoints. Do not send a device request to unconfigure + // though, since we may be deleted because the device was unplugged + // already. + Unconfigure(false); + + // Free all allocated resources + for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) { + usb_configuration_info *configuration = &fConfigurations[i]; + for (size_t j = 0; j < configuration->interface_count; j++) { + usb_interface_list *interfaceList = configuration->interface; + for (size_t k = 0; k < interfaceList->alt_count; k++) { + usb_interface_info *interface = &interfaceList->alt[k]; + delete (Interface *)GetStack()->GetObject(interface->handle); + free(interface->endpoint); + free(interface->generic); + } + + free(interfaceList->alt); + } + + free(configuration->interface); + free(configuration->descr); + } + + free(fConfigurations); + delete fDefaultPipe; +} + + status_t Device::InitCheck() { @@ -303,8 +290,12 @@ Device::ConfigurationAt(uint8 index) const status_t Device::SetConfiguration(const usb_configuration_info *configuration) { + if (!configuration) + return Unconfigure(true); + for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) { - if (configuration == &fConfigurations[i]) + if (configuration->descr->configuration_value + == fConfigurations[i].descr->configuration_value) return SetConfigurationAt(i); } @@ -317,7 +308,13 @@ Device::SetConfigurationAt(uint8 index) { if (index >= fDeviceDescriptor.num_configurations) return B_BAD_VALUE; + if (&fConfigurations[index] == fCurrentConfiguration) + return B_OK; + // Destroy our open endpoints + Unconfigure(false); + + // Tell the device to set the configuration status_t result = fDefaultPipe->SendRequest( USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type USB_REQUEST_SET_CONFIGURATION, // request @@ -334,12 +331,89 @@ Device::SetConfigurationAt(uint8 index) // Set current configuration fCurrentConfiguration = &fConfigurations[index]; + // Initialize all the endpoints that are now active + 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]; + Pipe *pipe = NULL; + + switch (endpoint->descr->attributes & 0x03) { + case 0x00: /* Control Endpoint */ + pipe = new(std::nothrow) ControlPipe(this, fDeviceAddress, + endpoint->descr->endpoint_address & 0x0f, fSpeed, + endpoint->descr->max_packet_size); + break; + + case 0x01: /* Isochronous Endpoint */ + pipe = new(std::nothrow) IsochronousPipe(this, fDeviceAddress, + endpoint->descr->endpoint_address & 0x0f, + (endpoint->descr->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, + fSpeed, endpoint->descr->max_packet_size); + break; + + case 0x02: /* Bulk Endpoint */ + pipe = new(std::nothrow) BulkPipe(this, fDeviceAddress, + endpoint->descr->endpoint_address & 0x0f, + (endpoint->descr->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, + fSpeed, endpoint->descr->max_packet_size); + break; + + case 0x03: /* Interrupt Endpoint */ + pipe = new(std::nothrow) InterruptPipe(this, fDeviceAddress, + endpoint->descr->endpoint_address & 0x0f, + (endpoint->descr->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, + fSpeed, endpoint->descr->max_packet_size); + break; + } + + endpoint->handle = pipe->USBID(); + } + // Wait some for the configuration being finished snooze(USB_DELAY_SET_CONFIGURATION); return B_OK; } +status_t +Device::Unconfigure(bool atDeviceLevel) +{ + // if we only want to destroy our open pipes before setting + // another configuration unconfigure will be called with + // atDevice = false. otherwise we explicitly want to unconfigure + // the device and have to send it the corresponding request. + if (atDeviceLevel) { + status_t result = fDefaultPipe->SendRequest( + USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type + USB_REQUEST_SET_CONFIGURATION, // request + 0, // value + 0, // index + 0, // length + NULL, // buffer + 0, // buffer length + NULL); // actual length + + if (result < B_OK) + return result; + + snooze(USB_DELAY_SET_CONFIGURATION); + } + + if (!fCurrentConfiguration) + return B_OK; + + 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]; + delete (Pipe *)GetStack()->GetObject(endpoint->handle); + endpoint->handle = 0; + } + + fCurrentConfiguration = NULL; + return B_OK; +} + + const usb_device_descriptor * Device::DeviceDescriptor() const { 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 ebd66ffc64..71d1f4d9d4 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -392,6 +392,7 @@ public: usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed); +virtual ~Device(); status_t InitCheck(); @@ -410,6 +411,7 @@ virtual status_t GetDescriptor(uint8 descriptorType, const usb_configuration_info *ConfigurationAt(uint8 index) const; status_t SetConfiguration(const usb_configuration_info *configuration); status_t SetConfigurationAt(uint8 index); + status_t Unconfigure(bool atDeviceLevel); virtual status_t ReportDevice( usb_support_descriptor *supportDescriptors, @@ -437,7 +439,6 @@ private: int8 fDeviceAddress; size_t fMaxPacketIn[16]; size_t fMaxPacketOut[16]; - sem_id fLock; ControlPipe *fDefaultPipe; };