diff options
| -rw-r--r-- | kapi/kapi/devices/device.hpp | 18 | ||||
| -rw-r--r-- | kapi/kapi/devices/interface_registry.hpp | 29 | ||||
| -rw-r--r-- | kernel/kapi/devices/device.cpp | 15 | ||||
| -rw-r--r-- | kernel/kapi/devices/interface_registry.cpp | 23 | ||||
| -rw-r--r-- | kernel/kapi/devices/interface_registry.tests.cpp | 10 | ||||
| -rw-r--r-- | kernel/kernel/filesystem/device_inode.cpp | 24 |
6 files changed, 69 insertions, 50 deletions
diff --git a/kapi/kapi/devices/device.hpp b/kapi/kapi/devices/device.hpp index c26a4701..2c799d5d 100644 --- a/kapi/kapi/devices/device.hpp +++ b/kapi/kapi/devices/device.hpp @@ -40,22 +40,28 @@ namespace kapi::devices */ virtual ~device() = default; + [[nodiscard]] auto as(interface interface) noexcept -> void *; + + [[nodiscard]] auto as(interface interface) const noexcept -> void const *; + template<typename InterfaceType> - [[nodiscard]] constexpr auto as() -> InterfaceType * + [[nodiscard]] auto as() -> InterfaceType * { - return static_cast<InterfaceType *>(query_interface(InterfaceType::id)); + return static_cast<InterfaceType *>(as(InterfaceType::id)); } template<typename InterfaceType> - [[nodiscard]] constexpr auto as() const noexcept -> InterfaceType const * + [[nodiscard]] auto as() const noexcept -> InterfaceType const * { - return static_cast<InterfaceType const *>(const_cast<device *>(this)->query_interface(InterfaceType::id)); + return static_cast<InterfaceType const *>(as(InterfaceType::id)); } + [[nodiscard]] auto is_a(interface interface) const noexcept -> bool; + template<typename InterfaceType> - [[nodiscard]] constexpr auto is_a() const noexcept -> bool + [[nodiscard]] auto is_a() const noexcept -> bool { - return const_cast<device *>(this)->query_interface(InterfaceType::id) != nullptr; + return is_a(InterfaceType::id); } /** diff --git a/kapi/kapi/devices/interface_registry.hpp b/kapi/kapi/devices/interface_registry.hpp index b1dfa08e..155a23cd 100644 --- a/kapi/kapi/devices/interface_registry.hpp +++ b/kapi/kapi/devices/interface_registry.hpp @@ -114,29 +114,36 @@ namespace kapi::devices //! @param interface The interface for which to get the implementing devices. [[nodiscard]] auto all(interface interface) const -> kstd::vector<entry>; - //! Find an entry for a given interface on a device with the given name. + //! Attempt to resolve a given device, by name, to a given interface implementation //! //! @param interface The interface to look for. //! @param name The stable name of the device to look for. - //! @return An entry representing the published interface if it exists, an error otherwise. - [[nodiscard]] auto find(interface interface, std::string_view name) const -> kstd::result<entry>; + [[nodiscard]] auto resolve(interface interface, std::string_view name) -> void *; - //! Find an entry for a given interface on a specific device. + //! Attempt to resolve a given device to a given interface implementation //! //! @param interface The interface to look for. //! @param device The device to look for. - //! @return An entry representing the published interface if it exists, an error otherwise. - [[nodiscard]] auto find(interface interface, device const & device) const -> kstd::result<entry>; + [[nodiscard]] auto resolve(interface interface, device & device) -> void *; - //! Find an entry for a given interface on a device with the given name. + //! Attempt to resolve a given device, by name, to a given interface implementation //! - //! @tparam Interface The interface type to look for. + //! @tparam Interface The interface to look for. //! @param name The stable name of the device to look for. - //! @return An entry representing the published interface if it exists, an error otherwise. template<typename Interface> - [[nodiscard]] auto find(std::string_view name) const -> kstd::result<entry> + [[nodiscard]] auto resolve(std::string_view name) -> Interface * { - return find(Interface::id, name); + return static_cast<Interface *>(resolve(Interface::id, name)); + } + + //! Attempt to resolve a given device to a given interface implementation + //! + //! @tparam Interface The interface to look for. + //! @param device The device to look for. + template<typename Interface> + [[nodiscard]] auto resolve(device & device) -> Interface * + { + return static_cast<Interface *>(resolve(Interface::id, device)); } private: diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp index 4c63f6a4..3eb9aaac 100644 --- a/kernel/kapi/devices/device.cpp +++ b/kernel/kapi/devices/device.cpp @@ -12,6 +12,21 @@ namespace kapi::devices : m_name(name) {} + auto device::as(interface interface) noexcept -> void * + { + return query_interface(interface); + } + + auto device::as(interface interface) const noexcept -> void const * + { + return const_cast<device *>(this)->query_interface(interface); + } + + auto device::is_a(interface interface) const noexcept -> bool + { + return const_cast<device *>(this)->query_interface(interface) != nullptr; + } + auto device::name() const -> kstd::string const & { return m_name; diff --git a/kernel/kapi/devices/interface_registry.cpp b/kernel/kapi/devices/interface_registry.cpp index d959c857..2ff42aa3 100644 --- a/kernel/kapi/devices/interface_registry.cpp +++ b/kernel/kapi/devices/interface_registry.cpp @@ -85,30 +85,41 @@ namespace kapi::devices return filtered; } - auto interface_registry::find(interface interface, std::string_view name) const -> kstd::result<entry> + auto interface_registry::resolve(interface interface, std::string_view name) -> void * { auto found = std::ranges::find_if( m_entries, [&](auto e) { return e.interface() == interface && e.name() == name && e.device(); }); + if (found == m_entries.cend()) { - return kstd::failure(make_error_code(kstd::errc::no_such_device)); + return nullptr; + } + else if (auto device = found->device()) + { + return resolve(interface, *device); } - return *found; + return nullptr; } - auto interface_registry::find(interface interface, device const & device) const -> kstd::result<entry> + auto interface_registry::resolve(interface interface, device & device) -> void * { + if (auto by_device = device.as(interface)) + { + return by_device; + } + auto found = std::ranges::find_if(m_entries, [&](auto e) { auto locked_device = e.device(); return e.interface() == interface && locked_device && locked_device.get() == &device; }); + if (found == m_entries.cend()) { - return kstd::failure(make_error_code(kstd::errc::no_such_device)); + return nullptr; } - return *found; + return found->implementation(); } } // namespace kapi::devices diff --git a/kernel/kapi/devices/interface_registry.tests.cpp b/kernel/kapi/devices/interface_registry.tests.cpp index 100954ea..f82e867e 100644 --- a/kernel/kapi/devices/interface_registry.tests.cpp +++ b/kernel/kapi/devices/interface_registry.tests.cpp @@ -133,23 +133,23 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry] THEN("find finds the published capability by name") { - REQUIRE(registry.find<probe_device>("probe0")); + REQUIRE(registry.resolve<probe_device>("probe0")); } THEN("find for an unpublished capability does not find a device") { - REQUIRE_FALSE(registry.find<const_device>("probe0")); + REQUIRE_FALSE(registry.resolve<const_device>("probe0")); } THEN("find for an unpublished device does not find a device") { - REQUIRE_FALSE(registry.find<probe_device>("probe1")); + REQUIRE_FALSE(registry.resolve<probe_device>("probe1")); } THEN("withdrawing an interface for a device removes it from the registry") { registry.unpublish(*device, probe_device::id); - REQUIRE_FALSE(registry.find<probe_device>("probe0")); + REQUIRE_FALSE(registry.resolve<probe_device>("probe0")); } } @@ -165,7 +165,7 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry] THEN("find() no longer finds it") { - REQUIRE_FALSE(registry.find<probe_device>("probe0")); + REQUIRE_FALSE(registry.resolve<probe_device>("probe0")); } } } diff --git a/kernel/kernel/filesystem/device_inode.cpp b/kernel/kernel/filesystem/device_inode.cpp index 0ff8dce6..b898c5eb 100644 --- a/kernel/kernel/filesystem/device_inode.cpp +++ b/kernel/kernel/filesystem/device_inode.cpp @@ -16,26 +16,6 @@ #include <optional> -namespace -{ - template<typename Interface> - auto resolve(kapi::devices::device & device) -> Interface * - { - if (auto * direct = device.as<Interface>()) - { - return direct; - } - - auto found = kapi::devices::interface_registry::get().find(Interface::id, device); - if (!found) - { - return nullptr; - } - - return found->template as<Interface>(); - } -} // namespace - namespace kernel::filesystem { device_inode::device_inode(kstd::shared_ptr<kapi::devices::device> const & device) @@ -61,7 +41,7 @@ namespace kernel::filesystem auto device_inode::read(void * buffer, kstd::units::bytes offset, kstd::units::bytes size) const -> kstd::result<kstd::units::bytes> { - if (auto block_device = resolve<kapi::devices::block_device>(*m_device)) + if (auto block_device = kapi::devices::interface_registry::get().resolve<kapi::devices::block_device>(*m_device)) { return devices::block_device_utils::read(*block_device, buffer, offset, size); } @@ -72,7 +52,7 @@ namespace kernel::filesystem auto device_inode::write(void const * buffer, kstd::units::bytes offset, kstd::units::bytes size) -> kstd::result<kstd::units::bytes> { - if (auto block_device = resolve<kapi::devices::block_device>(*m_device)) + if (auto block_device = kapi::devices::interface_registry::get().resolve<kapi::devices::block_device>(*m_device)) { return devices::block_device_utils::write(*block_device, buffer, offset, size); } |
