mirror of
https://git.citron-emu.org/Citron/Citron.git
synced 2025-01-31 13:16:55 +01:00
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:
This commit is contained in:
parent
58ed33dd9f
commit
5ba970b574
2 changed files with 36 additions and 6 deletions
|
@ -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"},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue