diff --git a/Kernel/Bus/USB/SysFSUSB.cpp b/Kernel/Bus/USB/SysFSUSB.cpp index 5ecc0c5be3..ba155f63a6 100644 --- a/Kernel/Bus/USB/SysFSUSB.cpp +++ b/Kernel/Bus/USB/SysFSUSB.cpp @@ -107,6 +107,12 @@ void SysFSUSBBusDirectory::unplug(USB::Device& deleted_device) device_node->m_list_node.remove(); } +SysFSUSBBusDirectory& SysFSUSBBusDirectory::the() +{ + VERIFY(s_procfs_usb_bus_directory); + return *s_procfs_usb_bus_directory; +} + UNMAP_AFTER_INIT SysFSUSBBusDirectory::SysFSUSBBusDirectory(SysFSBusDirectory& buses_directory) : SysFSDirectory("usb"sv, buses_directory) { diff --git a/Kernel/Bus/USB/SysFSUSB.h b/Kernel/Bus/USB/SysFSUSB.h index 6c59b6a2de..19ce26fd97 100644 --- a/Kernel/Bus/USB/SysFSUSB.h +++ b/Kernel/Bus/USB/SysFSUSB.h @@ -34,6 +34,8 @@ protected: class SysFSUSBBusDirectory final : public SysFSDirectory { public: static void initialize(); + static SysFSUSBBusDirectory& the(); + void plug(USB::Device&); void unplug(USB::Device&); diff --git a/Kernel/Bus/USB/USBHub.cpp b/Kernel/Bus/USB/USBHub.cpp index 1ba1728565..ffe1d8ff58 100644 --- a/Kernel/Bus/USB/USBHub.cpp +++ b/Kernel/Bus/USB/USBHub.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -152,6 +153,12 @@ KResult Hub::set_port_feature(u8 port, HubFeatureSelector feature_selector) return KSuccess; } +void Hub::remove_children_from_sysfs() +{ + for (auto& child : m_children) + SysFSUSBBusDirectory::the().unplug(child); +} + void Hub::check_for_port_updates() { for (u8 port_number = 1; port_number < m_hub_descriptor.number_of_downstream_ports + 1; ++port_number) { @@ -279,9 +286,12 @@ void Hub::check_for_port_updates() dbgln_if(USB_DEBUG, "USB Hub: Upgraded device at address {} to hub!", device->address()); - m_children.append(hub_or_error.release_value()); + auto hub = hub_or_error.release_value(); + m_children.append(hub); + SysFSUSBBusDirectory::the().plug(hub); } else { m_children.append(device); + SysFSUSBBusDirectory::the().plug(device); } } else { @@ -295,10 +305,17 @@ void Hub::check_for_port_updates() } } - if (device_to_remove) + if (device_to_remove) { m_children.remove(*device_to_remove); - else + SysFSUSBBusDirectory::the().unplug(*device_to_remove); + + if (device_to_remove->device_descriptor().device_class == USB_CLASS_HUB) { + auto* hub_child = static_cast(device_to_remove); + hub_child->remove_children_from_sysfs(); + } + } else { dbgln_if(USB_DEBUG, "USB Hub: No child set up on port {}, ignoring detachment.", port_number); + } } } } diff --git a/Kernel/Bus/USB/USBHub.h b/Kernel/Bus/USB/USBHub.h index 5ba10c9b0c..80ea4f6ba9 100644 --- a/Kernel/Bus/USB/USBHub.h +++ b/Kernel/Bus/USB/USBHub.h @@ -102,6 +102,8 @@ private: USBHubDescriptor m_hub_descriptor; Device::List m_children; + + void remove_children_from_sysfs(); }; }