aboutsummaryrefslogtreecommitdiff
path: root/kapi
diff options
context:
space:
mode:
Diffstat (limited to 'kapi')
-rw-r--r--kapi/kapi/boot_modules/device.hpp10
-rw-r--r--kapi/kapi/capabilities/facet_id.hpp36
-rw-r--r--kapi/kapi/capabilities/interface_id.hpp34
-rw-r--r--kapi/kapi/devices.hpp47
-rw-r--r--kapi/kapi/devices/bus.hpp14
-rw-r--r--kapi/kapi/devices/bus_protocol.hpp4
-rw-r--r--kapi/kapi/devices/device.hpp64
-rw-r--r--kapi/kapi/devices/driver.hpp40
-rw-r--r--kapi/kapi/devices/facet_registry.hpp305
-rw-r--r--kapi/kapi/devices/interface_id.hpp15
-rw-r--r--kapi/kapi/devices/interface_registry.hpp299
-rw-r--r--kapi/kapi/filesystem.hpp2
-rw-r--r--kapi/kapi/filesystem/block_special_file.hpp4
-rw-r--r--kapi/kapi/filesystem/character_special_file.hpp4
-rw-r--r--kapi/kapi/filesystem/interface_id.hpp15
-rw-r--r--kapi/kapi/test_support/devices.hpp2
16 files changed, 438 insertions, 457 deletions
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