summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/sm/sm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/sm/sm.cpp')
-rw-r--r--src/core/hle/service/sm/sm.cpp67
1 files changed, 59 insertions, 8 deletions
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 464e79d01..142929124 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -54,13 +54,22 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService
return ERR_ALREADY_REGISTERED;
auto& kernel = Core::System::GetInstance().Kernel();
- Kernel::SharedPtr<Kernel::ServerPort> server_port;
- Kernel::SharedPtr<Kernel::ClientPort> client_port;
- std::tie(server_port, client_port) =
+ auto [server_port, client_port] =
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, name);
registered_services.emplace(std::move(name), std::move(client_port));
- return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port));
+ return MakeResult(std::move(server_port));
+}
+
+ResultCode ServiceManager::UnregisterService(const std::string& name) {
+ CASCADE_CODE(ValidateServiceName(name));
+
+ const auto iter = registered_services.find(name);
+ if (iter == registered_services.end())
+ return ERR_SERVICE_NOT_REGISTERED;
+
+ registered_services.erase(iter);
+ return RESULT_SUCCESS;
}
ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> ServiceManager::GetServicePort(
@@ -72,7 +81,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> ServiceManager::GetServicePort(
return ERR_SERVICE_NOT_REGISTERED;
}
- return MakeResult<Kernel::SharedPtr<Kernel::ClientPort>>(it->second);
+ return MakeResult(it->second);
}
ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ServiceManager::ConnectToService(
@@ -92,9 +101,10 @@ SM::~SM() = default;
* 0: ResultCode
*/
void SM::Initialize(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_SM, "called");
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
- LOG_DEBUG(Service_SM, "called");
}
void SM::GetService(Kernel::HLERequestContext& ctx) {
@@ -127,13 +137,54 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
}
}
+void SM::RegisterService(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ const auto name_buf = rp.PopRaw<std::array<char, 8>>();
+ const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
+
+ const std::string name(name_buf.begin(), end);
+
+ const auto is_light = static_cast<bool>(rp.PopRaw<u32>());
+ const auto max_session_count = rp.PopRaw<u32>();
+
+ LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name,
+ max_session_count, is_light);
+
+ auto handle = service_manager->RegisterService(name, max_session_count);
+ if (handle.Failed()) {
+ LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}",
+ handle.Code().raw);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(handle.Code());
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
+ rb.Push(handle.Code());
+ rb.PushMoveObjects(std::move(handle).Unwrap());
+}
+
+void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ const auto name_buf = rp.PopRaw<std::array<char, 8>>();
+ const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
+
+ const std::string name(name_buf.begin(), end);
+ LOG_DEBUG(Service_SM, "called with name={}", name);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(service_manager->UnregisterService(name));
+}
+
SM::SM(std::shared_ptr<ServiceManager> service_manager)
: ServiceFramework("sm:", 4), service_manager(std::move(service_manager)) {
static const FunctionInfo functions[] = {
{0x00000000, &SM::Initialize, "Initialize"},
{0x00000001, &SM::GetService, "GetService"},
- {0x00000002, nullptr, "RegisterService"},
- {0x00000003, nullptr, "UnregisterService"},
+ {0x00000002, &SM::RegisterService, "RegisterService"},
+ {0x00000003, &SM::UnregisterService, "UnregisterService"},
};
RegisterHandlers(functions);
}