diff --git a/nx/include/switch/services/pctl.h b/nx/include/switch/services/pctl.h index d1fbed28..1e3181d9 100644 --- a/nx/include/switch/services/pctl.h +++ b/nx/include/switch/services/pctl.h @@ -6,12 +6,21 @@ */ #pragma once -#include "../kernel/ipc.h" -#include "../services/sm.h" +#include "../types.h" +#include "../sf/service.h" +/// Initialize pctl. Result pctlInitialize(void); + +/// Exit pctl. void pctlExit(void); +/// Gets the Service object for the actual pctl service session. +Service* pctlGetServiceSession(void); + +/// Gets the Service object for IParentalControlService. +Service* pctlGetServiceSession_Service(void); + /// Confirm whether VrMode is allowed. Only available with [4.0.0+]. Result pctlConfirmStereoVisionPermission(void); diff --git a/nx/source/services/pctl.c b/nx/source/services/pctl.c index 1a100760..181a4c19 100644 --- a/nx/source/services/pctl.c +++ b/nx/source/services/pctl.c @@ -1,23 +1,19 @@ +#include "service_guard.h" #include "services/pctl.h" -#include "arm/atomics.h" #include "runtime/hosversion.h" static Service g_pctlSrv; static Service g_pctlSession; -static u64 g_refCnt; -static Result _pctlCreateService(Service* out, u64 cmd_id); -static Result _pctlNoIO(u64 cmd_id); +static Result _pctlCreateService(Service* srv_out, u32 cmd_id); +static Result _pctlCmdNoIO(u32 cmd_id); -Result pctlInitialize(void) { +NX_GENERATE_SERVICE_GUARD(pctl); + +Result _pctlInitialize(void) { Result rc=0; bool sysverflag = hosversionBefore(4,0,0); - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_pctlSrv)) - return 0; - rc = smGetService(&g_pctlSrv, "pctl:a"); if (R_FAILED(rc)) rc = smGetService(&g_pctlSrv, "pctl:s"); if (R_FAILED(rc)) rc = smGetService(&g_pctlSrv, "pctl:r"); @@ -27,126 +23,48 @@ Result pctlInitialize(void) { if (R_SUCCEEDED(rc)) rc = _pctlCreateService(&g_pctlSession, sysverflag ? 0 : 1); - if (R_SUCCEEDED(rc) && !sysverflag) rc = _pctlNoIO(1); - - if (R_FAILED(rc)) - pctlExit(); + if (R_SUCCEEDED(rc) && !sysverflag) rc = _pctlCmdNoIO(1); return rc; } -void pctlExit(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_pctlSession); - serviceClose(&g_pctlSrv); - } +void _pctlCleanup(void) { + serviceClose(&g_pctlSession); + serviceClose(&g_pctlSrv); } -static Result _pctlCreateService(Service* out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid_reserved; - } *raw; - - raw = serviceIpcPrepareHeader(&g_pctlSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->pid_reserved = 0; - - Result rc = serviceIpcDispatch(&g_pctlSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_pctlSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - serviceCreateSubservice(out, &g_pctlSrv, &r, 0); - } - - return rc; +Service* pctlGetServiceSession(void) { + return &g_pctlSrv; } -static Result _pctlNoIO(u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_pctlSession, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_pctlSession); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_pctlSession, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +Service* pctlGetServiceSession_Service(void) { + return &g_pctlSession; } -static Result _pctlNoInputOutBool(u64 cmd_id, bool *flag) { - IpcCommand c; - ipcInitialize(&c); +static Result _pctlCreateService(Service* srv_out, u32 cmd_id) { + u64 pid_reserved=0; + serviceAssumeDomain(&g_pctlSrv); + return serviceDispatchIn(&g_pctlSrv, cmd_id, pid_reserved, + .in_send_pid = true, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; +static Result _pctlCmdNoIO(u32 cmd_id) { + serviceAssumeDomain(&g_pctlSession); + return serviceDispatch(&g_pctlSession, cmd_id); +} - raw = serviceIpcPrepareHeader(&g_pctlSession, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_pctlSession); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - u8 out; - } PACKED *resp; - - serviceIpcParse(&g_pctlSession, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && flag) *flag = resp->out!=0; - } +static Result _pctlCmdNoInOutU8(u8 *out, u32 cmd_id) { + serviceAssumeDomain(&g_pctlSession); + return serviceDispatchOut(&g_pctlSession, cmd_id, *out); +} +static Result _pctlCmdNoInOutBool(bool *out, u32 cmd_id) { + u8 tmp=0; + Result rc = _pctlCmdNoInOutU8(&tmp, cmd_id); + if (R_SUCCEEDED(rc) && out) *out = tmp!=0; return rc; } @@ -154,24 +72,24 @@ Result pctlConfirmStereoVisionPermission(void) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - return _pctlNoIO(1013); + return _pctlCmdNoIO(1013); } Result pctlIsRestrictionEnabled(bool *flag) { - return _pctlNoInputOutBool(1031, flag); + return _pctlCmdNoInOutBool(flag, 1031); } Result pctlResetConfirmedStereoVisionPermission(void) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - return _pctlNoIO(1064); + return _pctlCmdNoIO(1064); } Result pctlIsStereoVisionPermitted(bool *flag) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - return _pctlNoInputOutBool(1065, flag); + return _pctlCmdNoInOutBool(flag, 1065); }