diff --git a/nx/include/switch/services/pctl.h b/nx/include/switch/services/pctl.h index 1e3181d9..9623ba21 100644 --- a/nx/include/switch/services/pctl.h +++ b/nx/include/switch/services/pctl.h @@ -7,8 +7,15 @@ #pragma once #include "../types.h" +#include "../kernel/event.h" #include "../sf/service.h" +typedef struct { + u8 rating_age; + bool sns_post_restriction; + bool free_communication_restriction; +} PctlRestrictionSettings; + /// Initialize pctl. Result pctlInitialize(void); @@ -21,15 +28,41 @@ Service* pctlGetServiceSession(void); /// Gets the Service object for IParentalControlService. Service* pctlGetServiceSession_Service(void); +/// Gets whether Parental Controls restrictions are temporarily unlocked. +Result pctlIsRestrictionTemporaryUnlocked(bool *flag); + /// Confirm whether VrMode is allowed. Only available with [4.0.0+]. Result pctlConfirmStereoVisionPermission(void); /// Gets whether Parental Controls are enabled. Result pctlIsRestrictionEnabled(bool *flag); +/// Gets whether Parental Controls are enabled. +Result pctlGetSafetyLevel(u32 *safety_level); + +/// Returns the current restrictions settings. +Result pctlGetCurrentSettings(PctlRestrictionSettings *settings); + +/// Gets the count of applications that have free communication. +Result pctlGetFreeCommunicationApplicationListCount(u32 *count); + /// Reset the confirmation done by \ref pctlConfirmStereoVisionPermission. Only available with [5.0.0+]. Result pctlResetConfirmedStereoVisionPermission(void); /// Gets whether VrMode is allowed. Only available with [5.0.0+]. Result pctlIsStereoVisionPermitted(bool *flag); +/// Confirm whether pairing is active. +Result pctlIsPairingActive(bool *flag); + +/// Returns the synchronization event. +Result pctlGetSynchronizationEvent(Event* out_event); + +/// Returns the supension event. +Result pctlGetPlayTimerEventToRequestSuspension(Event* out_event); + +/// Confirm whether play timer alarm is disabled. Only available with [4.0.0+]. +Result pctlIsPlayTimerAlarmDisabled(bool *flag); + +/// Returns the unlinked event. +Result pctlGetUnlinkedEvent(Event* out_event); diff --git a/nx/source/services/pctl.c b/nx/source/services/pctl.c index 08e84f22..2cd87ffc 100644 --- a/nx/source/services/pctl.c +++ b/nx/source/services/pctl.c @@ -11,7 +11,7 @@ static Result _pctlCmdNoIO(u32 cmd_id); NX_GENERATE_SERVICE_GUARD(pctl); Result _pctlInitialize(void) { - Result rc=0; + Result rc = 0; bool sysverflag = hosversionBefore(4,0,0); rc = smGetService(&g_pctlSrv, "pctl:a"); @@ -42,7 +42,7 @@ Service* pctlGetServiceSession_Service(void) { } static Result _pctlCreateService(Service* srv_out, u32 cmd_id) { - u64 pid_reserved=0; + u64 pid_reserved = 0; serviceAssumeDomain(&g_pctlSrv); return serviceDispatchIn(&g_pctlSrv, cmd_id, pid_reserved, .in_send_pid = true, @@ -61,13 +61,35 @@ static Result _pctlCmdNoInOutU8(u8 *out, u32 cmd_id) { return serviceDispatchOut(&g_pctlSession, cmd_id, *out); } +static Result _pctlCmdNoInOutU32(u32 *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; + u8 tmp = 0; Result rc = _pctlCmdNoInOutU8(&tmp, cmd_id); if (R_SUCCEEDED(rc) && out) *out = tmp & 1; return rc; } +static Result _pctlCmdGetEvent(Event* out_event, u32 cmd_id) { + Result rc; + Handle tmp_handle = INVALID_HANDLE; + + serviceAssumeDomain(&g_pctlSession); + rc = serviceDispatch(&g_pctlSession, cmd_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmp_handle, + ); + if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, true); + return rc; +} + +Result pctlIsRestrictionTemporaryUnlocked(bool *flag) { + return _pctlCmdNoInOutBool(flag, 1006); +} + Result pctlConfirmStereoVisionPermission(void) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -79,6 +101,19 @@ Result pctlIsRestrictionEnabled(bool *flag) { return _pctlCmdNoInOutBool(flag, 1031); } +Result pctlGetSafetyLevel(u32 *safety_level) { + return _pctlCmdNoInOutU32(safety_level, 1032); +} + +Result pctlGetCurrentSettings(PctlRestrictionSettings *settings) { + serviceAssumeDomain(&g_pctlSession); + return serviceDispatchOut(&g_pctlSession, 1035, *settings); +} + +Result pctlGetFreeCommunicationApplicationListCount(u32 *count) { + return _pctlCmdNoInOutU32(count, 1039); +} + Result pctlResetConfirmedStereoVisionPermission(void) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -93,3 +128,25 @@ Result pctlIsStereoVisionPermitted(bool *flag) { return _pctlCmdNoInOutBool(flag, 1065); } +Result pctlIsPairingActive(bool *flag) { + return _pctlCmdNoInOutBool(flag, 1403); +} + +Result pctlGetSynchronizationEvent(Event* out_event) { + return _pctlCmdGetEvent(out_event, 1432); +} + +Result pctlGetPlayTimerEventToRequestSuspension(Event* out_event) { + return _pctlCmdGetEvent(out_event, 1457); +} + +Result pctlIsPlayTimerAlarmDisabled(bool *flag) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _pctlCmdNoInOutBool(flag, 1458); +} + +Result pctlGetUnlinkedEvent(Event* out_event) { + return _pctlCmdGetEvent(out_event, 1473); +}