diff options
-rw-r--r-- | src/core/hle/service/service.cpp | 5 | ||||
-rw-r--r-- | src/core/hle/service/sm/sm.cpp | 14 | ||||
-rw-r--r-- | src/core/hle/service/sm/sm.h | 10 | ||||
-rw-r--r-- | src/core/hle/service/sm/srv.cpp | 71 | ||||
-rw-r--r-- | src/core/hle/service/sm/srv.h | 26 |
5 files changed, 75 insertions, 51 deletions
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index f184736e0..d34968428 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -206,8 +206,9 @@ void AddService(Interface* interface_) { /// Initialize ServiceManager void Init() { - SM::g_service_manager = std::make_unique<SM::ServiceManager>(); - AddNamedPort(new SM::SRV); + SM::g_service_manager = std::make_shared<SM::ServiceManager>(); + SM::ServiceManager::InstallInterfaces(SM::g_service_manager); + AddNamedPort(new ERR::ERR_F); FS::ArchiveInit(); diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 361f7a0a9..5e7fc68f9 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -3,11 +3,13 @@ // Refer to the license.txt file included. #include <tuple> +#include "common/assert.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" #include "core/hle/kernel/server_port.h" #include "core/hle/result.h" #include "core/hle/service/sm/sm.h" +#include "core/hle/service/sm/srv.h" namespace Service { namespace SM { @@ -22,6 +24,14 @@ static ResultCode ValidateServiceName(const std::string& name) { return RESULT_SUCCESS; } +void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self) { + ASSERT(self->srv_interface.expired()); + + auto srv = std::make_shared<SRV>(self); + srv->InstallAsNamedPort(); + self->srv_interface = srv; +} + ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService( std::string name, unsigned int max_sessions) { @@ -30,7 +40,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService Kernel::SharedPtr<Kernel::ClientPort> client_port; std::tie(server_port, client_port) = Kernel::ServerPort::CreatePortPair(max_sessions, name); - registered_services.emplace(name, std::move(client_port)); + registered_services.emplace(std::move(name), std::move(client_port)); return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)); } @@ -53,7 +63,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ServiceManager::ConnectToSer return client_port->Connect(); } -std::unique_ptr<ServiceManager> g_service_manager; +std::shared_ptr<ServiceManager> g_service_manager; } // namespace SM } // namespace Service diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 5fac5455c..8f0dbf2db 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -20,6 +20,8 @@ class SessionRequestHandler; namespace Service { namespace SM { +class SRV; + constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(1, ErrorModule::SRV, ErrorSummary::WouldBlock, ErrorLevel::Temporary); // 0xD0406401 constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(2, ErrorModule::SRV, ErrorSummary::WouldBlock, @@ -33,17 +35,21 @@ constexpr ResultCode ERR_NAME_CONTAINS_NUL(7, ErrorModule::SRV, ErrorSummary::Wr class ServiceManager { public: + static void InstallInterfaces(std::shared_ptr<ServiceManager> self); + ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name, unsigned int max_sessions); ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name); ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ConnectToService(const std::string& name); private: - /// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. + std::weak_ptr<SRV> srv_interface; + + /// Map of registered services, retrieved using GetServicePort or ConnectToService. std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> registered_services; }; -extern std::unique_ptr<ServiceManager> g_service_manager; +extern std::shared_ptr<ServiceManager> g_service_manager; } // namespace SM } // namespace Service diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index 063b1b0fc..b8b62b068 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -20,8 +20,6 @@ namespace SM { constexpr int MAX_PENDING_NOTIFICATIONS = 16; -static Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore; - /** * SRV::RegisterClient service function * Inputs: @@ -31,8 +29,8 @@ static Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore; * 0: 0x00010040 * 1: ResultCode */ -static void RegisterClient(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void SRV::RegisterClient(Kernel::HLERequestContext& ctx) { + u32* cmd_buff = ctx.CommandBuffer(); if (cmd_buff[1] != IPC::CallingPidDesc()) { cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); // 0x40 @@ -54,8 +52,8 @@ static void RegisterClient(Interface* self) { * 2: Translation descriptor: 0x20 * 3: Handle to semaphore signaled on process notification */ -static void EnableNotification(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void SRV::EnableNotification(Kernel::HLERequestContext& ctx) { + u32* cmd_buff = ctx.CommandBuffer(); notification_semaphore = Kernel::Semaphore::Create(0, MAX_PENDING_NOTIFICATIONS, "SRV:Notification").Unwrap(); @@ -78,9 +76,9 @@ static void EnableNotification(Interface* self) { * 1: ResultCode * 3: Service handle */ -static void GetServiceHandle(Interface* self) { +void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { ResultCode res = RESULT_SUCCESS; - u32* cmd_buff = Kernel::GetCommandBuffer(); + u32* cmd_buff = ctx.CommandBuffer(); size_t name_len = cmd_buff[3]; if (name_len > Service::kMaxPortSize) { @@ -94,7 +92,7 @@ static void GetServiceHandle(Interface* self) { // TODO(yuriks): Permission checks go here - auto client_port = g_service_manager->GetServicePort(name); + auto client_port = service_manager->GetServicePort(name); if (client_port.Failed()) { cmd_buff[1] = client_port.Code().raw; LOG_ERROR(Service_SRV, "called service=%s, failed with code=0x%08X", name.c_str(), @@ -128,8 +126,8 @@ static void GetServiceHandle(Interface* self) { * 0: 0x00090040 * 1: ResultCode */ -static void Subscribe(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void SRV::Subscribe(Kernel::HLERequestContext& ctx) { + u32* cmd_buff = ctx.CommandBuffer(); u32 notification_id = cmd_buff[1]; @@ -147,8 +145,8 @@ static void Subscribe(Interface* self) { * 0: 0x000A0040 * 1: ResultCode */ -static void Unsubscribe(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void SRV::Unsubscribe(Kernel::HLERequestContext& ctx) { + u32* cmd_buff = ctx.CommandBuffer(); u32 notification_id = cmd_buff[1]; @@ -167,8 +165,8 @@ static void Unsubscribe(Interface* self) { * 0: 0x000C0040 * 1: ResultCode */ -static void PublishToSubscriber(Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void SRV::PublishToSubscriber(Kernel::HLERequestContext& ctx) { + u32* cmd_buff = ctx.CommandBuffer(); u32 notification_id = cmd_buff[1]; u8 flags = cmd_buff[2] & 0xFF; @@ -179,31 +177,28 @@ static void PublishToSubscriber(Interface* self) { flags); } -const Interface::FunctionInfo FunctionTable[] = { - {0x00010002, RegisterClient, "RegisterClient"}, - {0x00020000, EnableNotification, "EnableNotification"}, - {0x00030100, nullptr, "RegisterService"}, - {0x000400C0, nullptr, "UnregisterService"}, - {0x00050100, GetServiceHandle, "GetServiceHandle"}, - {0x000600C2, nullptr, "RegisterPort"}, - {0x000700C0, nullptr, "UnregisterPort"}, - {0x00080100, nullptr, "GetPort"}, - {0x00090040, Subscribe, "Subscribe"}, - {0x000A0040, Unsubscribe, "Unsubscribe"}, - {0x000B0000, nullptr, "ReceiveNotification"}, - {0x000C0080, PublishToSubscriber, "PublishToSubscriber"}, - {0x000D0040, nullptr, "PublishAndGetSubscriber"}, - {0x000E00C0, nullptr, "IsServiceRegistered"}, -}; - -SRV::SRV() { - Register(FunctionTable); - notification_semaphore = nullptr; +SRV::SRV(std::shared_ptr<ServiceManager> service_manager) + : ServiceFramework("srv:", 4), service_manager(std::move(service_manager)) { + static const FunctionInfo functions[] = { + {0x00010002, &SRV::RegisterClient, "RegisterClient"}, + {0x00020000, &SRV::EnableNotification, "EnableNotification"}, + {0x00030100, nullptr, "RegisterService"}, + {0x000400C0, nullptr, "UnregisterService"}, + {0x00050100, &SRV::GetServiceHandle, "GetServiceHandle"}, + {0x000600C2, nullptr, "RegisterPort"}, + {0x000700C0, nullptr, "UnregisterPort"}, + {0x00080100, nullptr, "GetPort"}, + {0x00090040, &SRV::Subscribe, "Subscribe"}, + {0x000A0040, &SRV::Unsubscribe, "Unsubscribe"}, + {0x000B0000, nullptr, "ReceiveNotification"}, + {0x000C0080, &SRV::PublishToSubscriber, "PublishToSubscriber"}, + {0x000D0040, nullptr, "PublishAndGetSubscriber"}, + {0x000E00C0, nullptr, "IsServiceRegistered"}, + }; + RegisterHandlers(functions); } -SRV::~SRV() { - notification_semaphore = nullptr; -} +SRV::~SRV() = default; } // namespace SM } // namespace Service diff --git a/src/core/hle/service/sm/srv.h b/src/core/hle/service/sm/srv.h index 4196ca1e2..75cca5184 100644 --- a/src/core/hle/service/sm/srv.h +++ b/src/core/hle/service/sm/srv.h @@ -4,21 +4,33 @@ #pragma once -#include <string> +#include "core/hle/kernel/kernel.h" #include "core/hle/service/service.h" +namespace Kernel { +class HLERequestContext; +class Semaphore; +} + namespace Service { namespace SM { /// Interface to "srv:" service -class SRV final : public Interface { +class SRV final : public ServiceFramework<SRV> { public: - SRV(); - ~SRV() override; + explicit SRV(std::shared_ptr<ServiceManager> service_manager); + ~SRV(); + +private: + void RegisterClient(Kernel::HLERequestContext& ctx); + void EnableNotification(Kernel::HLERequestContext& ctx); + void GetServiceHandle(Kernel::HLERequestContext& ctx); + void Subscribe(Kernel::HLERequestContext& ctx); + void Unsubscribe(Kernel::HLERequestContext& ctx); + void PublishToSubscriber(Kernel::HLERequestContext& ctx); - std::string GetPortName() const override { - return "srv:"; - } + std::shared_ptr<ServiceManager> service_manager; + Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore; }; } // namespace SM |