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  | 
