diff --git a/kernel/include/kernel/USB/Device.h b/kernel/include/kernel/USB/Device.h index 55abe030..4816a132 100644 --- a/kernel/include/kernel/USB/Device.h +++ b/kernel/include/kernel/USB/Device.h @@ -61,6 +61,9 @@ namespace Kernel {} virtual ~USBDevice() = default; + // Class drivers have to be destroyed before derived class destructor is called + void destroy() { m_class_drivers.clear(); } + BAN::ErrorOr initialize(); const BAN::Vector& configurations() { return m_descriptor.configurations; } diff --git a/kernel/include/kernel/USB/XHCI/Controller.h b/kernel/include/kernel/USB/XHCI/Controller.h index 2d8ba391..df73c4f0 100644 --- a/kernel/include/kernel/USB/XHCI/Controller.h +++ b/kernel/include/kernel/USB/XHCI/Controller.h @@ -46,7 +46,8 @@ namespace Kernel void port_updater_task(); - BAN::ErrorOr initialize_slot(int port_index); + BAN::ErrorOr initialize_slot(int port_index); + void deinitialize_slot(uint8_t slot_id); BAN::ErrorOr send_command(const XHCI::TRB&); void advance_command_enqueue(); diff --git a/kernel/kernel/USB/XHCI/Controller.cpp b/kernel/kernel/USB/XHCI/Controller.cpp index 3b77e071..d765b621 100644 --- a/kernel/kernel/USB/XHCI/Controller.cpp +++ b/kernel/kernel/USB/XHCI/Controller.cpp @@ -336,10 +336,9 @@ namespace Kernel if (!(op_port.portsc & XHCI::PORTSC::CCS)) { - // if device detached, clear the port if (my_port.slot_id != 0) { - m_slots[my_port.slot_id - 1].clear(); + deinitialize_slot(my_port.slot_id); my_port.slot_id = 0; } continue; @@ -364,7 +363,9 @@ namespace Kernel continue; } - if (auto ret = initialize_slot(i); ret.is_error()) + if (auto ret = initialize_slot(i); !ret.is_error()) + my_port.slot_id = ret.value(); + else { dwarnln("Could not initialize USB {H}.{H} device: {}", my_port.revision_major, @@ -376,7 +377,7 @@ namespace Kernel } } - BAN::ErrorOr XHCIController::initialize_slot(int port_index) + BAN::ErrorOr XHCIController::initialize_slot(int port_index) { auto& my_port = m_ports[port_index]; @@ -406,7 +407,15 @@ namespace Kernel dprintln_if(DEBUG_XHCI, "device on slot {} initialized", slot_id); - return {}; + return slot_id; + } + + void XHCIController::deinitialize_slot(uint8_t slot_id) + { + ASSERT(0 < slot_id && slot_id <= m_slots.size()); + ASSERT(m_slots[slot_id - 1]); + m_slots[slot_id - 1]->destroy(); + m_slots[slot_id - 1].clear(); } BAN::ErrorOr XHCIController::reset_controller()