From 838251124ccc1b6d6de301f4828a9077c7f6ebfa Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 16 Sep 2021 13:15:34 -0400 Subject: [PATCH] USB: Rework Device deinitialization and destruction. * Destroy interfaces and endpoints before deleting the default pipe, as all of these may actually use the default pipe at any time while they are alive. * Remove the default pipe and then ourselves from the stack before deleting the default pipe, as it also may be used at any time. May help with some of the open tickets about USB stack KDLs. --- .../kernel/bus_managers/usb/Device.cpp | 36 +++++++++++++++---- .../kernel/bus_managers/usb/usb_private.h | 3 ++ 2 files changed, 32 insertions(+), 7 deletions(-) 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;