diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 02:27:59 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 02:27:59 +0200 |
| commit | 59f54d012c71e782966e9d083f1ee9459fd3fd70 (patch) | |
| tree | fa1c34396c3b9e50c6128fa1b8e580abd4e44b3d | |
| parent | b486b794abaf35b0b2376662173eb07549252cfc (diff) | |
| download | kernel-59f54d012c71e782966e9d083f1ee9459fd3fd70.tar.xz kernel-59f54d012c71e782966e9d083f1ee9459fd3fd70.zip | |
chore: replace "interface" with "facet"
49 files changed, 893 insertions, 882 deletions
diff --git a/arch/x86_64/arch/bus/isa.cpp b/arch/x86_64/arch/bus/isa.cpp index ee195519..8e17c186 100644 --- a/arch/x86_64/arch/bus/isa.cpp +++ b/arch/x86_64/arch/bus/isa.cpp @@ -14,6 +14,8 @@ namespace arch::bus { struct isa_protocol final : kapi::devices::bus_protocol { + constexpr auto static id = kapi::capabilities::facet_id{"isa_protocol"}; + auto enumerate(kapi::devices::bus &) -> void override { // NOTE: ISA does not support enumeration, but we need to fulfill the interface. @@ -22,8 +24,8 @@ namespace arch::bus [[nodiscard]] auto match(kapi::devices::device const & device, kapi::devices::driver const & driver) const -> kstd::result<std::uint32_t> override { - auto device_signature = device.as<isa_signature>(); - auto driver_claim = driver.as<isa_claim>(); + auto device_signature = device.facet<isa_signature>(); + auto driver_claim = driver.facet<isa_claim>(); if (!device_signature || !driver_claim) { @@ -44,9 +46,14 @@ namespace arch::bus : kapi::devices::bus{"isa"} {} - auto isa::protocol() -> kapi::devices::bus_protocol * + auto isa::query_facet(kapi::capabilities::facet_id id) -> void * { - return &protocol_instance; + if (id == isa_protocol::id || id == kapi::devices::bus_protocol::id) + { + return &protocol_instance; + } + + return bus::query_facet(id); } } // namespace arch::bus
\ No newline at end of file diff --git a/arch/x86_64/arch/bus/isa.hpp b/arch/x86_64/arch/bus/isa.hpp index 87832c3c..db85f3f7 100644 --- a/arch/x86_64/arch/bus/isa.hpp +++ b/arch/x86_64/arch/bus/isa.hpp @@ -11,11 +11,11 @@ namespace arch::bus { - //! The signature interface used to identify ISA devices. + //! The signature facet used to identify ISA devices. struct isa_signature { - //! The ID of this interface. - constexpr auto static id = kapi::devices::interface_id{"isa_signature"}; + //! The ID of this facet. + constexpr auto static id = kapi::capabilities::facet_id{"isa_signature"}; //! Allow for correct destruction through base pointers. virtual ~isa_signature() = default; @@ -24,11 +24,11 @@ namespace arch::bus [[nodiscard]] virtual auto isa_name() const -> std::string_view = 0; }; - //! The claim interface used to match ISA drivers. + //! The claim facet used to match ISA drivers. struct isa_claim { - //! The ID of this interface - constexpr auto static id = kapi::devices::interface_id{"isa_claim"}; + //! The ID of this facet + constexpr auto static id = kapi::capabilities::facet_id{"isa_claim"}; //! Allow for correct destruction through base pointers. virtual ~isa_claim() = default; @@ -43,7 +43,8 @@ namespace arch::bus //! Construct a default ISA bus. isa(); - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override; + private: + auto query_facet(kapi::capabilities::facet_id id) -> void * override; }; } // namespace arch::bus diff --git a/arch/x86_64/arch/devices/pit.cpp b/arch/x86_64/arch/devices/pit.cpp index 6a8e9974..bfd6e84b 100644 --- a/arch/x86_64/arch/devices/pit.cpp +++ b/arch/x86_64/arch/devices/pit.cpp @@ -18,14 +18,14 @@ namespace arch::devices return "pit"; } - auto pit::query_interface(kapi::devices::interface_id interface) -> void * + auto pit::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == arch::bus::isa_signature::id) + if (facet == arch::bus::isa_signature::id) { return static_cast<arch::bus::isa_signature *>(this); } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } } // namespace arch::devices
\ No newline at end of file diff --git a/arch/x86_64/arch/devices/pit.hpp b/arch/x86_64/arch/devices/pit.hpp index adb722ab..e2546d27 100644 --- a/arch/x86_64/arch/devices/pit.hpp +++ b/arch/x86_64/arch/devices/pit.hpp @@ -24,7 +24,7 @@ namespace arch::devices [[nodiscard]] auto isa_name() const -> std::string_view override; protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override; + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; }; } // namespace arch::devices diff --git a/arch/x86_64/arch/drivers/pit.cpp b/arch/x86_64/arch/drivers/pit.cpp index ea053319..650c4245 100644 --- a/arch/x86_64/arch/drivers/pit.cpp +++ b/arch/x86_64/arch/drivers/pit.cpp @@ -92,14 +92,14 @@ namespace arch::drivers return kapi::interrupts::status::handled; } - auto pit::query_interface(kapi::devices::interface_id interface) -> void * + auto pit::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == arch::bus::isa_claim::id) + if (facet == arch::bus::isa_claim::id) { return static_cast<arch::bus::isa_claim *>(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } } // namespace arch::drivers
\ No newline at end of file diff --git a/arch/x86_64/arch/drivers/pit.hpp b/arch/x86_64/arch/drivers/pit.hpp index e99bdf81..32ad7573 100644 --- a/arch/x86_64/arch/drivers/pit.hpp +++ b/arch/x86_64/arch/drivers/pit.hpp @@ -32,7 +32,7 @@ namespace arch::drivers [[nodiscard]] auto name() const noexcept -> std::string_view override; protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override; + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; private: struct data diff --git a/kapi/kapi/boot_modules/device.hpp b/kapi/kapi/boot_modules/device.hpp index a6aba9b0..74152306 100644 --- a/kapi/kapi/boot_modules/device.hpp +++ b/kapi/kapi/boot_modules/device.hpp @@ -14,13 +14,13 @@ namespace kapi::boot_modules //! @addtogroup kapi-boot_modules-kernel-defined //! @{ - //! The signature interface of a boot module device. + //! The signature facet of a boot module device. //! //! Boot module devices are "virtual" devices that get attached to the boot module bus. The purpose is to allow them //! to materialize as "real" devices, e.g. a ram disk, and have a driver bound to them. struct boot_module_signature { - constexpr auto static id = kapi::devices::interface_id{"boot_module_signature"}; + constexpr auto static id = kapi::capabilities::facet_id{"boot_module_signature"}; virtual ~boot_module_signature() = default; @@ -31,10 +31,10 @@ namespace kapi::boot_modules [[nodiscard]] auto virtual module() const -> kapi::boot_modules::module const & = 0; }; - //! The claim interface of a boot module driver. + //! The claim facet of a boot module driver. struct boot_module_claim { - constexpr auto static id = kapi::devices::interface_id{"boot_module_claim"}; + constexpr auto static id = kapi::capabilities::facet_id{"boot_module_claim"}; virtual ~boot_module_claim() = default; @@ -52,7 +52,7 @@ namespace kapi::boot_modules [[nodiscard]] auto module() const -> struct module const & override; protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override; + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; private: struct module m_module; diff --git a/kapi/kapi/capabilities/facet_id.hpp b/kapi/kapi/capabilities/facet_id.hpp new file mode 100644 index 00000000..0ceae747 --- /dev/null +++ b/kapi/kapi/capabilities/facet_id.hpp @@ -0,0 +1,36 @@ +#ifndef TEACHOS_KAPI_CAPABILITIES_FACET_ID_HPP +#define TEACHOS_KAPI_CAPABILITIES_FACET_ID_HPP + +// IWYU pragma: private + +#include <string_view> + +namespace kapi::capabilities +{ + + //! A tag to mark the presence of a given behavioral or data facet. + struct facet_id + { + //! Construct a new facet id. + //! + //! @param name The name of the facet. + constexpr explicit facet_id(std::string_view name) + : m_name{name} + {} + + //! Get the name of this facet. + [[nodiscard]] constexpr auto name() const noexcept -> std::string_view const & + { + return m_name; + } + + //! Check if this facet is equal to another one. + constexpr auto operator==(facet_id const &) const noexcept -> bool = default; + + private: + std::string_view m_name; + }; + +} // namespace kapi::capabilities + +#endif diff --git a/kapi/kapi/capabilities/interface_id.hpp b/kapi/kapi/capabilities/interface_id.hpp deleted file mode 100644 index 8e6870cc..00000000 --- a/kapi/kapi/capabilities/interface_id.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TEACHOS_KAPI_CAPABILITIES_INTERFACE_ID_HPP -#define TEACHOS_KAPI_CAPABILITIES_INTERFACE_ID_HPP - -// IWYU pragma: private - -#include <string_view> - -namespace kapi::capabilities -{ - - //! A tag to mark that a given devices provides a specific device capability interface. - struct interface_id - { - //! Construct a new interface with a given name. - constexpr explicit interface_id(std::string_view name) - : m_name{name} - {} - - //! Get the name of this interface. - [[nodiscard]] constexpr auto name() const noexcept -> std::string_view const & - { - return m_name; - } - - //! Check if this interface is equal to another one. - constexpr auto operator==(interface_id const &) const noexcept -> bool = default; - - private: - std::string_view m_name; - }; - -} // namespace kapi::capabilities - -#endif diff --git a/kapi/kapi/devices.hpp b/kapi/kapi/devices.hpp index 51f5129e..59fcc568 100644 --- a/kapi/kapi/devices.hpp +++ b/kapi/kapi/devices.hpp @@ -1,16 +1,16 @@ #ifndef TEACHOS_KAPI_DEVICES_HPP #define TEACHOS_KAPI_DEVICES_HPP -#include <kapi/devices/bus.hpp> // IWYU pragma: export -#include <kapi/devices/bus_protocol.hpp> // IWYU pragma: export -#include <kapi/devices/cpu.hpp> // IWYU pragma: export -#include <kapi/devices/device.hpp> // IWYU pragma: export -#include <kapi/devices/device_registry.hpp> // IWYU pragma: export -#include <kapi/devices/driver.hpp> // IWYU pragma: export -#include <kapi/devices/driver_registry.hpp> // IWYU pragma: export -#include <kapi/devices/error.hpp> // IWYU pragma: export -#include <kapi/devices/interface_id.hpp> // IWYU pragma: export -#include <kapi/devices/interface_registry.hpp> // IWYU pragma: export +#include <kapi/capabilities/facet_id.hpp> // IWYU pragma: export +#include <kapi/devices/bus.hpp> // IWYU pragma: export +#include <kapi/devices/bus_protocol.hpp> // IWYU pragma: export +#include <kapi/devices/cpu.hpp> // IWYU pragma: export +#include <kapi/devices/device.hpp> // IWYU pragma: export +#include <kapi/devices/device_registry.hpp> // IWYU pragma: export +#include <kapi/devices/driver.hpp> // IWYU pragma: export +#include <kapi/devices/driver_registry.hpp> // IWYU pragma: export +#include <kapi/devices/error.hpp> // IWYU pragma: export +#include <kapi/devices/facet_registry.hpp> // IWYU pragma: export #include <kstd/memory.hpp> #include <kstd/result.hpp> @@ -34,28 +34,27 @@ namespace kapi::devices //! @return a shared pointer to the root bus. auto get_root_bus() -> kstd::shared_ptr<bus>; - //! Publish the fact that a given device implements a given interface. + //! Publish the fact that a device supports a specific facet. //! - //! @tparam Interface The interface type implemented by the given device. - //! @param device The device to publish the interface for. + //! @tparam Facet The facet type provided by the device. + //! @param device The device to publish the facet for. //! @param name A stable name for the device. - template<typename Interface> - auto publish_interface(kstd::shared_ptr<device> device, kstd::string name) -> kstd::result<void> + template<typename Facet> + auto publish_facet(kstd::shared_ptr<device> device, kstd::string name) -> kstd::result<void> { - return interface_registry::get().publish<Interface>(device, std::move(name)); + return facet_registry::get().publish<Facet>(device, std::move(name)); } - //! Publish the fact that a given device implements a given interface. + //! Publish the fact that a given device provides a given facet. //! - //! @tparam Interface The interface type implemented by the given device. - //! @param device The device to publish the interface for. + //! @tparam Facet The facet type provided by the given device. + //! @param device The device to publish the facet for. //! @param name A stable name for the device. - //! @param implementation The implementation of the interface for the device. - template<typename Interface> - auto publish_interface(kstd::shared_ptr<device> device, kstd::string name, Interface * implementation) - -> kstd::result<void> + //! @param implementation The implementation of the facet for the device. + template<typename Facet> + auto publish_facet(kstd::shared_ptr<device> device, kstd::string name, Facet * implementation) -> kstd::result<void> { - return interface_registry::get().publish(device, std::move(name), implementation); + return facet_registry::get().publish(device, std::move(name), implementation); } //! @} diff --git a/kapi/kapi/devices/bus.hpp b/kapi/kapi/devices/bus.hpp index 2a306031..6c42d1de 100644 --- a/kapi/kapi/devices/bus.hpp +++ b/kapi/kapi/devices/bus.hpp @@ -3,8 +3,8 @@ // IWYU pragma: private, include <kapi/devices.hpp> +#include <kapi/capabilities/facet_id.hpp> #include <kapi/devices/device.hpp> -#include <kapi/devices/interface_id.hpp> #include <kstd/memory.hpp> #include <kstd/print.hpp> @@ -23,7 +23,7 @@ namespace kapi::devices struct bus : device { //! The id of the bus facet. - constexpr auto static id = interface_id{"bus"}; + constexpr auto static id = kapi::capabilities::facet_id{"bus"}; //! Construct a bus with the given name. //! @@ -42,14 +42,14 @@ namespace kapi::devices //! @return A vector of all children attached to this bus. [[nodiscard]] auto children() const -> std::span<kstd::shared_ptr<device> const>; - //! Get this bus's protocol facet, if present. - //! - //! @return this bus's protocol facet if it has one, nullptr otherwise. - [[nodiscard]] virtual auto protocol() -> struct bus_protocol *; + // //! Get this bus's protocol facet, if present. + // //! + // //! @return this bus's protocol facet if it has one, nullptr otherwise. + // [[nodiscard]] virtual auto protocol() -> struct bus_protocol *; protected: //! All busses have the "bus" facet. - auto query_interface(interface_id interface) -> void * override; + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; private: kstd::vector<kstd::shared_ptr<device>> m_devices; diff --git a/kapi/kapi/devices/bus_protocol.hpp b/kapi/kapi/devices/bus_protocol.hpp index 2e4e6993..cc1f2e5b 100644 --- a/kapi/kapi/devices/bus_protocol.hpp +++ b/kapi/kapi/devices/bus_protocol.hpp @@ -3,6 +3,7 @@ // IWYU pragma: private, include <kapi/devices.hpp> +#include <kapi/capabilities/facet_id.hpp> #include <kapi/devices/bus.hpp> #include <kapi/devices/device.hpp> #include <kapi/devices/driver.hpp> @@ -20,6 +21,9 @@ namespace kapi::devices //! it a pure behavioral mixin. struct bus_protocol { + //! The id of the bus protocol facet. + constexpr auto static id = kapi::capabilities::facet_id{"bus_protocol"}; + //! Allow safe destruction through base pointers. virtual ~bus_protocol() = default; diff --git a/kapi/kapi/devices/device.hpp b/kapi/kapi/devices/device.hpp index 50fc10b6..71856279 100644 --- a/kapi/kapi/devices/device.hpp +++ b/kapi/kapi/devices/device.hpp @@ -3,8 +3,8 @@ // IWYU pragma: private, include <kapi/devices.hpp> +#include <kapi/capabilities/facet_id.hpp> #include <kapi/devices/driver.hpp> -#include <kapi/devices/interface_id.hpp> #include <kstd/memory.hpp> #include <kstd/string.hpp> @@ -46,52 +46,52 @@ namespace kapi::devices //! Enable safe destruction through base pointers. virtual ~device() = default; - //! Get a given capability from this device, if it implements it. + //! Get a specific facet of this device, if it supports it. //! - //! @param interface The id of the desired interface. - //! @return An opaque pointer to the interface implementation if this device supports it, nullptr otherwise. - [[nodiscard]] auto as(interface_id interface) noexcept -> void *; + //! @param id The id of the desired facet. + //! @return An opaque pointer to the facet implementation if this device supports it, nullptr otherwise. + [[nodiscard]] auto facet(kapi::capabilities::facet_id id) noexcept -> void *; - //! Get a given capability from this device, if it implements it. + //! Get a specific facet of this device, if it supports it. //! - //! @param interface The id of the desired interface. - //! @return A opaque pointer to the interface implementation if this device supports it, nullptr otherwise. - [[nodiscard]] auto as(interface_id interface) const noexcept -> void const *; + //! @param id The id of the desired facet. + //! @return A opaque pointer to the facet implementation if this device supports it, nullptr otherwise. + [[nodiscard]] auto facet(kapi::capabilities::facet_id id) const noexcept -> void const *; - //! Get a given capability from this device, if it implements it. + //! Get a specific facet of this device, if it supports it. //! - //! @tparam Interface The id of the desired interface. - //! @return A typed pointer to the interface implementation if this device supports it, nullptr otherwise. - template<typename InterfaceType> - [[nodiscard]] auto as() -> InterfaceType * + //! @tparam FacetType The type of the desired facet. + //! @return A typed pointer to the facet implementation if this device supports it, nullptr otherwise. + template<typename FacetType> + [[nodiscard]] auto facet() -> FacetType * { - return static_cast<InterfaceType *>(as(InterfaceType::id)); + return static_cast<FacetType *>(facet(FacetType::id)); } - //! Get a given capability from this device, if it implements it. + //! Get a specific facet of this device, if it supports it. //! - //! @tparam Interface The id of the desired interface. - //! @return A typed pointer to the interface implementation if this device supports it, nullptr otherwise. - template<typename InterfaceType> - [[nodiscard]] auto as() const noexcept -> InterfaceType const * + //! @tparam FacetType The type of the desired facet. + //! @return A typed pointer to the facet implementation if this device supports it, nullptr otherwise. + template<typename FacetType> + [[nodiscard]] auto facet() const noexcept -> FacetType const * { - return static_cast<InterfaceType const *>(as(InterfaceType::id)); + return static_cast<FacetType const *>(facet(FacetType::id)); } - //! Check if this device implements a given capability interface. + //! Check if this device has a specific facet. //! - //! @param interface The id of the queried interface. - //! @return true iff. this device implements the given interface, false otherwise. - [[nodiscard]] auto is_a(interface_id interface) const noexcept -> bool; + //! @param id The id of the desired facet. + //! @return true iff. this device has the given facet, false otherwise. + [[nodiscard]] auto has_facet(kapi::capabilities::facet_id id) const noexcept -> bool; - //! Check if this device implements a given capability interface. + //! Check if this device has a specific facet. //! - //! @tparam Interface The id of the queried interface. - //! @return true iff. this device implements the given interface, false otherwise. - template<typename InterfaceType> - [[nodiscard]] auto is_a() const noexcept -> bool + //! @tparam FacetType The type of the desired facet. + //! @return true iff. this device has the given facet, false otherwise. + template<typename FacetType> + [[nodiscard]] auto has_facet() const noexcept -> bool { - return is_a(InterfaceType::id); + return has_facet(FacetType::id); } //! Get the name of the device. @@ -125,7 +125,7 @@ namespace kapi::devices auto set_driver_data(kstd::shared_ptr<void> data) -> void; protected: - auto virtual query_interface(interface_id interface) -> void *; + auto virtual query_facet(kapi::capabilities::facet_id facet) -> void *; private: //! Busses need to be able to register themselves as a device's parent. diff --git a/kapi/kapi/devices/driver.hpp b/kapi/kapi/devices/driver.hpp index a2c2e396..348e2841 100644 --- a/kapi/kapi/devices/driver.hpp +++ b/kapi/kapi/devices/driver.hpp @@ -3,7 +3,7 @@ // IWYU pragma: private, include <kapi/devices.hpp> -#include <kapi/devices/interface_id.hpp> +#include <kapi/capabilities/facet_id.hpp> #include <kstd/result.hpp> @@ -46,33 +46,33 @@ namespace kapi::devices //! @param device The device to release. virtual auto unbind(device & device) -> void = 0; - //! Retrieve this drivers implementation of a given capability interface. + //! Retrieve this drivers implementation of a given capability facet. //! - //! @return A pointer to this drivers implementation of the requested interface, nullptr if this driver does not - //! support the requested interface. - template<typename InterfaceType> - [[nodiscard]] auto as() -> InterfaceType * + //! @return A pointer to this drivers implementation of the requested facet, nullptr if this driver does not + //! support the requested facet. + template<typename FacetType> + [[nodiscard]] auto facet() -> FacetType * { - return static_cast<InterfaceType *>(query_interface(InterfaceType::id)); + return static_cast<FacetType *>(query_facet(FacetType::id)); } - //! Retrieve this drivers implementation of a given capability interface. + //! Retrieve this drivers implementation of a given capability facet. //! - //! @return A pointer to this drivers implementation of the requested interface, nullptr if this driver does not - //! support the requested interface. - template<typename InterfaceType> - [[nodiscard]] auto as() const -> InterfaceType const * + //! @return A pointer to this drivers implementation of the requested facet, nullptr if this driver does not + //! support the requested facet. + template<typename FacetType> + [[nodiscard]] auto facet() const -> FacetType const * { - return static_cast<InterfaceType *>(const_cast<driver *>(this)->query_interface(InterfaceType::id)); + return static_cast<FacetType *>(const_cast<driver *>(this)->query_facet(FacetType::id)); } - //! Check if this driver implements a given capability interface. + //! Check if this driver implements a given capability facet. //! - //! @return true iff. this driver implements the requested capability interface, false otherwise. - template<typename InterfaceType> - [[nodiscard]] auto is_a() const noexcept -> bool + //! @return true iff. this driver implements the requested capability facet, false otherwise. + template<typename FacetType> + [[nodiscard]] auto has_facet() const noexcept -> bool { - return query_interface(InterfaceType::id) != nullptr; + return query_facet(FacetType::id) != nullptr; } //! Get the major number associated with this driver, if any. @@ -86,8 +86,8 @@ namespace kapi::devices [[nodiscard]] virtual auto name() const noexcept -> std::string_view = 0; protected: - //! Return a pointer to the implementation of the given interface if this driver supports it. - virtual auto query_interface(interface_id interface) -> void *; + //! Return a pointer to the implementation of the given facet if this driver supports it. + virtual auto query_facet(kapi::capabilities::facet_id facet) -> void *; }; //! @} diff --git a/kapi/kapi/devices/facet_registry.hpp b/kapi/kapi/devices/facet_registry.hpp new file mode 100644 index 00000000..82bb304b --- /dev/null +++ b/kapi/kapi/devices/facet_registry.hpp @@ -0,0 +1,305 @@ +#ifndef TEACHOS_KAPI_DEVICES_FACET_REGISTRY_HPP +#define TEACHOS_KAPI_DEVICES_FACET_REGISTRY_HPP + +// IWYU pragma: private, include <kapi/devices.hpp> + +#include <kapi/capabilities/facet_id.hpp> +#include <kapi/devices/device.hpp> + +#include <kstd/memory.hpp> +#include <kstd/result.hpp> +#include <kstd/string.hpp> +#include <kstd/system_error.hpp> +#include <kstd/vector.hpp> + +#include <string_view> +#include <utility> + +namespace kapi::devices +{ + + //! @addtogroup kapi-devices-kernel-defined + //! @{ + + struct facet_registry_observer; + + //! The device facet registry. + //! + //! The purpose of the facet registry is to allow system components, for example drivers, to publish capabilities in + //! terms of facets for devices. An example for such a capability are block devices. A driver for a given type of + //! block devices may choose too publish a the "block" facet on a bound device. Other subsystems may then query if a + //! given device exposes the "block" facet or get all devices implementing that capability. + //! + //! @note The device registry holds only non-owning references to the published devices. If a device dies after + //! publishing, without being unpublished, the registry accessors will prevent a dead handle from being exported. + //! + //! @see kernel::drivers::storage::ram_disk + //! @see kernel::filesystem::device_inode + //! @see kernel::filesystem::device_number_registry + struct facet_registry + { + //! A registry entry. + //! + //! Registry entries are used to record published facets on devices. + struct entry + { + //! Create a new registry entry, associating a device with a name and facet + //! + //! @param device The device to record the published facet for. + //! @param name The stable name to associate with this facet record. + //! @param facet The id of the implemented facet. + //! @param implementation A pointer to the actual implementation of the facet for the given device. + constexpr entry(kstd::shared_ptr<struct device> device, kstd::string name, kapi::capabilities::facet_id facet, + void * implementation) + : m_device{device} + , m_name{name} + , m_id{facet} + , m_facet{implementation} + {} + + //! Get a handle to the device of this entry. + //! + //! @return A non-null pointer to the device if it is still alive, a null + //! pointer otherwise. + [[nodiscard]] constexpr auto device() const noexcept -> kstd::shared_ptr<device> + { + return m_device.lock(); + } + + //! Get the name of this entry. + //! + //! @return The name associated with this entry. + [[nodiscard]] constexpr auto name() const noexcept -> kstd::string const & + { + return m_name; + } + + //! Get the id of the facet of the device-facet-implementation tuple described by this entry. + //! + //! @return The facet id of this entry. + [[nodiscard]] constexpr auto id() const noexcept -> kapi::capabilities::facet_id + { + return m_id; + } + + //! Get the facet of the device-facet-implementation tuple described by this entry. + //! + //! @return An untyped pointer to the facet implementation. + [[nodiscard]] constexpr auto untyped_facet() const noexcept -> void * + { + return m_facet; + } + + //! Get the facet of the device-facet-implementation tuple described by this entry. + //! + //! @return A typed pointer to the facet if the facet id matches, nullptr otherwise. + template<typename FacetType> + [[nodiscard]] constexpr auto facet() noexcept -> FacetType * + { + if (m_id == FacetType::id) + { + return static_cast<FacetType *>(untyped_facet()); + } + return nullptr; + } + + //! Get the facet of the device-facet-implementation tuple described by this entry. + //! + //! @return A typed pointer to the facet if the facet id matches, nullptr otherwise. + template<typename FacetType> + [[nodiscard]] constexpr auto facet() const noexcept -> FacetType const * + { + if (m_id == FacetType::id) + { + return static_cast<FacetType const *>(untyped_facet()); + } + return nullptr; + } + + private: + kstd::weak_ptr<struct device> m_device; + kstd::string m_name; + kapi::capabilities::facet_id m_id; + void * m_facet; + }; + + //! Construct an empty facet registry. + facet_registry() = default; + + //! Initialize the system global singleton. + //! + //! @warning This function will panic if the global singleton has already been + //! initialized. + auto static init() -> void; + + //! Get the system global singleton. + //! + //! @warning This function will panic if the global singleton has not been + //! initialized. + auto static get() -> facet_registry &; + + //! Publish the fact that a given device has a given facet. + //! + //! Each published device-facet tuple must be associated with a unique stable name, to allow unique lookup via the + //! stable name. + //! + //! This overload is designed for devices that know about the existence of the given facet on themselves. + //! + //! @tparam FacetType The facet type supported by the given device. + //! @param device The device to publish the facet for. + //! @param name A stable name for the device. + template<typename FacetType> + auto publish(kstd::shared_ptr<device> device, kstd::string name) -> kstd::result<void> + { + if (!device) + { + return kstd::failure(make_error_code(kstd::errc::invalid_argument)); + } + + return do_publish(device, std::move(name), FacetType::id, device->facet<FacetType>()); + } + + //! Publish the fact that a given device has a given facet. + //! + //! Each published device-facet tuple must be associated with a unique stable name, to allow unique lookup via the + //! stable name. + //! + //! This overload is designed to externally assign facets to a device. + //! + //! @tparam FacetType The facet type supported by the given device. + //! @param device The device to publish the facet for. + //! @param name A stable name for the device. + //! @param facet The implementation of the facet for the device. + template<typename FacetType> + auto publish(kstd::shared_ptr<device> device, kstd::string name, FacetType * facet) -> kstd::result<void> + { + return do_publish(device, std::move(name), FacetType::id, facet); + } + + //! Withdraw a previously published facets for a device. + //! + //! @param device The device to withdraw the facet for. + //! @param id The id of the facet to withdraw for the device. + auto withdraw(device const & device, kapi::capabilities::facet_id id) -> void; + + //! Withdraw every facet previously published for a device. + //! + //! @param device The device to withdraw all facets for. + auto withdraw_all_for(device const & device) -> void; + + //! Get all devices supporting a given facet. + //! + //! @param id The id of the facet for which to get the devices supporting it. + [[nodiscard]] auto all(kapi::capabilities::facet_id id) const -> kstd::vector<entry>; + + //! Attempt to resolve a facet for a device by name. + //! + //! @param id The id of the facet to look for. + //! @param name The stable name of the device. + [[nodiscard]] auto resolve(kapi::capabilities::facet_id id, std::string_view name) -> void *; + + //! Attempt to resolve a facet for a device. + //! + //! @param id The id of the facet to look for. + //! @param device The device. + [[nodiscard]] auto resolve(kapi::capabilities::facet_id id, device & device) -> void *; + + //! Attempt to resolve a facet for a device by name. + //! + //! @tparam FacetType The facet to look for. + //! @param name The stable name of the device. + template<typename FacetType> + [[nodiscard]] auto resolve(std::string_view name) -> FacetType * + { + return static_cast<FacetType *>(resolve(FacetType::id, name)); + } + + //! Attempt to resolve a facet for a device. + //! + //! @tparam FacetType The facet to look for. + //! @param device The device. + template<typename FacetType> + [[nodiscard]] auto resolve(device & device) -> FacetType * + { + return static_cast<FacetType *>(resolve(FacetType::id, device)); + } + + //! Subscribe to facet publish/withdraw notifications. + //! + //! Observers subscribed through this function are held through non-owning pointers. It is safe of an observer + //! subscribed through this function to be destroyed without being unsubscribed. + //! + //! @param observer The observer to subscribe. + auto subscribe(kstd::weak_ptr<facet_registry_observer> observer) -> void; + + //! Subscribe to facet publish/withdraw notifications. + //! + //! @warning The registry has no way of detecting liveness of observers subscribed through this function. This + //! function is intended to be used solely with long-lived observers. If an observer subscribed through this + //! function is destroyed before being unregistered, the behavior of any triggered notifications becomes undefined. + //! + //! @param observer The observer to subscribe. + auto subscribe(facet_registry_observer & observer) -> void; + + //! Cancel a subscription previously made for a given observer. + //! + //! @param observer The observer to unsubscribe. + auto unsubscribe(facet_registry_observer & observer) -> void; + + private: + //! Publish the fact that a device has a specific facet + //! + //! @param device The device to publish the facet for. + //! @param name A stable name for the device. + //! @param id The id of the facet to be published for the device. + //! @param facet The facet of the device. + auto do_publish(kstd::shared_ptr<device> device, kstd::string name, kapi::capabilities::facet_id id, void * facet) + -> kstd::result<void>; + + //! Notify all subscribed observers about a new facet having been published for a device. + //! + //! @param id The id of the published facet. + //! @param published The entry representing the published device-facet combination. + auto do_notify_published(kapi::capabilities::facet_id id, entry const & published) -> void; + + //! Notify all subscribed observers that a facet was withdrawn for a device. + //! + //! @param id The id of the withdrawn device. + //! @param device The device. + auto do_notify_withdrawn(kapi::capabilities::facet_id id, device const & device) -> void; + + kstd::vector<entry> m_entries; + kstd::vector<kstd::weak_ptr<facet_registry_observer>> m_observers; + kstd::vector<facet_registry_observer *> m_static_observers; + }; + + //! @} + + //! @addtogroup kapi-devices + //! @{ + + //! The facet for types interested in observing facet transaction on an facet registry. + struct facet_registry_observer + { + //! Enable correct destruction through base pointers. + virtual ~facet_registry_observer() = default; + + //! Called after an facet has been published for a device. + //! + //! @param facet The facet id of the published facet. + //! @param published The published entry. + virtual auto on_facet_published(kapi::capabilities::facet_id facet, facet_registry::entry const & published) + -> void = 0; + + //! Called after an facet has been withdrawn. + //! + //! @param facet The facet that was withdrawn. + //! @param device The device for which the facet was withdrawn. + virtual auto on_facet_withdrawn(kapi::capabilities::facet_id facet, device & device) -> void = 0; + }; + + //! @} + +} // namespace kapi::devices + +#endif diff --git a/kapi/kapi/devices/interface_id.hpp b/kapi/kapi/devices/interface_id.hpp deleted file mode 100644 index 0698d2fd..00000000 --- a/kapi/kapi/devices/interface_id.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TEACHOS_KAPI_DEVICES_INTERFACE_ID_HPP -#define TEACHOS_KAPI_DEVICES_INTERFACE_ID_HPP - -// IWYU pragma: private - -#include <kapi/capabilities/interface_id.hpp> - -namespace kapi::devices -{ - - using interface_id = kapi::capabilities::interface_id; - -} - -#endif diff --git a/kapi/kapi/devices/interface_registry.hpp b/kapi/kapi/devices/interface_registry.hpp deleted file mode 100644 index e0e70654..00000000 --- a/kapi/kapi/devices/interface_registry.hpp +++ /dev/null @@ -1,299 +0,0 @@ -#ifndef TEACHOS_KAPI_DEVICES_INTERFACE_REGISTRY_HPP -#define TEACHOS_KAPI_DEVICES_INTERFACE_REGISTRY_HPP - -// IWYU pragma: private, include <kapi/devices.hpp> - -#include <kapi/devices/device.hpp> -#include <kapi/devices/interface_id.hpp> - -#include <kstd/memory.hpp> -#include <kstd/result.hpp> -#include <kstd/string.hpp> -#include <kstd/system_error.hpp> -#include <kstd/vector.hpp> - -#include <string_view> -#include <utility> - -namespace kapi::devices -{ - - //! @addtogroup kapi-devices-kernel-defined - //! @{ - - struct interface_registry_observer; - - //! The device capability interface registry. - //! - //! The purpose of the interface registry is to allow system components, for - //! example drivers, to plush interfaces/capabilities for devices. An example - //! for such a capability are block devices. A driver for a given type of block - //! devices may choose too publish a the "block" capability on a bound device. - //! Other subsystems may then query if a given device exposes the "block" - //! capability or get all devices implementing that capability. - //! - //! @note The device registry holds only non-owning references to the published - //! devices. If a device dies after publishing, without being unpublished, the - //! registry accessors will prevent a dead handle from being exported. - //! - //! @see kernel::drivers::storage::ram_disk - //! @see kernel::filesystem::device_inode - //! @see kernel::filesystem::device_number_registry - struct interface_registry - { - //! A registry entry. - //! - //! Registry entries are used to record published interfaces on devices. - struct entry - { - //! Create a new registry entry, associating a device with a name, - //! interface, and interface implementation. - //! - //! @param device The device to record the published interface for. - //! @param name The stable name to associate with this interface record. - //! @param interface The id of the implemented interface. - //! @param implementation A pointer to the actual implementation of the - //! interface for the given device. - constexpr entry(kstd::shared_ptr<struct device> device, kstd::string name, interface_id interface, - void * implementation) - : m_device{device} - , m_name{name} - , m_interface{interface} - , m_implementation{implementation} - {} - - //! Get a handle to the device of this entry. - //! - //! @return A non-null pointer to the device if it is still alive, a null - //! pointer otherwise. - [[nodiscard]] constexpr auto device() const noexcept -> kstd::shared_ptr<device> - { - return m_device.lock(); - } - - //! Get the name of this entry. - //! - //! @return The name associated with this entry. - [[nodiscard]] constexpr auto name() const noexcept -> kstd::string const & - { - return m_name; - } - - //! Get the interface id associated with this entry. - //! - //! @return The interface id of this entry. - [[nodiscard]] constexpr auto interface() const noexcept -> interface_id - { - return m_interface; - } - - //! Get the interface implementation associated with this entry. - //! - //! @return An untyped pointer to the interface implementation. - [[nodiscard]] constexpr auto implementation() const noexcept -> void * - { - return m_implementation; - } - - //! Get the interface implementation associated with this entry. - //! - //! @return A typed pointer to the implementation if the interface type - //! matches, nullptr otherwise. - template<typename Interface> - [[nodiscard]] constexpr auto as() noexcept -> Interface * - { - if (m_interface == Interface::id) - { - return static_cast<Interface *>(m_implementation); - } - return nullptr; - } - - //! Get the interface implementation associated with this entry. - //! - //! @return A typed pointer to the implementation if the interface type - //! matches, nullptr otherwise. - template<typename Interface> - [[nodiscard]] constexpr auto as() const noexcept -> Interface const * - { - if (m_interface == Interface::id) - { - return static_cast<Interface const *>(m_implementation); - } - return nullptr; - } - - private: - kstd::weak_ptr<struct device> m_device; - kstd::string m_name; - interface_id m_interface; - void * m_implementation; - }; - - //! Construct an empty interface registry. - interface_registry() = default; - - //! Initialize the system global singleton. - //! - //! @warning This function will panic if the global singleton has already been - //! initialized. - auto static init() -> void; - - //! Get the system global singleton. - //! - //! @warning This function will panic if the global singleton has not been - //! initialized. - auto static get() -> interface_registry &; - - //! Publish the fact that a given device implements a given interface. - //! - //! @tparam Interface The interface type implemented by the given device. - //! @param device The device to publish the interface for. - //! @param name A stable name for the device. - template<typename Interface> - auto publish(kstd::shared_ptr<device> device, kstd::string name) -> kstd::result<void> - { - if (!device) - { - return kstd::failure(make_error_code(kstd::errc::invalid_argument)); - } - - return do_publish(device, std::move(name), Interface::id, device->as<Interface>()); - } - - //! Publish the fact that a given device implements a given interface. - //! - //! @tparam Interface The interface type implemented by the given device. - //! @param device The device to publish the interface for. - //! @param name A stable name for the device. - //! @param implementation The implementation of the interface for the device. - template<typename Interface> - auto publish(kstd::shared_ptr<device> device, kstd::string name, Interface * implementation) -> kstd::result<void> - { - return do_publish(device, std::move(name), Interface::id, implementation); - } - - //! Withdraw a previously published inteface for a given device. - //! - //! @param device The device to withdraw the interface for. - //! @param interface The interface to withdraw for the given device. - auto withdraw(device const & device, interface_id interface) -> void; - - //! Withdraw every interface previously published for a given device. - //! - //! @param device The device to withdraw all interfaces for. - auto withdraw_all_for(device const & device) -> void; - - //! Get all devices implementing a given interface. - //! - //! @param interface The interface for which to get the implementing devices. - [[nodiscard]] auto all(interface_id interface) const -> kstd::vector<entry>; - - //! 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. - [[nodiscard]] auto resolve(interface_id interface, std::string_view name) -> void *; - - //! 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. - [[nodiscard]] auto resolve(interface_id interface, device & device) -> void *; - - //! Attempt to resolve a given device, by name, to a given interface - //! implementation - //! - //! @tparam Interface The interface to look for. - //! @param name The stable name of the device to look for. - template<typename Interface> - [[nodiscard]] auto resolve(std::string_view name) -> Interface * - { - 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)); - } - - //! Subscribe to interface publish/withdraw notifications. - //! - //! Observers subscribed through this function are held through non-owning - //! pointers. It is safe of an observer subscribed through this function to be - //! destroyed without being unsubscribed. - //! - //! @param observer The observer to subscribe. - auto subscribe(kstd::weak_ptr<interface_registry_observer> observer) -> void; - - //! Subscribe to interface publish/withdraw notifications. - //! - //! @warning The registry has no way of detecting liveness of observers - //! subscribed through this function. This function is intended to be used - //! solely with long-lived observers. If an observer subscribed through this - //! function is destroyed before being unregistered, the behavior of any - //! triggered notifications becomes undefined. - //! - //! @param observer The observer to subscribe. - auto subscribe(interface_registry_observer & observer) -> void; - - //! Cancel a subscription previously made for a given observer. - //! - //! @param observer The observer to unsubscribe. - auto unsubscribe(interface_registry_observer & observer) -> void; - - private: - //! Publish the fact that a given device implements a given interface. - //! - //! @param device The device to publish the interface for. - //! @param name A stable name for the device. - //! @param interface The capability interface to be published for the device. - //! @param implementation The implementation of the interface for the device. - auto do_publish(kstd::shared_ptr<device> device, kstd::string name, interface_id interface, void * implementation) - -> kstd::result<void>; - - auto do_notify_published(interface_id interface, entry const & published) -> void; - - auto do_notify_withdrawn(interface_id interface, device const & device) -> void; - - kstd::vector<entry> m_entries; - kstd::vector<kstd::weak_ptr<interface_registry_observer>> m_observers; - kstd::vector<interface_registry_observer *> m_static_observers; - }; - - //! @} - - //! @addtogroup kapi-devices - //! @{ - - //! The interface for types interested in observing interface transaction on an interface registry. - struct interface_registry_observer - { - //! Enable correct destruction through base pointers. - virtual ~interface_registry_observer() = default; - - //! Called after an interface has been published for a device. - //! - //! @param interface The interface id of the published interface. - //! @param published The published entry. - virtual auto on_interface_published(interface_id interface, interface_registry::entry const & published) - -> void = 0; - - //! Called after an interface has been withdrawn. - //! - //! @param interface The interface that was withdrawn. - //! @param device The device for which the interface was withdrawn. - virtual auto on_interface_withdrawn(interface_id interface, device & device) -> void = 0; - }; - - //! @} - -} // namespace kapi::devices - -#endif diff --git a/kapi/kapi/filesystem.hpp b/kapi/kapi/filesystem.hpp index 52bc22bc..da72f523 100644 --- a/kapi/kapi/filesystem.hpp +++ b/kapi/kapi/filesystem.hpp @@ -1,12 +1,12 @@ #ifndef TEACHOS_KAPI_FILESYSTEM_HPP #define TEACHOS_KAPI_FILESYSTEM_HPP +#include <kapi/capabilities/facet_id.hpp> // IWYU pragma: export #include <kapi/filesystem/block_special_file.hpp> // IWYU pragma: export #include <kapi/filesystem/character_special_file.hpp> // IWYU pragma: export #include <kapi/filesystem/device_number.hpp> // IWYU pragma: export #include <kapi/filesystem/file_status.hpp> // IWYU pragma: export #include <kapi/filesystem/file_type.hpp> // IWYU pragma: export -#include <kapi/filesystem/interface_id.hpp> // IWYU pragma: export #include <kstd/result.hpp> #include <kstd/system_error.hpp> diff --git a/kapi/kapi/filesystem/block_special_file.hpp b/kapi/kapi/filesystem/block_special_file.hpp index c7f3ac51..0e44fe35 100644 --- a/kapi/kapi/filesystem/block_special_file.hpp +++ b/kapi/kapi/filesystem/block_special_file.hpp @@ -3,7 +3,7 @@ // IWYU pragma: private, include <kapi/filesystem.hpp> -#include <kapi/filesystem/interface_id.hpp> +#include <kapi/capabilities/facet_id.hpp> #include <kstd/result.hpp> #include <kstd/units.hpp> @@ -15,7 +15,7 @@ namespace kapi::filesystem struct block_special_file { - constexpr auto static id = interface_id{"block"}; + constexpr auto static id = kapi::capabilities::facet_id{"block"}; //! Virtual destructor to enable clean deletes through base pointers. virtual ~block_special_file() = default; diff --git a/kapi/kapi/filesystem/character_special_file.hpp b/kapi/kapi/filesystem/character_special_file.hpp index 7ce5fdaa..328bbef9 100644 --- a/kapi/kapi/filesystem/character_special_file.hpp +++ b/kapi/kapi/filesystem/character_special_file.hpp @@ -3,7 +3,7 @@ // IWYU pragma: private, include <kapi/filesystem.hpp> -#include <kapi/filesystem/interface_id.hpp> +#include <kapi/capabilities/facet_id.hpp> #include <kstd/result.hpp> #include <kstd/units.hpp> @@ -16,7 +16,7 @@ namespace kapi::filesystem struct character_special_file { - constexpr auto static id = interface_id{"char"}; + constexpr auto static id = kapi::capabilities::facet_id{"char"}; //! Virtual destructor to enable clean deletes through base pointers. virtual ~character_special_file() = default; diff --git a/kapi/kapi/filesystem/interface_id.hpp b/kapi/kapi/filesystem/interface_id.hpp deleted file mode 100644 index 18e0fbc4..00000000 --- a/kapi/kapi/filesystem/interface_id.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TEACHOS_KAPI_FILESYSTEM_INTERFACE_ID_HPP -#define TEACHOS_KAPI_FILESYSTEM_INTERFACE_ID_HPP - -// IWYU pragma: private - -#include <kapi/capabilities/interface_id.hpp> - -namespace kapi::filesystem -{ - - using interface_id = kapi::capabilities::interface_id; - -} - -#endif diff --git a/kapi/kapi/test_support/devices.hpp b/kapi/kapi/test_support/devices.hpp index 3cb1cd8b..623bb87a 100644 --- a/kapi/kapi/test_support/devices.hpp +++ b/kapi/kapi/test_support/devices.hpp @@ -4,7 +4,7 @@ namespace kapi::test_support::devices { auto deinit() -> void; - auto deinit_interface_registry() -> void; + auto deinit_facet_registry() -> void; auto deinit_driver_registry() -> void; auto deinit_device_registry() -> void; } // namespace kapi::test_support::devices diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 9bb2efd8..d22ad107 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -19,7 +19,7 @@ target_sources("kernel_lib" PRIVATE "kapi/devices/driver.cpp" "kapi/devices/driver_registry.cpp" "kapi/devices/error.cpp" - "kapi/devices/interface_registry.cpp" + "kapi/devices/facet_registry.cpp" "kapi/filesystem.cpp" "kapi/interrupts.cpp" "kapi/memory.cpp" diff --git a/kernel/kapi/boot_modules/device.cpp b/kernel/kapi/boot_modules/device.cpp index 84a43c1c..b9262abf 100644 --- a/kernel/kapi/boot_modules/device.cpp +++ b/kernel/kapi/boot_modules/device.cpp @@ -26,14 +26,14 @@ namespace kapi::boot_modules return m_module; } - auto device::query_interface(kapi::devices::interface_id interface) -> void * + auto device::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == boot_module_signature::id) + if (facet == boot_module_signature::id) { return static_cast<boot_module_signature *>(this); } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } } // namespace kapi::boot_modules
\ No newline at end of file diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp index c3c9e595..2505779a 100644 --- a/kernel/kapi/devices.cpp +++ b/kernel/kapi/devices.cpp @@ -27,7 +27,7 @@ namespace kapi::devices } device_registry::init(); - interface_registry::init(); + facet_registry::init(); root_bus = kstd::make_shared<kernel::bus::root>(); device_registry::get().add(root_bus); @@ -49,7 +49,7 @@ namespace kapi::test_support::devices auto deinit() -> void { deinit_driver_registry(); - deinit_interface_registry(); + deinit_facet_registry(); deinit_device_registry(); kapi::devices::root_bus.reset(); diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp index a9bba4fb..9eecced0 100644 --- a/kernel/kapi/devices/bus.cpp +++ b/kernel/kapi/devices/bus.cpp @@ -37,19 +37,14 @@ namespace kapi::devices return {m_devices.data(), m_devices.size()}; } - auto bus::protocol() -> struct bus_protocol * + auto bus::query_facet(kapi::capabilities::facet_id facet) -> void * { - return nullptr; - } - - auto bus::query_interface(interface_id interface) -> void * - { - if (interface == bus::id) + if (facet == bus::id) { return this; } - return device::query_interface(interface); + return device::query_facet(facet); } } // namespace kapi::devices
\ No newline at end of file diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp index 01096165..2628e4f4 100644 --- a/kernel/kapi/devices/device.cpp +++ b/kernel/kapi/devices/device.cpp @@ -12,19 +12,19 @@ namespace kapi::devices : m_name(name) {} - auto device::as(interface_id interface) noexcept -> void * + auto device::facet(kapi::capabilities::facet_id facet) noexcept -> void * { - return query_interface(interface); + return query_facet(facet); } - auto device::as(interface_id interface) const noexcept -> void const * + auto device::facet(kapi::capabilities::facet_id facet) const noexcept -> void const * { - return const_cast<device *>(this)->query_interface(interface); + return const_cast<device *>(this)->query_facet(facet); } - auto device::is_a(interface_id interface) const noexcept -> bool + auto device::has_facet(kapi::capabilities::facet_id facet) const noexcept -> bool { - return const_cast<device *>(this)->query_interface(interface) != nullptr; + return const_cast<device *>(this)->query_facet(facet) != nullptr; } auto device::name() const -> kstd::string const & @@ -67,7 +67,7 @@ namespace kapi::devices m_driver_data = data; } - auto device::query_interface(interface_id) -> void * + auto device::query_facet(kapi::capabilities::facet_id) -> void * { return nullptr; } diff --git a/kernel/kapi/devices/driver.cpp b/kernel/kapi/devices/driver.cpp index be2866f0..55b7507b 100644 --- a/kernel/kapi/devices/driver.cpp +++ b/kernel/kapi/devices/driver.cpp @@ -11,7 +11,7 @@ namespace kapi::devices return std::nullopt; } - auto driver::query_interface(interface_id) -> void * + auto driver::query_facet(kapi::capabilities::facet_id) -> void * { return nullptr; } diff --git a/kernel/kapi/devices/driver.tests.cpp b/kernel/kapi/devices/driver.tests.cpp index e65e48e0..560cc1bc 100644 --- a/kernel/kapi/devices/driver.tests.cpp +++ b/kernel/kapi/devices/driver.tests.cpp @@ -16,39 +16,49 @@ namespace { struct controller_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_controller_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_identification"}; virtual ~controller_identification() = default; [[nodiscard]] virtual auto controller_name() const -> std::string_view = 0; }; struct controller_driver_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_controller_driver_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_driver_identification"}; virtual ~controller_driver_identification() = default; [[nodiscard]] virtual auto supported_names() const -> std::span<std::string_view const> = 0; }; - struct controller_bus final : kapi::devices::bus, kapi::devices::bus_protocol + struct controller_protocol : kapi::devices::bus_protocol { - using kapi::devices::bus::bus; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_protocol"}; auto enumerate(kapi::devices::bus &) -> void override {} [[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const -> kstd::result<std::uint32_t> override { - auto const * ident = dev.as<controller_identification>(); - auto const * claims = drv.as<controller_driver_identification>(); + auto const * ident = dev.facet<controller_identification>(); + auto const * claims = drv.facet<controller_driver_identification>(); if (!ident || !claims || !std::ranges::contains(claims->supported_names(), ident->controller_name())) { return kstd::failure(kapi::devices::driver_match_errc::no_match); } return 0u; } + } constinit controller_protocol_instance{}; + + struct controller_bus final : kapi::devices::bus + { + using kapi::devices::bus::bus; - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override { - return this; + if (id == controller_protocol::id || id == kapi::devices::bus_protocol::id) + { + return &controller_protocol_instance; + } + + return kapi::devices::bus::query_facet(id); } }; @@ -64,26 +74,26 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == controller_identification::id) + if (facet == controller_identification::id) { return static_cast<controller_identification *>(this); } - return kapi::devices::bus::query_interface(interface); + return kapi::devices::bus::query_facet(facet); } }; struct leaf_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_leaf_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_identification"}; virtual ~leaf_identification() = default; [[nodiscard]] virtual auto leaf_name() const -> std::string_view = 0; }; struct leaf_driver_identification { - constexpr auto static id = kapi::devices::interface_id{"stacking_test_leaf_driver_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_driver_identification"}; virtual ~leaf_driver_identification() = default; [[nodiscard]] virtual auto supported_names() const -> std::span<std::string_view const> = 0; }; @@ -100,19 +110,19 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == leaf_identification::id) + if (facet == leaf_identification::id) { return static_cast<leaf_identification *>(this); } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } }; - struct leaf_bus final : kapi::devices::bus, kapi::devices::bus_protocol + struct leaf_protocol final : kapi::devices::bus_protocol { - using kapi::devices::bus::bus; + constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_protocol"}; auto enumerate(kapi::devices::bus & self) -> void override { @@ -122,18 +132,28 @@ namespace [[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const -> kstd::result<std::uint32_t> override { - auto const * ident = dev.as<leaf_identification>(); - auto const * claims = drv.as<leaf_driver_identification>(); + auto const * ident = dev.facet<leaf_identification>(); + auto const * claims = drv.facet<leaf_driver_identification>(); if (!ident || !claims || !std::ranges::contains(claims->supported_names(), ident->leaf_name())) { return kstd::failure(kapi::devices::driver_match_errc::no_match); } return 0u; } + } constinit leaf_protocol_instance{}; + + struct leaf_bus final : kapi::devices::bus + { + using kapi::devices::bus::bus; - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override { - return this; + if (id == leaf_protocol::id || id == kapi::devices::bus_protocol::id) + { + return &leaf_protocol_instance; + } + + return kapi::devices::bus::query_facet(id); } }; @@ -144,7 +164,7 @@ namespace auto self_as_bus = kstd::static_pointer_cast<kapi::devices::bus>(dev.shared_from_this()); auto leaf = kstd::make_shared<leaf_bus>("stacking_test_leaf_bus"); self_as_bus->add_child(leaf); - leaf->enumerate(*leaf); + leaf->facet<leaf_protocol>()->enumerate(*leaf); return kstd::success(); } @@ -163,14 +183,14 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == controller_driver_identification::id) + if (facet == controller_driver_identification::id) { return static_cast<controller_driver_identification *>(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } }; @@ -195,14 +215,14 @@ namespace } protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == leaf_driver_identification::id) + if (facet == leaf_driver_identification::id) { return static_cast<leaf_driver_identification *>(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } }; } // namespace diff --git a/kernel/kapi/devices/driver_registry.cpp b/kernel/kapi/devices/driver_registry.cpp index cb101d27..842dbc1d 100644 --- a/kernel/kapi/devices/driver_registry.cpp +++ b/kernel/kapi/devices/driver_registry.cpp @@ -79,7 +79,7 @@ namespace kapi::devices } auto parent = device->parent(); - auto protocol = parent ? parent->protocol() : nullptr; + auto protocol = parent ? parent->facet<kapi::devices::bus_protocol>() : nullptr; if (!protocol) { return; diff --git a/kernel/kapi/devices/driver_registry.tests.cpp b/kernel/kapi/devices/driver_registry.tests.cpp index d4d8a174..c7d1744d 100644 --- a/kernel/kapi/devices/driver_registry.tests.cpp +++ b/kernel/kapi/devices/driver_registry.tests.cpp @@ -15,7 +15,7 @@ namespace struct test_identification { - constexpr auto static id = kapi::devices::interface_id{"test_identification"}; + constexpr auto static id = kapi::capabilities::facet_id{"test_identification"}; virtual ~test_identification() = default; @@ -25,6 +25,8 @@ namespace struct test_protocol final : kapi::devices::bus_protocol { + constexpr auto static id = kapi::capabilities::facet_id{"test_protocol"}; + explicit test_protocol(unsigned * match_calls) : match_calls{match_calls} {} @@ -36,7 +38,7 @@ namespace { ++*match_calls; - auto const * identification = driver.as<test_identification>(); + auto const * identification = driver.facet<test_identification>(); if (!identification) { return kstd::failure(kapi::devices::driver_match_errc::no_match); @@ -52,9 +54,14 @@ namespace { using kapi::devices::bus::bus; - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override { - return &bus_protocol; + if (id == test_protocol::id || id == kapi::devices::bus_protocol::id) + { + return &bus_protocol; + } + + return kapi::devices::bus::query_facet(id); } unsigned match_calls{}; @@ -106,14 +113,14 @@ namespace mutable unsigned probe_calls; protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == test_identification::id) + if (facet == test_identification::id) { return static_cast<test_identification *>(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } private: diff --git a/kernel/kapi/devices/facet_registry.cpp b/kernel/kapi/devices/facet_registry.cpp new file mode 100644 index 00000000..4aeebfc1 --- /dev/null +++ b/kernel/kapi/devices/facet_registry.cpp @@ -0,0 +1,216 @@ +#include <kapi/devices/facet_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<facet_registry>{}; + } + + auto facet_registry::init() -> void + { + if (registry.has_value()) + { + system::panic("[kernel] Device facet registry has already been initialized."); + } + + registry.emplace(); + } + + auto facet_registry::get() -> facet_registry & + { + if (!registry) + { + system::panic("[kernel] Device facet registry has not been initialized."); + } + + return *registry; + } + + auto facet_registry::do_publish(kstd::shared_ptr<device> device, kstd::string name, kapi::capabilities::facet_id id, + void * facet) -> kstd::result<void> + { + // TODO: lock registry + + erase_if(m_entries, [id](auto e) { return e.id() == id && !e.device(); }); + + if (!device || !facet || name.empty()) + { + return kstd::failure(make_error_code(kstd::errc::invalid_argument)); + } + + auto already_published = std::ranges::any_of( + m_entries, [&](auto const & entry) { return entry.id() == id && entry.device().get() == device.get(); }); + + if (already_published) + { + return kstd::failure(make_error_code(kstd::errc::file_exists)); + } + + auto & published = m_entries.emplace_back(device, std::move(name), id, facet); + + do_notify_published(id, published); + + return kstd::success(); + } + + auto facet_registry::do_notify_published(kapi::capabilities::facet_id id, entry const & published) -> void + { + std::ranges::for_each(m_observers, [&](auto observer) { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_facet_published(id, published); + } + }); + + std::ranges::for_each(m_static_observers, [&](auto observer) { observer->on_facet_published(id, published); }); + } + + auto facet_registry::do_notify_withdrawn(kapi::capabilities::facet_id id, device const & device) -> void + { + std::ranges::for_each(m_observers, [&](auto observer) { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_facet_withdrawn(id, const_cast<devices::device &>(device)); + } + }); + + std::ranges::for_each(m_static_observers, [&](auto observer) { + observer->on_facet_withdrawn(id, const_cast<devices::device &>(device)); + }); + } + + auto facet_registry::withdraw(device const & device, kapi::capabilities::facet_id id) -> void + { + // TODO: lock registry + + auto did_remove = erase_if(m_entries, [&](auto e) { + auto locked_device = e.device(); + return e.id() == id && locked_device && locked_device.get() == &device; + }) != 0; + + if (did_remove) + { + do_notify_withdrawn(id, device); + } + } + + auto facet_registry::withdraw_all_for(device const & device) -> void + { + // TODO: lock registry + + auto withdrawn_facets = kstd::vector<kapi::capabilities::facet_id>{}; + + erase_if(m_entries, [&](auto e) { + auto locked_device = e.device(); + auto do_erase = locked_device && locked_device.get() == &device; + if (do_erase) + { + withdrawn_facets.push_back(e.id()); + } + return do_erase; + }); + + std::ranges::for_each(withdrawn_facets, [&](auto facet) { do_notify_withdrawn(facet, device); }); + } + + auto facet_registry::all(kapi::capabilities::facet_id id) const -> kstd::vector<entry> + { + // TODO: lock registry + + auto filtered = m_entries; + erase_if(filtered, [&](auto e) { + auto locked_device = e.device(); + return !(e.id() == id && locked_device); + }); + return filtered; + } + + auto facet_registry::resolve(kapi::capabilities::facet_id id, std::string_view name) -> void * + { + // TODO: lock registry + + auto found = std::ranges::find_if(m_entries, [&](auto e) { return e.name() == name && e.device(); }); + + if (found == m_entries.cend()) + { + return nullptr; + } + else if (auto device = found->device()) + { + return resolve(id, *device); + } + + return nullptr; + } + + auto facet_registry::resolve(kapi::capabilities::facet_id id, device & device) -> void * + { + // TODO: lock registry + + if (auto by_device = device.facet(id)) + { + return by_device; + } + + auto found = std::ranges::find_if(m_entries, [&](auto e) { + auto locked_device = e.device(); + return e.id() == id && locked_device && locked_device.get() == &device; + }); + + if (found == m_entries.cend()) + { + return nullptr; + } + + return found->untyped_facet(); + } + + auto facet_registry::subscribe(kstd::weak_ptr<facet_registry_observer> observer) -> void + { + // TODO: lock registry + + erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); + m_observers.push_back(observer); + } + + auto facet_registry::subscribe(facet_registry_observer & observer) -> void + { + // TODO: lock registry + + m_static_observers.push_back(&observer); + } + + auto facet_registry::unsubscribe(facet_registry_observer & observer) -> void + { + // TODO: lock registry + + erase_if(m_observers, [&](auto const & subscribed) { return subscribed.lock().get() == &observer; }); + erase(m_static_observers, &observer); + } + +} // namespace kapi::devices + +namespace kapi::test_support::devices +{ + auto deinit_facet_registry() -> void + { + kapi::devices::registry.reset(); + } +} // namespace kapi::test_support::devices diff --git a/kernel/kapi/devices/interface_registry.tests.cpp b/kernel/kapi/devices/facet_registry.tests.cpp index 071b9a6d..4ad3f763 100644 --- a/kernel/kapi/devices/interface_registry.tests.cpp +++ b/kernel/kapi/devices/facet_registry.tests.cpp @@ -10,7 +10,7 @@ namespace { struct probe_device { - constexpr auto static id = kapi::devices::interface_id{"probe"}; + constexpr auto static id = kapi::capabilities::facet_id{"probe"}; virtual ~probe_device() = default; @@ -19,7 +19,7 @@ namespace struct const_device { - constexpr auto static id = kapi::devices::interface_id{"flip"}; + constexpr auto static id = kapi::capabilities::facet_id{"flip"}; virtual ~const_device() = default; @@ -31,7 +31,7 @@ namespace struct unimplemented_device { - constexpr auto static id = kapi::devices::interface_id{"unimplemented"}; + constexpr auto static id = kapi::capabilities::facet_id{"unimplemented"}; virtual ~unimplemented_device() = default; }; @@ -49,18 +49,18 @@ namespace return m_value; } - auto query_interface(kapi::devices::interface_id interface) -> void * override + auto query_facet(kapi::capabilities::facet_id facet) -> void * override { - if (interface == probe_device::id) + if (facet == probe_device::id) { return static_cast<probe_device *>(this); } - if (interface == const_device::id) + if (facet == const_device::id) { return m_const_device; } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } private: @@ -68,15 +68,14 @@ namespace const_device * m_const_device; }; - struct counting_observer final : kapi::devices::interface_registry_observer + struct counting_observer final : kapi::devices::facet_registry_observer { - auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &) - -> void override + auto on_facet_published(kapi::capabilities::facet_id, kapi::devices::facet_registry::entry const &) -> void override { ++published; } - auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override + auto on_facet_withdrawn(kapi::capabilities::facet_id, kapi::devices::device &) -> void override { ++withdrawn; } @@ -85,19 +84,18 @@ namespace std::size_t withdrawn{}; }; - struct evil_observer final : kapi::devices::interface_registry_observer + struct evil_observer final : kapi::devices::facet_registry_observer { explicit evil_observer(kstd::shared_ptr<counting_observer> & victim) : m_victim{victim} {} - auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &) - -> void override + auto on_facet_published(kapi::capabilities::facet_id, kapi::devices::facet_registry::entry const &) -> void override { m_victim.reset(); } - auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override + auto on_facet_withdrawn(kapi::capabilities::facet_id, kapi::devices::device &) -> void override { m_victim.reset(); } @@ -108,46 +106,46 @@ namespace } // namespace -SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]") +SCENARIO("Publishing and finding a device", "[kapi][devices][facet_registry]") { - GIVEN("An empty registry, a device, and an interface the device implements by inheritance") + GIVEN("An empty registry, a device, and a facet the device implements by inheritance") { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared<test_device>(128, free_standing_interface); + auto registry = kapi::devices::facet_registry{}; + auto free_standing_facet = const_device{}; + auto device = kstd::make_shared<test_device>(128, free_standing_facet); - THEN("Publishing an interface without a name fails") + THEN("Publishing an facet without a name fails") { REQUIRE_FALSE(registry.publish<probe_device>(device, "")); } - WHEN("publishing the interface for the device") + WHEN("publishing the facet for the device") { - CHECK(device->is_a<probe_device>()); - CHECK(device->is_a<const_device>()); - auto published = registry.publish(device, "probe0", device->as<probe_device>()); + CHECK(device->has_facet<probe_device>()); + CHECK(device->has_facet<const_device>()); + auto published = registry.publish(device, "probe0", device->facet<probe_device>()); THEN("publishing is successful") { REQUIRE(published); } - THEN("publishing the same device and interface with a different name fails") + THEN("publishing the same device and facet with a different name fails") { - REQUIRE_FALSE(registry.publish(device, "probe1", device->as<probe_device>())); + REQUIRE_FALSE(registry.publish(device, "probe1", device->facet<probe_device>())); } - THEN("publishing a second interface for the same device succeeds") + THEN("publishing a second facet for the same device succeeds") { REQUIRE(registry.publish<const_device>(device, "probe0")); } - THEN("publishing a free standing second interface for the same device succeeds") + THEN("publishing a free standing second facet for the same device succeeds") { - REQUIRE(registry.publish(device, "probe0", &free_standing_interface)); + REQUIRE(registry.publish(device, "probe0", &free_standing_facet)); } - AND_WHEN("getting all devices implementing that interface") + AND_WHEN("getting all devices implementing that facet") { auto probeable_devices = registry.all(probe_device::id); @@ -168,12 +166,12 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry] THEN("the returned implementation equals the result of device::as") { - REQUIRE(probeable_devices[0].implementation() == device->as<probe_device>()); + REQUIRE(probeable_devices[0].untyped_facet() == device->facet<probe_device>()); } - THEN("the interface provided function can be invoked") + THEN("the facet provided function can be invoked") { - auto implementation = probeable_devices[0].as<probe_device>(); + auto implementation = probeable_devices[0].facet<probe_device>(); REQUIRE(implementation->get_value() == device->get_value()); } } @@ -198,7 +196,7 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry] REQUIRE_FALSE(registry.resolve<probe_device>("probe1")); } - THEN("withdrawing an interface for a device removes it from the registry") + THEN("withdrawing an facet for a device removes it from the registry") { registry.withdraw(*device, probe_device::id); REQUIRE_FALSE(registry.resolve<probe_device>("probe0")); @@ -207,7 +205,7 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry] WHEN("the device is destroyed without withdrawing it") { - CHECK(registry.publish(device, "probe0", device->as<probe_device>())); + CHECK(registry.publish(device, "probe0", device->facet<probe_device>())); device.reset(); THEN("querying all does no longer report it") @@ -224,7 +222,7 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry] GIVEN("no device has ever been published") { - auto registry = kapi::devices::interface_registry{}; + auto registry = kapi::devices::facet_registry{}; THEN("all() returns an empty vector") { @@ -234,31 +232,31 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry] GIVEN("a null device") { - auto registry = kapi::devices::interface_registry{}; + auto registry = kapi::devices::facet_registry{}; auto device = kstd::shared_ptr<kapi::devices::device>{}; - auto interface = const_device{}; + auto facet = const_device{}; - THEN("publishing the interface for the device fails") + THEN("publishing the facet for the device fails") { - REQUIRE_FALSE(registry.publish(device, "probe0", &interface)); + REQUIRE_FALSE(registry.publish(device, "probe0", &facet)); } } } -SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_registry]") +SCENARIO("facet registry notifies subscribers", "[kapi][devices][facet_registry]") { GIVEN("a device and a subscribed observer") { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared<test_device>(128, free_standing_interface); + auto registry = kapi::devices::facet_registry{}; + auto free_standing_facet = const_device{}; + auto device = kstd::make_shared<test_device>(128, free_standing_facet); auto observer = kstd::make_shared<counting_observer>(); registry.subscribe(observer); - WHEN("an interface is published for the device") + WHEN("an facet is published for the device") { - CHECK(registry.publish(device, "probe0", device->as<probe_device>())); + CHECK(registry.publish(device, "probe0", device->facet<probe_device>())); THEN("the observer is notified exactly once") { @@ -267,9 +265,9 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r } } - WHEN("an interface is published and then withdrawn") + WHEN("an facet is published and then withdrawn") { - CHECK(registry.publish(device, "probe0", device->as<probe_device>())); + CHECK(registry.publish(device, "probe0", device->facet<probe_device>())); registry.withdraw(*device, probe_device::id); THEN("the observer is notified of both exactly one") @@ -285,7 +283,7 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r THEN("publishing afterward does not crash") { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>())); } } @@ -295,12 +293,12 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r THEN("publishing afterward does not crash") { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>())); } THEN("the subscriber is not notified") { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>())); REQUIRE_NOTHROW(registry.withdraw(*device, probe_device::id)); REQUIRE(observer->published == 0); REQUIRE(observer->withdrawn == 0); @@ -310,9 +308,9 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r GIVEN("two subscriber, the first destroying the second") { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared<test_device>(128, free_standing_interface); + auto registry = kapi::devices::facet_registry{}; + auto free_standing_facet = const_device{}; + auto device = kstd::make_shared<test_device>(128, free_standing_facet); auto second = kstd::make_shared<counting_observer>(); auto first = kstd::make_shared<evil_observer>(second); @@ -320,9 +318,9 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r registry.subscribe(first); registry.subscribe(second); - THEN("publishing an interface does not crash") + THEN("publishing an facet does not crash") { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); + REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>())); REQUIRE(second == nullptr); } } diff --git a/kernel/kapi/devices/interface_registry.cpp b/kernel/kapi/devices/interface_registry.cpp deleted file mode 100644 index 1d456b30..00000000 --- a/kernel/kapi/devices/interface_registry.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#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_id interface, - void * implementation) -> kstd::result<void> - { - // TODO: lock registry - - erase_if(m_entries, [interface](auto e) { return e.interface() == interface && !e.device(); }); - - if (!device || !implementation || name.empty()) - { - return kstd::failure(make_error_code(kstd::errc::invalid_argument)); - } - - auto already_published = std::ranges::any_of(m_entries, [&](auto const & entry) { - return entry.interface() == interface && entry.device().get() == device.get(); - }); - - if (already_published) - { - return kstd::failure(make_error_code(kstd::errc::file_exists)); - } - - auto & published = m_entries.emplace_back(device, std::move(name), interface, implementation); - - do_notify_published(interface, published); - - return kstd::success(); - } - - auto interface_registry::do_notify_published(interface_id interface, entry const & published) -> void - { - std::ranges::for_each(m_observers, [&](auto observer) { - if (auto locked_observer = observer.lock()) - { - locked_observer->on_interface_published(interface, published); - } - }); - - std::ranges::for_each(m_static_observers, - [&](auto observer) { observer->on_interface_published(interface, published); }); - } - - auto interface_registry::do_notify_withdrawn(interface_id interface, device const & device) -> void - { - std::ranges::for_each(m_observers, [&](auto observer) { - if (auto locked_observer = observer.lock()) - { - locked_observer->on_interface_withdrawn(interface, const_cast<devices::device &>(device)); - } - }); - - std::ranges::for_each(m_static_observers, [&](auto observer) { - observer->on_interface_withdrawn(interface, const_cast<devices::device &>(device)); - }); - } - - auto interface_registry::withdraw(device const & device, interface_id interface) -> void - { - // TODO: lock registry - - auto did_remove = erase_if(m_entries, [&](auto e) { - auto locked_device = e.device(); - return e.interface() == interface && locked_device && locked_device.get() == &device; - }) != 0; - - if (did_remove) - { - do_notify_withdrawn(interface, device); - } - } - - auto interface_registry::withdraw_all_for(device const & device) -> void - { - // TODO: lock registry - - auto withdrawn_interfaces = kstd::vector<interface_id>{}; - - erase_if(m_entries, [&](auto e) { - auto locked_device = e.device(); - auto do_erase = locked_device && locked_device.get() == &device; - if (do_erase) - { - withdrawn_interfaces.push_back(e.interface()); - } - return do_erase; - }); - - std::ranges::for_each(withdrawn_interfaces, [&](auto interface) { do_notify_withdrawn(interface, device); }); - } - - auto interface_registry::all(interface_id interface) const -> kstd::vector<entry> - { - // TODO: lock registry - - auto filtered = m_entries; - erase_if(filtered, [&](auto e) { - auto locked_device = e.device(); - return !(e.interface() == interface && locked_device); - }); - return filtered; - } - - auto interface_registry::resolve(interface_id interface, std::string_view name) -> void * - { - // TODO: lock registry - - auto found = std::ranges::find_if(m_entries, [&](auto e) { return e.name() == name && e.device(); }); - - if (found == m_entries.cend()) - { - return nullptr; - } - else if (auto device = found->device()) - { - return resolve(interface, *device); - } - - return nullptr; - } - - auto interface_registry::resolve(interface_id interface, device & device) -> void * - { - // TODO: lock registry - - 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 nullptr; - } - - return found->implementation(); - } - - auto interface_registry::subscribe(kstd::weak_ptr<interface_registry_observer> observer) -> void - { - // TODO: lock registry - - erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); - m_observers.push_back(observer); - } - - auto interface_registry::subscribe(interface_registry_observer & observer) -> void - { - // TODO: lock registry - - m_static_observers.push_back(&observer); - } - - auto interface_registry::unsubscribe(interface_registry_observer & observer) -> void - { - // TODO: lock registry - - erase_if(m_observers, [&](auto const & subscribed) { return subscribed.lock().get() == &observer; }); - erase(m_static_observers, &observer); - } - -} // namespace kapi::devices - -namespace kapi::test_support::devices -{ - auto deinit_interface_registry() -> void - { - kapi::devices::registry.reset(); - } -} // namespace kapi::test_support::devices diff --git a/kernel/kernel/bus/boot_modules.cpp b/kernel/kernel/bus/boot_modules.cpp index 069d414f..be507eb5 100644 --- a/kernel/kernel/bus/boot_modules.cpp +++ b/kernel/kernel/bus/boot_modules.cpp @@ -29,6 +29,8 @@ namespace kernel::bus struct boot_modules_protocol : kapi::devices::bus_protocol { + constexpr auto static id = kapi::capabilities::facet_id{"boot_modules_bus"}; + auto enumerate(kapi::devices::bus &) -> void override { // The boot modules virtual bus does not support enumeration. @@ -37,8 +39,8 @@ namespace kernel::bus [[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const -> kstd::result<unsigned> override { - auto signature = dev.as<kapi::boot_modules::boot_module_signature>(); - auto claim = drv.as<kapi::boot_modules::boot_module_claim>(); + auto signature = dev.facet<kapi::boot_modules::boot_module_signature>(); + auto claim = drv.facet<kapi::boot_modules::boot_module_claim>(); if (!signature || !claim) { @@ -62,9 +64,14 @@ namespace kernel::bus : kapi::devices::bus{"boot_modules"} {} - auto boot_modules::protocol() -> kapi::devices::bus_protocol * + auto boot_modules::query_facet(kapi::capabilities::facet_id id) -> void * { - return &protocol_instance; + if (id == boot_modules_protocol::id || id == kapi::devices::bus_protocol::id) + { + return static_cast<kapi::devices::bus_protocol *>(&protocol_instance); + } + + return kapi::devices::bus::query_facet(id); } } // namespace kernel::bus diff --git a/kernel/kernel/bus/boot_modules.hpp b/kernel/kernel/bus/boot_modules.hpp index c73e0d74..011e2b2e 100644 --- a/kernel/kernel/bus/boot_modules.hpp +++ b/kernel/kernel/bus/boot_modules.hpp @@ -15,7 +15,7 @@ namespace kernel::bus { boot_modules(); - [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override; + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override; }; } // namespace kernel::bus diff --git a/kernel/kernel/devices/storage.cpp b/kernel/kernel/devices/storage.cpp index 4f5776d2..d54e7056 100644 --- a/kernel/kernel/devices/storage.cpp +++ b/kernel/kernel/devices/storage.cpp @@ -18,7 +18,7 @@ namespace kernel::devices::storage auto determine_boot_device() -> kstd::shared_ptr<kapi::devices::device> { - auto block_devices = kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id); + auto block_devices = kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id); if (block_devices.empty()) { return nullptr; diff --git a/kernel/kernel/devices/storage.tests.cpp b/kernel/kernel/devices/storage.tests.cpp index 3cf21b01..46dfb5ab 100644 --- a/kernel/kernel/devices/storage.tests.cpp +++ b/kernel/kernel/devices/storage.tests.cpp @@ -29,7 +29,7 @@ TEST_CASE("Storage devices attached with init() are reachable from the root bus" bus->add_child(device); - auto block_devices = kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id); + auto block_devices = kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id); REQUIRE(block_devices.size() == 1); CHECK(block_devices[0].name() == "ram0"); diff --git a/kernel/kernel/drivers/storage/ram_disk.cpp b/kernel/kernel/drivers/storage/ram_disk.cpp index 97a6443b..987f4bbc 100644 --- a/kernel/kernel/drivers/storage/ram_disk.cpp +++ b/kernel/kernel/drivers/storage/ram_disk.cpp @@ -96,13 +96,13 @@ namespace kernel::drivers::storage auto ram_disk::probe(kapi::devices::device & device) -> kstd::result<void> { - auto interface = device.as<kapi::boot_modules::boot_module_signature>(); - if (!interface) + auto facet = device.facet<kapi::boot_modules::boot_module_signature>(); + if (!facet) { return kstd::failure(make_error_code(kstd::errc::invalid_argument)); } - auto const & module = interface->module(); + auto const & module = facet->module(); if (module.start_address.raw() == 0 || module.size == 0) { return kstd::failure(make_error_code(kstd::errc::invalid_argument)); @@ -111,15 +111,15 @@ namespace kernel::drivers::storage auto implementation = kstd::make_shared<struct block_node>(module); auto next_index = - std::ranges::count_if(kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id), + std::ranges::count_if(kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id), [this](auto const & published) { auto published_device = published.device(); return published_device && published_device->bound_driver() == this; }); auto name = kstd::format("ram{}", next_index); - auto published = kapi::devices::publish_interface<kapi::filesystem::block_special_file>(device.shared_from_this(), - name, implementation.get()); + auto published = kapi::devices::publish_facet<kapi::filesystem::block_special_file>(device.shared_from_this(), name, + implementation.get()); if (!published) { return published; @@ -132,7 +132,7 @@ namespace kernel::drivers::storage auto ram_disk::unbind(kapi::devices::device & device) -> void { - kapi::devices::interface_registry::get().withdraw(device, kapi::filesystem::block_special_file::id); + kapi::devices::facet_registry::get().withdraw(device, kapi::filesystem::block_special_file::id); device.set_driver_data(nullptr); } @@ -151,14 +151,14 @@ namespace kernel::drivers::storage return "Generic RAM Disk"; } - auto ram_disk::query_interface(kapi::devices::interface_id interface) -> void * + auto ram_disk::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == kapi::boot_modules::boot_module_claim::id) + if (facet == kapi::boot_modules::boot_module_claim::id) { return static_cast<kapi::boot_modules::boot_module_claim *>(this); } - return kapi::devices::driver::query_interface(interface); + return kapi::devices::driver::query_facet(facet); } } // namespace kernel::drivers::storage
\ No newline at end of file diff --git a/kernel/kernel/drivers/storage/ram_disk.hpp b/kernel/kernel/drivers/storage/ram_disk.hpp index 2805466f..d5d54551 100644 --- a/kernel/kernel/drivers/storage/ram_disk.hpp +++ b/kernel/kernel/drivers/storage/ram_disk.hpp @@ -27,7 +27,7 @@ namespace kernel::drivers::storage [[nodiscard]] auto name() const noexcept -> std::string_view override; protected: - auto query_interface(kapi::devices::interface_id interface) -> void * override; + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; }; } // namespace kernel::drivers::storage diff --git a/kernel/kernel/filesystem/device_inode.cpp b/kernel/kernel/filesystem/device_inode.cpp index ce0ad3fe..4dcff4a1 100644 --- a/kernel/kernel/filesystem/device_inode.cpp +++ b/kernel/kernel/filesystem/device_inode.cpp @@ -42,7 +42,7 @@ namespace kernel::filesystem -> kstd::result<kstd::units::bytes> { if (auto block_device = - kapi::devices::interface_registry::get().resolve<kapi::filesystem::block_special_file>(*m_device)) + kapi::devices::facet_registry::get().resolve<kapi::filesystem::block_special_file>(*m_device)) { return devices::block_device_utils::read(*block_device, buffer, offset, size); } @@ -54,7 +54,7 @@ namespace kernel::filesystem -> kstd::result<kstd::units::bytes> { if (auto block_device = - kapi::devices::interface_registry::get().resolve<kapi::filesystem::block_special_file>(*m_device)) + kapi::devices::facet_registry::get().resolve<kapi::filesystem::block_special_file>(*m_device)) { return devices::block_device_utils::write(*block_device, buffer, offset, size); } diff --git a/kernel/kernel/filesystem/device_inode.tests.cpp b/kernel/kernel/filesystem/device_inode.tests.cpp index 5f409a79..59800531 100644 --- a/kernel/kernel/filesystem/device_inode.tests.cpp +++ b/kernel/kernel/filesystem/device_inode.tests.cpp @@ -172,7 +172,7 @@ SCENARIO("Device inode raw_device()", "[filesystem][device-inode]") CHECK(kernel::tests::devices::bind(*device, std::uint8_t{1})); - REQUIRE(kapi::devices::interface_registry::get().publish<kapi::filesystem::block_special_file>(device, "ram0")); + REQUIRE(kapi::devices::facet_registry::get().publish<kapi::filesystem::block_special_file>(device, "ram0")); auto inode = kernel::filesystem::device_inode{device}; diff --git a/kernel/kernel/filesystem/device_number_registry.cpp b/kernel/kernel/filesystem/device_number_registry.cpp index aca0c64c..d51a343a 100644 --- a/kernel/kernel/filesystem/device_number_registry.cpp +++ b/kernel/kernel/filesystem/device_number_registry.cpp @@ -29,28 +29,28 @@ namespace kernel::filesystem { if (!instance) { - instance.emplace(kapi::devices::interface_registry::get()); + instance.emplace(kapi::devices::facet_registry::get()); } return *instance; } - device_number_registry::device_number_registry(kapi::devices::interface_registry & interface_registry) - : m_interface_registry{&interface_registry} + device_number_registry::device_number_registry(kapi::devices::facet_registry & facet_registry) + : m_facet_registry{&facet_registry} { for (auto const & binding : file_type_bindings) { - for (auto const & published : interface_registry.all(binding.interface)) + for (auto const & published : facet_registry.all(binding.facet)) { - try_number(binding.interface, published); + try_number(binding.facet, published); } } - m_interface_registry->subscribe(*this); + m_facet_registry->subscribe(*this); } device_number_registry::~device_number_registry() { - m_interface_registry->unsubscribe(*this); + m_facet_registry->unsubscribe(*this); } auto device_number_registry::resolve(kapi::filesystem::device_number number, file_type type) const @@ -114,19 +114,18 @@ namespace kernel::filesystem m_observers.push_back(std::move(observer)); } - auto device_number_registry::on_interface_published(kapi::devices::interface_id interface, - kapi::devices::interface_registry::entry const & published) - -> void + auto device_number_registry::on_facet_published(kapi::capabilities::facet_id facet, + kapi::devices::facet_registry::entry const & published) -> void { - try_number(interface, published); + try_number(facet, published); } - auto device_number_registry::on_interface_withdrawn(kapi::devices::interface_id interface, - kapi::devices::device & device) -> void + auto device_number_registry::on_facet_withdrawn(kapi::capabilities::facet_id facet, kapi::devices::device & device) + -> void { - // Check if there even is a binding defined for the given interface. + // Check if there even is a binding defined for the given facet. auto binding = - std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.interface == interface; }); + std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.facet == facet; }); if (binding == std::ranges::cend(file_type_bindings)) { return; @@ -158,12 +157,12 @@ namespace kernel::filesystem }); } - auto device_number_registry::try_number(kapi::devices::interface_id interface, - kapi::devices::interface_registry::entry const & published) -> void + auto device_number_registry::try_number(kapi::capabilities::facet_id facet, + kapi::devices::facet_registry::entry const & published) -> void { - // Check if there even is a binding defined for the given interface. + // Check if there even is a binding defined for the given facet. auto binding = - std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.interface == interface; }); + std::ranges::find_if(file_type_bindings, [&](auto const & binding) { return binding.facet == facet; }); if (binding == std::ranges::cend(file_type_bindings)) { return; diff --git a/kernel/kernel/filesystem/device_number_registry.hpp b/kernel/kernel/filesystem/device_number_registry.hpp index 20a26c22..8ace3727 100644 --- a/kernel/kernel/filesystem/device_number_registry.hpp +++ b/kernel/kernel/filesystem/device_number_registry.hpp @@ -20,7 +20,7 @@ namespace kernel::filesystem struct device_number_registry_observer; //! A registry to assign stable device numbers to published devices. - struct device_number_registry final : kapi::devices::interface_registry_observer + struct device_number_registry final : kapi::devices::facet_registry_observer { //! A single numbered device. //! @@ -33,10 +33,10 @@ namespace kernel::filesystem kstd::weak_ptr<kapi::devices::device> device; }; - //! Construct a new device number registry, subscribing to the given interface registry. + //! Construct a new device number registry, subscribing to the given facet registry. //! - //! @param interface_registry The interface registry to back this device number registry. - explicit device_number_registry(kapi::devices::interface_registry & interface_registry); + //! @param facet_registry The facet registry to back this device number registry. + explicit device_number_registry(kapi::devices::facet_registry & facet_registry); //! Destroy this registry. ~device_number_registry() override; @@ -78,21 +78,20 @@ namespace kernel::filesystem auto subscribe(kstd::weak_ptr<device_number_registry_observer> observer) -> void; private: - auto on_interface_published(kapi::devices::interface_id interface, - kapi::devices::interface_registry::entry const & entry) -> void override; + auto on_facet_published(kapi::capabilities::facet_id facet, kapi::devices::facet_registry::entry const & entry) + -> void override; - auto on_interface_withdrawn(kapi::devices::interface_id interface, kapi::devices::device & device) -> void override; + auto on_facet_withdrawn(kapi::capabilities::facet_id facet, kapi::devices::device & device) -> void override; - auto try_number(kapi::devices::interface_id interface, kapi::devices::interface_registry::entry const & published) - -> void; + auto try_number(kapi::capabilities::facet_id facet, kapi::devices::facet_registry::entry const & published) -> void; - kstd::observer_ptr<kapi::devices::interface_registry> m_interface_registry; + kstd::observer_ptr<kapi::devices::facet_registry> m_facet_registry; mutable kstd::vector<entry> m_entries{}; kstd::flat_map<kapi::devices::driver const *, std::uint8_t> m_next_minor; kstd::vector<kstd::weak_ptr<device_number_registry_observer>> m_observers{}; }; - //! The interface for types interested in observing numbering transactions on a device number registry. + //! The facet for types interested in observing numbering transactions on a device number registry. struct device_number_registry_observer { //! Enable correct destruction through base pointers. diff --git a/kernel/kernel/filesystem/device_number_registry.tests.cpp b/kernel/kernel/filesystem/device_number_registry.tests.cpp index 3791a16e..865a6de9 100644 --- a/kernel/kernel/filesystem/device_number_registry.tests.cpp +++ b/kernel/kernel/filesystem/device_number_registry.tests.cpp @@ -22,13 +22,13 @@ using namespace kstd::units_literals; namespace { - auto make_bound_block_device(kapi::devices::interface_registry & interfaces, kstd::string const & name, + auto make_bound_block_device(kapi::devices::facet_registry & facets, kstd::string const & name, kstd::units::bytes block_size, std::optional<std::uint8_t> major) -> kstd::shared_ptr<kernel::tests::devices::block_device> { auto device = kstd::make_shared<kernel::tests::devices::block_device>(name, block_size); [[maybe_unused]] auto driver = kernel::tests::devices::bind(*device, major); - if (!interfaces.publish<kapi::filesystem::block_special_file>(device, name)) + if (!facets.publish<kapi::filesystem::block_special_file>(device, name)) { throw std::runtime_error{"failed to publish block device!"}; } @@ -39,8 +39,8 @@ namespace SCENARIO("Device number registry resolves and numbers published block devices", "[kernel][filesystem][device_number_registry]") { - auto interfaces = kapi::devices::interface_registry{}; - auto registry = kernel::filesystem::device_number_registry{interfaces}; + auto facets = kapi::devices::facet_registry{}; + auto registry = kernel::filesystem::device_number_registry{facets}; GIVEN("No devices have been published") { @@ -52,7 +52,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A single block device has been published, bound to a driver claiming major 1") { - auto device = make_bound_block_device(interfaces, "ram0", 512_B, std::uint8_t{1}); + auto device = make_bound_block_device(facets, "ram0", 512_B, std::uint8_t{1}); THEN("all() returns a vector with one element") { @@ -96,7 +96,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A device was published") { - auto device = make_bound_block_device(interfaces, "ram0", 512_B, std::uint8_t{1}); + auto device = make_bound_block_device(facets, "ram0", 512_B, std::uint8_t{1}); auto number = registry.number_of(*device); WHEN("destroying it with no further owner") @@ -112,8 +112,8 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("Two block-capable drivers claiming different majors") { - [[maybe_unused]] auto device_a = make_bound_block_device(interfaces, "ramA0", 512_B, std::uint8_t{1}); - [[maybe_unused]] auto device_b = make_bound_block_device(interfaces, "ramB0", 512_B, std::uint8_t{2}); + [[maybe_unused]] auto device_a = make_bound_block_device(facets, "ramA0", 512_B, std::uint8_t{1}); + [[maybe_unused]] auto device_b = make_bound_block_device(facets, "ramB0", 512_B, std::uint8_t{2}); THEN("their minors are numbered independently, starting at 0 for each driver") { @@ -134,7 +134,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A driver that never overrides claimed_major()") { - make_bound_block_device(interfaces, "unnumbered0", 512_B, std::nullopt); + make_bound_block_device(facets, "unnumbered0", 512_B, std::nullopt); THEN("it is never numbered, regardless of what it publishes") { @@ -145,7 +145,7 @@ SCENARIO("Device number registry resolves and numbers published block devices", GIVEN("A published device with no bound driver at all") { auto device = kstd::make_shared<kernel::tests::devices::block_device>("unbound0", 512_B); - CHECK(interfaces.publish<kapi::filesystem::block_special_file>(device, "unbound0")); + CHECK(facets.publish<kapi::filesystem::block_special_file>(device, "unbound0")); THEN("it is never numbered") { diff --git a/kernel/kernel/filesystem/file_type_bindings.hpp b/kernel/kernel/filesystem/file_type_bindings.hpp index d771f49c..ea52972b 100644 --- a/kernel/kernel/filesystem/file_type_bindings.hpp +++ b/kernel/kernel/filesystem/file_type_bindings.hpp @@ -11,16 +11,16 @@ namespace kernel::filesystem { - //! A binding between an interface, a posix special file type + //! A binding between a facet, a posix special file type struct file_type_binding // NOLINT(cppcoreguidelines-pro-type-member-init) { - kapi::filesystem::interface_id interface; + kapi::capabilities::facet_id facet; file_type posix_type; }; - //! Predefined bindings for interface + file type + //! Predefined bindings for facet + file type //! - //! This array associates published interfaces with files types. + //! This array associates published facets with files types. constexpr auto inline file_type_bindings = std::array{ file_type_binding{kapi::filesystem::block_special_file::id, file_type::block}, }; diff --git a/kernel/kernel/test_support/devices/block_device.cpp b/kernel/kernel/test_support/devices/block_device.cpp index 2cde621c..a92b095b 100644 --- a/kernel/kernel/test_support/devices/block_device.cpp +++ b/kernel/kernel/test_support/devices/block_device.cpp @@ -68,13 +68,13 @@ namespace kernel::tests::devices return kstd::units::bytes{data.size()}; } - auto block_device::query_interface(kapi::devices::interface_id interface) -> void * + auto block_device::query_facet(kapi::capabilities::facet_id facet) -> void * { - if (interface == kapi::filesystem::block_special_file::id) + if (facet == kapi::filesystem::block_special_file::id) { return static_cast<kapi::filesystem::block_special_file *>(this); } - return kapi::devices::device::query_interface(interface); + return kapi::devices::device::query_facet(facet); } } // namespace kernel::tests::devices
\ No newline at end of file diff --git a/kernel/kernel/test_support/devices/block_device.hpp b/kernel/kernel/test_support/devices/block_device.hpp index 9546b0cc..94201da1 100644 --- a/kernel/kernel/test_support/devices/block_device.hpp +++ b/kernel/kernel/test_support/devices/block_device.hpp @@ -28,7 +28,7 @@ namespace kernel::tests::devices kstd::vector<uint8_t> data{}; private: - [[nodiscard]] auto query_interface(kapi::devices::interface_id interface) -> void * override; + [[nodiscard]] auto query_facet(kapi::capabilities::facet_id facet) -> void * override; kstd::units::bytes m_block_size{}; }; diff --git a/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp index 3464c6e8..d5068565 100644 --- a/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp +++ b/kernel/kernel/test_support/filesystem/storage_boot_module_fixture.cpp @@ -104,8 +104,7 @@ namespace kernel::tests::filesystem m_boot_module_bus->add_child(kstd::make_shared<kapi::boot_modules::device>(i, module)); } - if (module_count > 0 && - kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id).empty()) + if (module_count > 0 && kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id).empty()) { throw std::runtime_error{"No RAM disk driver bound to any of the test fixture's boot modules."}; } @@ -128,7 +127,7 @@ namespace kernel::tests::filesystem } if (!module_names.empty() && - kapi::devices::interface_registry::get().all(kapi::filesystem::block_special_file::id).empty()) + kapi::devices::facet_registry::get().all(kapi::filesystem::block_special_file::id).empty()) { throw std::runtime_error{"No RAM disk driver bound to any of the test fixture's boot modules."}; } |
