2026-09-25 15:39:00

Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie
2026-09-25 15:39:00 +00:00
parent f273423b2b
commit aa8fd1b647
7 changed files with 226 additions and 166 deletions
+105 -109
View File
@@ -75,41 +75,6 @@ class IManagerForSystemService final : public ServiceFramework<IManagerForSystem
public:
explicit IManagerForSystemService(Core::System& system_, Common::UUID uuid)
: ServiceFramework{system_, "IManagerForSystemService"}, account_id{uuid} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IManagerForSystemService::CheckAvailability>, "CheckAvailability"},
{1, D<&IManagerForSystemService::GetAccountId>, "GetAccountId"},
{2, nullptr, "EnsureIdTokenCacheAsync"},
{3, D<&IManagerForSystemService::LoadIdTokenCacheDeprecated>, "LoadIdTokenCacheDeprecated"}, // 19.0.0+
{4, D<&IManagerForSystemService::LoadIdTokenCache>, "LoadIdTokenCache"}, // 19.0.0+
{100, nullptr, "SetSystemProgramIdentification"},
{101, nullptr, "RefreshNotificationTokenAsync"}, // 7.0.0+
{110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+
{111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+
{112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0
{113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+
{120, nullptr, "GetNintendoAccountId"},
{121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+
{130, nullptr, "GetNintendoAccountUserResourceCache"},
{131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"},
{132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"},
{133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+
{134, nullptr, "RefreshNintendoAccountVerificationUrlCache"}, // 9.0.0+
{135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+
{136, nullptr, "GetNintendoAccountUserResourceCache"}, // 19.0.0+
{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
{143, D<&IManagerForSystemService::GetNetworkServiceLicenseCacheEx>, "GetNetworkServiceLicenseCacheEx"}, // 15.0.0+
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
{170, nullptr, "CreateDeviceHistoryRequest"}, // 17.0.0+
{180, nullptr, "GetRequestForNintendoAccountReauthentication"} // 18.0.0+
};
// clang-format on
RegisterHandlers(functions);
}
private:
@@ -143,6 +108,39 @@ private:
R_SUCCEED();
}
FunctionInfoBase const* FindRequest(u32 key) override {
return HandlerTableGenerateWithFind(key,
FunctionInfo{0, D<&IManagerForSystemService::CheckAvailability>, "CheckAvailability"},
FunctionInfo{1, D<&IManagerForSystemService::GetAccountId>, "GetAccountId"},
FunctionInfo{2, nullptr, "EnsureIdTokenCacheAsync"},
FunctionInfo{3, D<&IManagerForSystemService::LoadIdTokenCacheDeprecated>, "LoadIdTokenCacheDeprecated"}, // 19.0.0+
FunctionInfo{4, D<&IManagerForSystemService::LoadIdTokenCache>, "LoadIdTokenCache"}, // 19.0.0+
FunctionInfo{100, nullptr, "SetSystemProgramIdentification"},
FunctionInfo{101, nullptr, "RefreshNotificationTokenAsync"}, // 7.0.0+
FunctionInfo{110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+
FunctionInfo{111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+
FunctionInfo{112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0
FunctionInfo{113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+
FunctionInfo{120, nullptr, "GetNintendoAccountId"},
FunctionInfo{121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+
FunctionInfo{130, nullptr, "GetNintendoAccountUserResourceCache"},
FunctionInfo{131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"},
FunctionInfo{132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"},
FunctionInfo{133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+
FunctionInfo{134, nullptr, "RefreshNintendoAccountVerificationUrlCache"}, // 9.0.0+
FunctionInfo{135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+
FunctionInfo{136, nullptr, "GetNintendoAccountUserResourceCache"}, // 19.0.0+
FunctionInfo{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
FunctionInfo{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
FunctionInfo{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
FunctionInfo{143, D<&IManagerForSystemService::GetNetworkServiceLicenseCacheEx>, "GetNetworkServiceLicenseCacheEx"}, // 15.0.0+
FunctionInfo{150, nullptr, "CreateAuthorizationRequest"},
FunctionInfo{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
FunctionInfo{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
FunctionInfo{170, nullptr, "CreateDeviceHistoryRequest"}, // 17.0.0+
FunctionInfo{180, nullptr, "GetRequestForNintendoAccountReauthentication"} // 18.0.0+
);
}
Common::UUID account_id;
};
@@ -151,25 +149,24 @@ class IFloatingRegistrationRequest final : public ServiceFramework<IFloatingRegi
public:
explicit IFloatingRegistrationRequest(Core::System& system_, Common::UUID)
: ServiceFramework{system_, "IFloatingRegistrationRequest"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetSessionId"},
{12, nullptr, "GetAccountId"},
{13, nullptr, "GetLinkedNintendoAccountId"},
{14, nullptr, "GetNickname"},
{15, nullptr, "GetProfileImage"},
{16, nullptr, "GetProfileLargeImage"}, // 18.0.0+
{21, nullptr, "LoadIdTokenCache"},
{100, nullptr, "RegisterUser"}, // [1.0.0-3.0.2] RegisterAsync
{101, nullptr, "RegisterUserWithUid"}, // [1.0.0-3.0.2] RegisterWithUidAsync
{102, nullptr, "RegisterNetworkServiceAccountAsync"}, // 4.0.0+
{103, nullptr, "RegisterNetworkServiceAccountWithUidAsync"}, // 4.0.0+
{110, nullptr, "SetSystemProgramIdentification"},
{111, nullptr, "EnsureIdTokenCacheAsync"},
};
// clang-format on
}
RegisterHandlers(functions);
FunctionInfoBase const* FindRequest(u32 key) override {
return HandlerTableGenerateWithFind(key,
FunctionInfo{0, nullptr, "GetSessionId"},
FunctionInfo{12, nullptr, "GetAccountId"},
FunctionInfo{13, nullptr, "GetLinkedNintendoAccountId"},
FunctionInfo{14, nullptr, "GetNickname"},
FunctionInfo{15, nullptr, "GetProfileImage"},
FunctionInfo{16, nullptr, "GetProfileLargeImage", MakeVersionGate({18,0,0})},
FunctionInfo{21, nullptr, "LoadIdTokenCache"},
FunctionInfo{100, nullptr, "RegisterUser"}, // [1.0.0-3.0.2] RegisterAsync
FunctionInfo{101, nullptr, "RegisterUserWithUid"}, // [1.0.0-3.0.2] RegisterWithUidAsync
FunctionInfo{102, nullptr, "RegisterNetworkServiceAccountAsync", MakeVersionGate({4,0,0})},
FunctionInfo{103, nullptr, "RegisterNetworkServiceAccountWithUidAsync", MakeVersionGate({4,0,0})},
FunctionInfo{110, nullptr, "SetSystemProgramIdentification"},
FunctionInfo{111, nullptr, "EnsureIdTokenCacheAsync"}
);
}
};
@@ -177,62 +174,6 @@ class IAdministrator final : public ServiceFramework<IAdministrator> {
public:
explicit IAdministrator(Core::System& system_, Common::UUID)
: ServiceFramework{system_, "IAdministrator"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "CheckAvailability"},
{1, nullptr, "GetAccountId"},
{2, nullptr, "EnsureIdTokenCacheAsync"},
{3, nullptr, "LoadIdTokenCache"},
{100, nullptr, "SetSystemProgramIdentification"},
{101, nullptr, "RefreshNotificationTokenAsync"}, // 7.0.0+
{110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+
{111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+
{112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0
{113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+
{120, nullptr, "GetNintendoAccountId"},
{121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+
{130, nullptr, "GetNintendoAccountUserResourceCache"},
{131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"},
{132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"},
{133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+
{134, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsync"}, // 9.0.0+
{135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+
{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
{143, nullptr, "GetNetworkServiceLicenseCacheEx"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
{170, nullptr, "CreateDeviceHistoryRequest"}, // 17.0.0+
{180, nullptr, "GetRequestForNintendoAccountReauthentication"}, // 18.0.0+
{200, nullptr, "IsRegistered"},
{201, nullptr, "RegisterAsync"},
{202, nullptr, "UnregisterAsync"},
{203, nullptr, "DeleteRegistrationInfoLocally"},
{220, nullptr, "SynchronizeProfileAsync"},
{221, nullptr, "UploadProfileAsync"},
{222, nullptr, "SynchronizaProfileAsyncIfSecondsElapsed"},
{250, &IAdministrator::IsLinkedWithNintendoAccount, "IsLinkedWithNintendoAccount"},
{251, nullptr, "CreateProcedureToLinkWithNintendoAccount"},
{252, nullptr, "ResumeProcedureToLinkWithNintendoAccount"},
{255, nullptr, "CreateProcedureToUpdateLinkageStateOfNintendoAccount"},
{256, nullptr, "ResumeProcedureToUpdateLinkageStateOfNintendoAccount"},
{260, nullptr, "CreateProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+
{261, nullptr, "ResumeProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+
{280, nullptr, "ProxyProcedureToAcquireApplicationAuthorizationForNintendoAccount"},
{290, nullptr, "GetRequestForNintendoAccountUserResourceView"}, // 8.0.0+
{300, nullptr, "TryRecoverNintendoAccountUserStateAsync"}, // 6.0.0+
{400, nullptr, "IsServiceEntryRequirementCacheRefreshRequiredForOnlinePlay"}, // 6.1.0+
{401, nullptr, "RefreshServiceEntryRequirementCacheForOnlinePlayAsync"}, // 6.1.0+
{900, nullptr, "GetAuthenticationInfoForWin"}, // 9.0.0+
{901, nullptr, "ImportAsyncForWin"}, // 9.0.0+
{997, nullptr, "DebugUnlinkNintendoAccountAsync"},
{998, nullptr, "DebugSetAvailabilityErrorDetail"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
@@ -241,6 +182,61 @@ private:
rb.Push(ResultSuccess);
rb.Push(false);
}
FunctionInfoBase const* FindRequest(u32 key) override {
return HandlerTableGenerateWithFind(key,
FunctionInfo{0, nullptr, "CheckAvailability"},
FunctionInfo{1, nullptr, "GetAccountId"},
FunctionInfo{2, nullptr, "EnsureIdTokenCacheAsync"},
FunctionInfo{3, nullptr, "LoadIdTokenCache"},
FunctionInfo{100, nullptr, "SetSystemProgramIdentification"},
FunctionInfo{101, nullptr, "RefreshNotificationTokenAsync", MakeVersionGate({7,0,0})},
FunctionInfo{110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+
FunctionInfo{111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+
FunctionInfo{112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0
FunctionInfo{113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+
FunctionInfo{120, nullptr, "GetNintendoAccountId"},
FunctionInfo{121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+
FunctionInfo{130, nullptr, "GetNintendoAccountUserResourceCache"},
FunctionInfo{131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"},
FunctionInfo{132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"},
FunctionInfo{133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+
FunctionInfo{134, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsync"}, // 9.0.0+
FunctionInfo{135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+
FunctionInfo{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
FunctionInfo{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
FunctionInfo{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
FunctionInfo{143, nullptr, "GetNetworkServiceLicenseCacheEx"},
FunctionInfo{150, nullptr, "CreateAuthorizationRequest"},
FunctionInfo{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
FunctionInfo{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
FunctionInfo{170, nullptr, "CreateDeviceHistoryRequest"}, // 17.0.0+
FunctionInfo{180, nullptr, "GetRequestForNintendoAccountReauthentication"}, // 18.0.0+
FunctionInfo{200, nullptr, "IsRegistered"},
FunctionInfo{201, nullptr, "RegisterAsync"},
FunctionInfo{202, nullptr, "UnregisterAsync"},
FunctionInfo{203, nullptr, "DeleteRegistrationInfoLocally"},
FunctionInfo{220, nullptr, "SynchronizeProfileAsync"},
FunctionInfo{221, nullptr, "UploadProfileAsync"},
FunctionInfo{222, nullptr, "SynchronizaProfileAsyncIfSecondsElapsed"},
FunctionInfo{250, &IAdministrator::IsLinkedWithNintendoAccount, "IsLinkedWithNintendoAccount"},
FunctionInfo{251, nullptr, "CreateProcedureToLinkWithNintendoAccount"},
FunctionInfo{252, nullptr, "ResumeProcedureToLinkWithNintendoAccount"},
FunctionInfo{255, nullptr, "CreateProcedureToUpdateLinkageStateOfNintendoAccount"},
FunctionInfo{256, nullptr, "ResumeProcedureToUpdateLinkageStateOfNintendoAccount"},
FunctionInfo{260, nullptr, "CreateProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+
FunctionInfo{261, nullptr, "ResumeProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+
FunctionInfo{280, nullptr, "ProxyProcedureToAcquireApplicationAuthorizationForNintendoAccount"},
FunctionInfo{290, nullptr, "GetRequestForNintendoAccountUserResourceView"}, // 8.0.0+
FunctionInfo{300, nullptr, "TryRecoverNintendoAccountUserStateAsync"}, // 6.0.0+
FunctionInfo{400, nullptr, "IsServiceEntryRequirementCacheRefreshRequiredForOnlinePlay"}, // 6.1.0+
FunctionInfo{401, nullptr, "RefreshServiceEntryRequirementCacheForOnlinePlayAsync"}, // 6.1.0+
FunctionInfo{900, nullptr, "GetAuthenticationInfoForWin"}, // 9.0.0+
FunctionInfo{901, nullptr, "ImportAsyncForWin"}, // 9.0.0+
FunctionInfo{997, nullptr, "DebugUnlinkNintendoAccountAsync"},
FunctionInfo{998, nullptr, "DebugSetAvailabilityErrorDetail"}
);
}
};
class IAuthorizationRequest final : public ServiceFramework<IAuthorizationRequest> {
+4 -29
View File
@@ -47,22 +47,7 @@ ServiceFrameworkBase::~ServiceFrameworkBase() {
const auto guard = ServiceFrameworkBase::LockService();
}
void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
// Usually this array is sorted by id already, so hint to insert at the end
handlers.reserve(handlers.size() + n);
for (std::size_t i = 0; i < n; ++i)
handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]);
}
void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n) {
// Usually this array is sorted by id already, so hint to insert at the end
handlers_tipc.reserve(handlers_tipc.size() + n);
for (std::size_t i = 0; i < n; ++i)
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, functions[i]);
}
void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
const FunctionInfoBase* info) {
void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, const FunctionInfoBase* info) {
auto cmd_buf = ctx.CommandBuffer();
std::string function_name = info == nullptr ? "<unknown>" : info->name;
@@ -82,16 +67,10 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
}
void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) {
const auto command = ctx.GetCommand();
auto it = handlers.find(command);
const bool is_cmd_read = command == 0;
FunctionInfoBase const* info = it == handlers.end() ? nullptr : &it->second;
if (info == nullptr || info->handler_callback == nullptr)
return ReportUnimplementedFunction(ctx, info);
const bool is_cmd_read = ctx.GetCommand() == 0;
auto const info = FindRequest(ctx.GetCommand());
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
handler_invoker(this, info->handler_callback, ctx);
if (is_i_storage && is_cmd_read) {
const auto* const process = ctx.GetThread().GetOwnerProcess();
if (process != nullptr && system.IsNVDECActiveForProcess(process->GetId())) {
@@ -101,11 +80,7 @@ void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) {
}
void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) {
auto it = handlers_tipc.find(ctx.GetCommand());
FunctionInfoBase const* info = it == handlers_tipc.end() ? nullptr : &it->second;
if (info == nullptr || info->handler_callback == nullptr)
return ReportUnimplementedFunction(ctx, info);
auto const info = FindRequestTipc(ctx.GetCommand());
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
handler_invoker(this, info->handler_callback, ctx);
}
+72 -24
View File
@@ -7,7 +7,10 @@
#pragma once
#include <cstddef>
#include <memory>
#include <mutex>
#include <tuple>
#include "frozen/map.h"
#include "common/container/unordered_map.h"
#include "common/common_types.h"
#include "core/hle/service/hle_ipc.h"
@@ -77,30 +80,37 @@ protected:
[[nodiscard]] virtual std::unique_lock<std::mutex> LockService() noexcept {
return std::unique_lock{lock_service};
}
private:
template <typename T>
friend class ServiceFramework;
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 << 12) | (s_min << 16) | (s_maj << 20);
}
struct FunctionInfoBase {
u32 expected_header;
HandlerFnP<ServiceFrameworkBase> handler_callback;
const char* name;
u32 version_gating;
};
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 FunctionInfoBase const* FindRequest(u32 key) = 0;
virtual FunctionInfoBase const* FindRequestTipc(u32 key) = 0;
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.
@@ -143,25 +153,60 @@ 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.
FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_)
: FunctionInfoBase{expected_header_, HandlerFnP<ServiceFrameworkBase>(handler_callback_), name_} {}
FunctionInfoTyped(u32 expected_header_, HandlerFnP<T> handler_callback_, const char* name_, u32 version_gating_ = 0)
: FunctionInfoBase{expected_header_, HandlerFnP<ServiceFrameworkBase>(handler_callback_), name_, version_gating_}
{}
};
using FunctionInfo = FunctionInfoTyped<Self>;
/**
* 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.
*/
template<typename ...Ts>
requires (std::same_as<Ts, FunctionInfo> && ...)
static FunctionInfoBase const* HandlerTableGenerateWithFind(u32 key, Ts... args) {
static auto const map = frozen::map<u32, FunctionInfo, sizeof...(args)>{
{args.expected_header, FunctionInfo(args)}...
};
auto const it = map.find(key);
return it != map.end() ? std::addressof(it->second) : nullptr;
}
/// @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) {}
: ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker)
{}
FunctionInfoBase const* FindRequest(u32 key) override {
auto it = handlers.find(key);
FunctionInfoBase const* info = it == handlers.end() ? nullptr : &it->second;
return !(info == nullptr || info->handler_callback == nullptr) ? info : nullptr;
}
FunctionInfoBase const* FindRequestTipc(u32 key) override {
auto it = handlers_tipc.find(key);
FunctionInfoBase const* info = it == handlers_tipc.end() ? nullptr : &it->second;
return !(info == nullptr || info->handler_callback == nullptr) ? info : nullptr;
}
constexpr void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
// Usually this array is sorted by id already, so hint to insert at the end
handlers.reserve(handlers.size() + n);
for (std::size_t i = 0; i < n; ++i)
handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]);
}
constexpr void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n) {
// Usually this array is sorted by id already, so hint to insert at the end
handlers_tipc.reserve(handlers_tipc.size() + n);
for (std::size_t i = 0; i < n; ++i)
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, functions[i]);
}
/// Registers handlers in the service.
template <typename T = Self, std::size_t N>
void RegisterHandlers(const FunctionInfoTyped<T> (&functions)[N]) {
constexpr void RegisterHandlers(const FunctionInfoTyped<T> (&functions)[N]) {
RegisterHandlers(functions, N);
}
@@ -170,13 +215,13 @@ protected:
* 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) {
constexpr void RegisterHandlers(const FunctionInfoTyped<T>* functions, std::size_t n) {
RegisterHandlersBase(functions, n);
}
/// Registers handlers in the service.
template <typename T = Self, std::size_t N>
void RegisterHandlersTipc(const FunctionInfoTyped<T> (&functions)[N]) {
constexpr void RegisterHandlersTipc(const FunctionInfoTyped<T> (&functions)[N]) {
RegisterHandlersTipc(functions, N);
}
@@ -185,7 +230,7 @@ protected:
* 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) {
constexpr void RegisterHandlersTipc(const FunctionInfoTyped<T>* functions, std::size_t n) {
RegisterHandlersBaseTipc(functions, n);
}
@@ -217,6 +262,9 @@ private:
// Cast back up to our original types and call the member function
(static_cast<Self*>(object)->*HandlerFnP<Self>(member))(ctx);
}
::Common::unordered_map<u32, FunctionInfoBase> handlers;
::Common::unordered_map<u32, FunctionInfoBase> handlers_tipc;
};
} // namespace Service