aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/service/service.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/service.h')
-rw-r--r--src/core/hle/service/service.h133
1 files changed, 49 insertions, 84 deletions
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index e8bd8683ea..ea98897e79 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -7,11 +7,7 @@
#pragma once
#include <cstddef>
-#include <memory>
#include <mutex>
-#include <tuple>
-#include <type_traits>
-#include "frozen/map.h"
#include "common/container/unordered_map.h"
#include "common/common_types.h"
#include "core/hle/service/hle_ipc.h"
@@ -81,35 +77,30 @@ protected:
[[nodiscard]] virtual std::unique_lock<std::mutex> LockService() noexcept {
return std::unique_lock{lock_service};
}
-
- static constexpr u32 MakeVersionGate(std::tuple<u32, u32, u32> since, std::tuple<u32, u32, u32> until = {0, 0, 0}) {
- auto const [s_maj, s_min, s_pat] = since;
- auto const [u_maj, u_min, u_pat] = until;
- return (u_pat << 0) | (u_min << 4) | (u_maj << 8)
- | (s_pat << 16) | (s_min << 20) | (s_maj << 24);
- }
+private:
+ template <typename T>
+ friend class ServiceFramework;
struct FunctionInfoBase {
+ u32 expected_header;
HandlerFnP<ServiceFrameworkBase> handler_callback;
const char* name;
- u32 version_gating;
};
- static_assert(std::is_trivially_constructible_v<FunctionInfoBase>);
-private:
- template <typename T>
- friend class ServiceFramework;
- using InvokerFn = void(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member, HLERequestContext& ctx);
+ using InvokerFn = void(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member,
+ HLERequestContext& ctx);
- explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_, u32 max_sessions_, InvokerFn* handler_invoker_);
+ explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_,
+ u32 max_sessions_, InvokerFn* handler_invoker_);
~ServiceFrameworkBase() override;
- virtual std::optional<FunctionInfoBase> FindRequest(u32 key) = 0;
- virtual std::optional<FunctionInfoBase> FindRequestTipc(u32 key) = 0;
-
- void ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info, bool gated);
+ void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
+ void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n);
+ void ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info);
protected:
+ ::Common::unordered_map<u32, FunctionInfoBase> handlers;
+ ::Common::unordered_map<u32, FunctionInfoBase> handlers_tipc;
/// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
std::mutex lock_service;
/// System context that the service operates under.
@@ -130,7 +121,8 @@ protected:
/**
* Framework for implementing HLE services. Dispatches on the header id of incoming SyncRequests
* based on a table mapping header ids to handler functions. Service implementations should inherit
- * from ServiceFramework using the CRTP (`class Foo : public ServiceFramework<Foo> { ... };`)
+ * from ServiceFramework using the CRTP (`class Foo : public ServiceFramework<Foo> { ... };`) and
+ * populate it with handlers by calling #RegisterHandlers.
*
* In order to avoid duplicating code in the binary and exposing too many implementation details in
* the header, this class is split into a non-templated base (ServiceFrameworkBase) and a template
@@ -151,77 +143,50 @@ protected:
/// @param expected_header_ request header in the command buffer which will trigger dispatch to this handler
/// @param handler_callback_ member function in this service which will be called to handle the request
/// @param name_ human-friendly name for the request. Used mostly for logging purposes.
- explicit constexpr FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_, u32 version_gating_ = 0)
- : handler_callback{handler_callback_}
- , name{name_}
- , version_gating{version_gating_}
- , expected_header{expected_header_}
- {}
- HandlerFnP<T> handler_callback;
- const char* name;
- u32 version_gating;
- u32 expected_header;
+ FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_)
+ : FunctionInfoBase{expected_header_, HandlerFnP<ServiceFrameworkBase>(handler_callback_), name_} {}
};
using FunctionInfo = FunctionInfoTyped<Self>;
- // expected_header serves as a key to 'address' function handlers, thus only include the minimal
- template <typename T>
- struct FunctionValueInfo {
- explicit constexpr FunctionValueInfo(HandlerFnP<T> handler_callback_, const char* name_, u32 version_gating_)
- : handler_callback{handler_callback_}
- , name{name_}
- , version_gating{version_gating_}
- {}
- HandlerFnP<T> handler_callback;
- const char* name;
- u32 version_gating;
- };
+ /**
+ * Initializes the handler with no functions installed.
+ *
+ * @param system_ The system context to construct this service under.
+ * @param service_name_ Name of the service.
+ * @param max_sessions_ Maximum number of sessions that can be connected to this service at the
+ * same time.
+ */
+ explicit ServiceFramework(Core::System& system_, const char* service_name_, u32 max_sessions_ = ServerSessionCountMax)
+ : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {}
- template<typename ...Ts>
- //requires (std::same_as<Ts, FunctionInfo> && ...)
- [[nodiscard]] static consteval frozen::map<u32, FunctionValueInfo<Self>, sizeof...(Ts)> CreateStaticMap(Ts... args) {
- return frozen::map<u32, FunctionValueInfo<Self>, sizeof...(args)>{
- {args.expected_header, FunctionValueInfo<Self>{args.handler_callback, args.name, args.version_gating}}...
- };
+ /// Registers handlers in the service.
+ template <typename T = Self, std::size_t N>
+ void RegisterHandlers(const FunctionInfoTyped<T> (&functions)[N]) {
+ RegisterHandlers(functions, N);
}
- // Used exclusively by NFC
- template<typename T, typename ...Ts>
- //requires (std::same_as<Ts, FunctionInfoTyped<T>> && ...)
- [[nodiscard]] static consteval frozen::map<u32, FunctionValueInfo<T>, sizeof...(Ts)> CreateStaticMapWithClass(Ts... args) {
- return frozen::map<u32, FunctionValueInfo<T>, sizeof...(args)>{
- {args.expected_header, FunctionValueInfo<T>{args.handler_callback, args.name, args.version_gating}}...
- };
+ /**
+ * Registers handlers in the service. Usually prefer using the other RegisterHandlers
+ * overload in order to avoid needing to specify the array size.
+ */
+ template <typename T = Self>
+ void RegisterHandlers(const FunctionInfoTyped<T>* functions, std::size_t n) {
+ RegisterHandlersBase(functions, n);
}
- template<typename T>
- [[nodiscard]] static std::optional<FunctionInfoBase> HandlerTableGenerateWithFind(u32 key, T const& map) {
- auto const it = map.find(key);
- if (it != map.end()) {
- auto const r = it->second;
- return std::optional<FunctionInfoBase>{{
- HandlerFnP<ServiceFrameworkBase>(r.handler_callback),
- r.name,
- r.version_gating
- }};
- }
- return std::nullopt;
+ /// Registers handlers in the service.
+ template <typename T = Self, std::size_t N>
+ void RegisterHandlersTipc(const FunctionInfoTyped<T> (&functions)[N]) {
+ RegisterHandlersTipc(functions, N);
}
- /// @brief Initializes the handler with no functions installed.
- /// @param system_ The system context to construct this service under.
- /// @param service_name_ Name of the service.
- /// @param max_sessions_ Maximum number of sessions that can be connected to this service at the
- /// same time.
- explicit ServiceFramework(Core::System& system_, const char* service_name_, u32 max_sessions_ = ServerSessionCountMax)
- : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker)
- {}
-
- std::optional<FunctionInfoBase> FindRequest(u32 key) override {
- UNREACHABLE();
- }
- std::optional<FunctionInfoBase> FindRequestTipc(u32 key) override {
- UNREACHABLE();
+ /**
+ * Registers handlers in the service. Usually prefer using the other RegisterHandlers
+ * overload in order to avoid needing to specify the array size.
+ */
+ template <typename T = Self>
+ void RegisterHandlersTipc(const FunctionInfoTyped<T>* functions, std::size_t n) {
+ RegisterHandlersBaseTipc(functions, n);
}
protected: