aboutsummaryrefslogtreecommitdiff
path: root/kernel/kapi/devices/bus.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kapi/devices/bus.cpp')
-rw-r--r--kernel/kapi/devices/bus.cpp66
1 files changed, 66 insertions, 0 deletions
diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp
index dad90a15..d917eb96 100644
--- a/kernel/kapi/devices/bus.cpp
+++ b/kernel/kapi/devices/bus.cpp
@@ -9,6 +9,7 @@
#include <kstd/string.hpp>
#include <kstd/vector.hpp>
+#include <algorithm>
#include <span>
#include <utility>
@@ -23,6 +24,15 @@ namespace kapi::devices
, m_protocol{&protocol}
{}
+ bus::~bus()
+ {
+ auto children = m_devices;
+ for (auto const & child : children)
+ {
+ remove_child(*child);
+ }
+ }
+
auto bus::add_child(kstd::shared_ptr<device> child) -> void
{
child->set_parent(kstd::static_pointer_cast<bus>(shared_from_this()));
@@ -32,12 +42,35 @@ namespace kapi::devices
kapi::system::panic("[OS:DEV] Failed to register child device {}", child->name());
}
+ // TODO: lock bus
+
auto & attached = m_devices.emplace_back(std::move(child));
attached->set_state(state::present);
+ // TODO: unlock bus
+
driver_registry::get().device_attached(attached);
}
+ auto bus::remove_child(device & device) -> bool // NOLINT(misc-no-recursion)
+ {
+ // TODO: lock bus
+
+ auto found = std::ranges::find_if(m_devices, [&](auto const & d) { return d.get() == &device; });
+ if (!found)
+ {
+ return false;
+ }
+
+ auto lifeline = *found;
+ m_devices.erase(found);
+
+ // TODO: unlock bus
+
+ do_remove_child(*lifeline);
+ return true;
+ }
+
[[nodiscard]] auto bus::children() const -> std::span<kstd::shared_ptr<device> const>
{
return {m_devices.data(), m_devices.size()};
@@ -57,4 +90,37 @@ namespace kapi::devices
return device::query_facet(facet);
}
+ auto bus::do_remove_child(device & device) -> void // NOLINT(misc-no-recursion)
+ {
+ if (device.state() == state::removed)
+ {
+ return;
+ }
+
+ if (auto child_bus = device.facet<bus>())
+ {
+ auto grandchildren = kstd::vector<kstd::shared_ptr<kapi::devices::device>>{};
+ // TODO: lock child bus
+ // NOTE: this could be more efficient one vector::assign is implemented.
+ grandchildren = kstd::vector(child_bus->m_devices.begin(), child_bus->m_devices.end());
+ // TODO: unlock child bus
+
+ for (auto & grandchild : grandchildren)
+ {
+ child_bus->remove_child(*grandchild);
+ }
+ }
+
+ device.set_state(state::removed);
+
+ if (auto bound_driver = device.bound_driver())
+ {
+ bound_driver->unbind(device);
+ }
+
+ facet_registry::get().withdraw_all_for(device);
+ device_registry::get().remove(device);
+ device.set_parent(kstd::weak_ptr<bus>{});
+ }
+
} // namespace kapi::devices \ No newline at end of file