mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-02 23:59:49 -04:00
Stratosphere: Implement support for deferred commands. Finish sm GetService()'s deferred path.
This commit is contained in:
parent
809090e40d
commit
674528b246
16 changed files with 137 additions and 27 deletions
|
@ -18,6 +18,11 @@ Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_
|
|||
return rc;
|
||||
}
|
||||
|
||||
Result ManagerService::handle_deferred() {
|
||||
/* This service is never deferrable. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::tuple<Result> ManagerService::register_process(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac) {
|
||||
return std::make_tuple(Registration::RegisterProcess(pid, acid_sac.buffer, acid_sac.num_elements, aci0_sac.buffer, aci0_sac.num_elements));
|
||||
|
|
|
@ -9,7 +9,8 @@ enum ManagerServiceCmd {
|
|||
|
||||
class ManagerService : IServiceObject {
|
||||
public:
|
||||
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
|
||||
virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
|
||||
virtual Result handle_deferred();
|
||||
|
||||
private:
|
||||
/* Actual commands. */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <switch.h>
|
||||
#include <algorithm>
|
||||
#include <stratosphere/servicesession.hpp>
|
||||
#include "sm_registration.hpp"
|
||||
|
||||
static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0};
|
||||
|
@ -132,6 +133,24 @@ bool Registration::HasService(u64 service) {
|
|||
return false;
|
||||
}
|
||||
|
||||
Result Registration::GetServiceHandle(u64 service, Handle *out) {
|
||||
Registration::Service *target_service = GetService(service);
|
||||
if (target_service == NULL) {
|
||||
/* Note: This defers the result until later. */
|
||||
return RESULT_DEFER_SESSION;
|
||||
}
|
||||
|
||||
*out = 0;
|
||||
Result rc = svcConnectToPort(out, target_service->port_h);
|
||||
if (R_FAILED(rc)) {
|
||||
if ((rc & 0x3FFFFF) == 0xE01) {
|
||||
return 0x615;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result Registration::GetServiceForPid(u64 pid, u64 service, Handle *out) {
|
||||
if (!service) {
|
||||
return 0xC15;
|
||||
|
@ -158,20 +177,7 @@ Result Registration::GetServiceForPid(u64 pid, u64 service, Handle *out) {
|
|||
}
|
||||
}
|
||||
|
||||
Registration::Service *target_service = GetService(service);
|
||||
if (target_service == NULL) {
|
||||
/* TODO: This defers the request, somehow? Needs to be RE'd in more detail. */
|
||||
return 0x6580A;
|
||||
}
|
||||
|
||||
*out = 0;
|
||||
Result rc = svcConnectToPort(out, target_service->port_h);
|
||||
if (R_FAILED(rc)) {
|
||||
if ((rc & 0x3FFFFF) == 0xE01) {
|
||||
return 0x615;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
return GetServiceHandle(service, out);
|
||||
}
|
||||
|
||||
Result Registration::RegisterServiceForPid(u64 pid, u64 service, u64 max_sessions, bool is_light, Handle *out) {
|
||||
|
|
|
@ -34,6 +34,7 @@ class Registration {
|
|||
|
||||
/* Service management. */
|
||||
static bool HasService(u64 service);
|
||||
static Result GetServiceHandle(u64 service, Handle *out);
|
||||
static Result GetServiceForPid(u64 pid, u64 service, Handle *out);
|
||||
static Result RegisterServiceForPid(u64 pid, u64 service, u64 max_sessions, bool is_light, Handle *out);
|
||||
static Result RegisterServiceForSelf(u64 service, u64 max_sessions, bool is_light, Handle *out);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <switch.h>
|
||||
#include <stratosphere/servicesession.hpp>
|
||||
#include "sm_user_service.hpp"
|
||||
#include "sm_registration.hpp"
|
||||
|
||||
|
@ -24,6 +25,11 @@ Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id,
|
|||
return rc;
|
||||
}
|
||||
|
||||
Result UserService::handle_deferred() {
|
||||
/* If we're deferred, GetService failed. */
|
||||
return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);
|
||||
}
|
||||
|
||||
|
||||
std::tuple<Result> UserService::initialize(PidDescriptor pid) {
|
||||
this->pid = pid.pid;
|
||||
|
@ -37,6 +43,16 @@ std::tuple<Result, MovedHandle> UserService::get_service(u64 service) {
|
|||
if (this->has_initialized) {
|
||||
rc = Registration::GetServiceForPid(this->pid, service, &session_h);
|
||||
}
|
||||
/* It's possible that this will end up deferring us...take that into account. */
|
||||
if (rc == RESULT_DEFER_SESSION) {
|
||||
this->deferred_service = service;
|
||||
}
|
||||
return std::make_tuple(rc, MovedHandle{session_h});
|
||||
}
|
||||
|
||||
std::tuple<Result, MovedHandle> UserService::deferred_get_service(u64 service) {
|
||||
Handle session_h = 0;
|
||||
Result rc = Registration::GetServiceHandle(service, &session_h);
|
||||
return std::make_tuple(rc, MovedHandle{session_h});
|
||||
}
|
||||
|
||||
|
|
|
@ -12,15 +12,18 @@ enum UserServiceCmd {
|
|||
class UserService : IServiceObject {
|
||||
u64 pid;
|
||||
bool has_initialized;
|
||||
u64 deferred_service;
|
||||
|
||||
public:
|
||||
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
|
||||
UserService() : pid(U64_MAX), has_initialized(false) { }
|
||||
UserService() : pid(U64_MAX), has_initialized(false), deferred_service(0) { }
|
||||
virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
|
||||
virtual Result handle_deferred();
|
||||
|
||||
private:
|
||||
/* Actual commands. */
|
||||
std::tuple<Result> initialize(PidDescriptor pid);
|
||||
std::tuple<Result, MovedHandle> get_service(u64 service);
|
||||
std::tuple<Result, MovedHandle> deferred_get_service(u64 service);
|
||||
std::tuple<Result, MovedHandle> register_service(u64 service, u8 is_light, u32 max_sessions);
|
||||
std::tuple<Result> unregister_service(u64 service);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue