summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.org>2025-01-25 15:20:01 +1000
committerZephyron <zephyron@citron-emu.org>2025-01-25 15:20:01 +1000
commit5ba970b574f6df377b57716781ec966a3c8feff1 (patch)
treefcc9a636db0c8277ef491dd4ecd1aad169b7ffc9 /src
parent58ed33dd9fe06b7a30238f5404deade11a927f9d (diff)
service: sm: Update to match official IPC interface
Updates the SM service implementation to better match the official "nn::sm::detail::IUserInterface" interface. Key changes include: - Replace Initialize with RegisterClient command (cmd 0) - Add DetachClient command implementation (cmd 4) - Update service name handling to use u64-encoded names - Add proper PID descriptor handling for RegisterClient/DetachClient - Add ResultNotAllowed error code - Update handler registration for both CMIF and TIPC This brings the implementation closer to the official documentation while maintaining compatibility with existing code. Refs: switchbrew.org/wiki/Services_API#sm:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/sm/sm.cpp40
-rw-r--r--src/core/hle/service/sm/sm.h2
2 files changed, 36 insertions, 6 deletions
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 1095dcf6c..14e0a03c8 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -22,6 +22,7 @@ constexpr Result ResultInvalidClient(ErrorModule::SM, 2);
constexpr Result ResultAlreadyRegistered(ErrorModule::SM, 4);
constexpr Result ResultInvalidServiceName(ErrorModule::SM, 6);
constexpr Result ResultNotRegistered(ErrorModule::SM, 7);
+constexpr Result ResultNotAllowed(ErrorModule::SM, 1);
ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {
controller_interface = std::make_unique<Controller>(kernel.System());
@@ -157,9 +158,10 @@ void SM::GetServiceTipc(HLERequestContext& ctx) {
}
static std::string PopServiceName(IPC::RequestParser& rp) {
- auto name_buf = rp.PopRaw<std::array<char, 8>>();
+ const u64 name_encoded = rp.PopRaw<u64>();
std::string result;
- for (const auto& c : name_buf) {
+ for (int i = 0; i < 8; i++) {
+ const char c = static_cast<char>((name_encoded >> (i * 8)) & 0xFF);
if (c >= ' ' && c <= '~') {
result.push_back(c);
}
@@ -250,22 +252,48 @@ void SM::UnregisterService(HLERequestContext& ctx) {
rb.Push(service_manager.UnregisterService(name));
}
+void SM::RegisterClient(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_SM, "called");
+
+ IPC::RequestParser rp{ctx};
+
+ // Read PID descriptor
+ rp.Skip(2, false); // Skip PID descriptor and reserved u64
+
+ ctx.GetManager()->SetIsInitializedForSm();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void SM::DetachClient(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_SM, "called");
+
+ IPC::RequestParser rp{ctx};
+ rp.Skip(2, false); // Skip PID descriptor and reserved u64
+
+ ctx.GetManager()->SetIsInitializedForSm();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
SM::SM(ServiceManager& service_manager_, Core::System& system_)
: ServiceFramework{system_, "sm:", 4},
service_manager{service_manager_}, kernel{system_.Kernel()} {
RegisterHandlers({
- {0, &SM::Initialize, "Initialize"},
+ {0, &SM::RegisterClient, "RegisterClient"},
{1, &SM::GetServiceCmif, "GetService"},
{2, &SM::RegisterServiceCmif, "RegisterService"},
{3, &SM::UnregisterService, "UnregisterService"},
- {4, nullptr, "DetachClient"},
+ {4, &SM::DetachClient, "DetachClient"},
});
RegisterHandlersTipc({
- {0, &SM::Initialize, "Initialize"},
+ {0, &SM::RegisterClient, "RegisterClient"},
{1, &SM::GetServiceTipc, "GetService"},
{2, &SM::RegisterServiceTipc, "RegisterService"},
{3, &SM::UnregisterService, "UnregisterService"},
- {4, nullptr, "DetachClient"},
+ {4, &SM::DetachClient, "DetachClient"},
});
}
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 32c218638..d73eac08e 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -38,12 +38,14 @@ public:
~SM() override;
private:
+ void RegisterClient(HLERequestContext& ctx);
void Initialize(HLERequestContext& ctx);
void GetServiceCmif(HLERequestContext& ctx);
void GetServiceTipc(HLERequestContext& ctx);
void RegisterServiceCmif(HLERequestContext& ctx);
void RegisterServiceTipc(HLERequestContext& ctx);
void UnregisterService(HLERequestContext& ctx);
+ void DetachClient(HLERequestContext& ctx);
Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx);
void RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_session_count,