diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-16 14:16:33 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-16 14:16:33 +0200 |
| commit | a6166befa7421be233ece97e184139870bbc0af7 (patch) | |
| tree | 905c5a876911d0ec2bf7270f6ba0e75b8680eb7c /kernel/kapi/devices/interface_registry.cpp | |
| parent | d04cb84074b6cdb3d36f5d5e1e22dbc9294724f7 (diff) | |
| download | kernel-a6166befa7421be233ece97e184139870bbc0af7.tar.xz kernel-a6166befa7421be233ece97e184139870bbc0af7.zip | |
kapi: introduce device interfaces
Diffstat (limited to 'kernel/kapi/devices/interface_registry.cpp')
| -rw-r--r-- | kernel/kapi/devices/interface_registry.cpp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/kernel/kapi/devices/interface_registry.cpp b/kernel/kapi/devices/interface_registry.cpp new file mode 100644 index 00000000..8882e8db --- /dev/null +++ b/kernel/kapi/devices/interface_registry.cpp @@ -0,0 +1,108 @@ +#include <kapi/devices/interface_registry.hpp> + +#include <kapi/devices.hpp> +#include <kapi/system.hpp> +#include <kapi/test_support/devices.hpp> + +#include <kstd/memory.hpp> +#include <kstd/result.hpp> +#include <kstd/string.hpp> +#include <kstd/system_error.hpp> +#include <kstd/vector.hpp> + +#include <algorithm> +#include <optional> +#include <string_view> +#include <utility> + +namespace kapi::devices +{ + + namespace + { + constinit auto static registry = std::optional<interface_registry>{}; + } + + auto interface_registry::init() -> void + { + if (registry.has_value()) + { + system::panic("[kernel] Device interface registry has already been initialized."); + } + + registry.emplace(); + } + + auto interface_registry::get() -> interface_registry & + { + if (!registry) + { + system::panic("[kernel] Device interface registry has not been initialized."); + } + + return *registry; + } + + auto interface_registry::do_publish(kstd::shared_ptr<device> device, kstd::string name, interface interface, + void * implementation) -> kstd::result<void> + { + erase_if(m_entries, [interface](auto e) { return e.interface() == interface && e.device().expired(); }); + + if (!device || !implementation || name.empty()) + { + return kstd::failure(make_error_code(kstd::errc::invalid_argument)); + } + + auto published = std::ranges::any_of(m_entries, [&](auto const & entry) { + return entry.interface() == interface && entry.device().lock().get() == device.get(); + }); + + if (published) + { + return kstd::failure(make_error_code(kstd::errc::file_exists)); + } + + m_entries.emplace_back(device, std::move(name), interface, implementation); + + return kstd::success(); + } + + auto interface_registry::unpublish(device const & device, interface interface) -> void + { + erase_if(m_entries, [&](auto e) { + auto locked_device = e.device().lock(); + return e.interface() == interface && locked_device && locked_device.get() == &device; + }); + } + + auto interface_registry::all(interface interface) const -> kstd::vector<entry> + { + auto filtered = m_entries; + erase_if(filtered, [&](auto e) { + auto locked_device = e.device().lock(); + return !(e.interface() == interface && locked_device); + }); + return filtered; + } + + auto interface_registry::find(interface interface, std::string_view name) const -> kstd::result<entry> + { + auto found = std::ranges::find_if( + m_entries, [&](auto e) { return e.interface() == interface && e.name() == name && e.device().lock(); }); + if (found == m_entries.cend()) + { + return kstd::failure(make_error_code(kstd::errc::no_such_device)); + } + + return *found; + } + +} // namespace kapi::devices + +namespace kapi::test_support::devices +{ + auto deinit_interface_registry() -> void + { + kapi::devices::registry.reset(); + } +} // namespace kapi::test_support::devices |
