#include #include #include #include #include #include #include namespace kapi::devices { namespace { auto resume_subtree(device & node) -> void; // NOLINTNEXTLINE(misc-no-recursion) auto suspend_subtree(device & node) -> kstd::result { auto suspended_children = kstd::vector>{}; if (auto as_bus = node.facet()) { for (auto const & child : as_bus->children()) { auto result = suspend_subtree(*child); if (!result) { for (auto const & already_suspended : std::views::reverse(suspended_children)) { resume_subtree(*already_suspended); } return result; } suspended_children.push_back(child); } } if (auto driver = node.bound_driver()) { auto result = driver->suspend(node); if (!result) { for (auto const & already_suspended : std::views::reverse(suspended_children)) { resume_subtree(*already_suspended); } return result; } } return kstd::success(); } // NOLINTNEXTLINE(misc-no-recursion) auto resume_subtree(device & node) -> void { if (auto driver = node.bound_driver()) { auto result = driver->resume(node); if (!result) { kstd::println(kstd::print_sink::stderr, "[OS:PM] failed to resume device '{}': {}", node.name(), result.error().message()); } } if (auto as_bus = node.facet()) { for (auto const & child : as_bus->children()) { resume_subtree(*child); } } } } // namespace auto suspend_tree(bus & root) -> kstd::result { return suspend_subtree(root); } auto resume_tree(bus & root) -> void { resume_subtree(root); } } // namespace kapi::devices