diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index e6ddd6f508..9ffe1dcfb6 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -329,6 +329,34 @@ Device::~Device() // Unset fInitOK to indicate we are tearing down. fInitOK = false; + // 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); + + // Destroy all Interfaces in the Configurations hierarchy. + for (int32 i = 0; fConfigurations != NULL + && i < fDeviceDescriptor.num_configurations; i++) { + usb_configuration_info* configuration = &fConfigurations[i]; + if (configuration == NULL || configuration->interface == NULL) + continue; + + for (size_t j = 0; j < configuration->interface_count; j++) { + usb_interface_list* interfaceList = &configuration->interface[j]; + if (interfaceList->alt == NULL) + continue; + + for (size_t k = 0; k < interfaceList->alt_count; k++) { + usb_interface_info* interface = &interfaceList->alt[k]; + delete (Interface*)GetStack()->GetObject(interface->handle); + interface->handle = 0; + } + } + } + + // Remove ourselves from the stack before deleting public structures. + if (fDefaultPipe != NULL) + fDefaultPipe->PutUSBID(); + PutUSBID(); delete fDefaultPipe; if (fConfigurations == NULL) { @@ -336,12 +364,7 @@ Device::~Device() return; } - // 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 + // Free the Configurations hierarchy. for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) { usb_configuration_info* configuration = &fConfigurations[i]; if (configuration == NULL) @@ -358,7 +381,6 @@ Device::~Device() 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); } diff --git a/src/add-ons/kernel/bus_managers/usb/usb_private.h b/src/add-ons/kernel/bus_managers/usb/usb_private.h index 314216c60d..2d7d9a53ab 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_private.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_private.h @@ -347,6 +347,9 @@ virtual status_t SetFeature(uint16 selector); virtual status_t ClearFeature(uint16 selector); virtual status_t GetStatus(uint16 *status); +protected: + friend class Device; + private: int8 fDeviceAddress; uint8 fEndpointAddress;