feat(hle/pctl): implement parental control service stubs for 18.0.0+

- Add GetPlayTimerSettingsVer2 (cmd 1456) with proper struct

- Add GetPlayTimerRemainingTime (cmd 1454)

- Add GetPlayTimerRemainingTimeDisplayInfo (cmd 1459) for 20.0.0+

- Add GetExtendedPlayTimerEvent (cmd 1475) with kernel event

- Define PlayTimerSettingsVer2 and PlayTimerRemainingTimeDisplayInfo types
This commit is contained in:
Zephyron
2026-01-28 16:41:58 +10:00
parent 37863fcb09
commit 3bfa2ebc58
3 changed files with 71 additions and 2 deletions

View File

@@ -13,7 +13,8 @@ namespace Service::PCTL {
IParentalControlService::IParentalControlService(Core::System& system_, Capability capability_)
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_},
service_context{system_, "IParentalControlService"}, synchronization_event{service_context},
unlinked_event{service_context}, request_suspension_event{service_context} {
unlinked_event{service_context}, request_suspension_event{service_context},
extended_play_timer_event{service_context} {
// clang-format off
static const FunctionInfo functions[] = {
{1, D<&IParentalControlService::Initialize>, "Initialize"},
@@ -77,11 +78,12 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
{1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"},
{1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"},
{1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"},
{1454, nullptr, "GetPlayTimerRemainingTime"},
{1454, D<&IParentalControlService::GetPlayTimerRemainingTime>, "GetPlayTimerRemainingTime"},
{1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"},
{1456, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"},
{1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"},
{1458, D<&IParentalControlService::IsPlayTimerAlarmDisabled>, "IsPlayTimerAlarmDisabled"},
{1459, D<&IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo>, "GetPlayTimerRemainingTimeDisplayInfo"}, // [20.0.0+]
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
{1472, nullptr, "CancelNetworkRequest"},
{1473, D<&IParentalControlService::GetUnlinkedEvent>, "GetUnlinkedEvent"},
@@ -117,6 +119,14 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
{2014, nullptr, "FinishSynchronizeParentalControlSettings"},
{2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
{2016, nullptr, "RequestUpdateExemptionListAsync"},
// [18.0.0+]
{1475, D<&IParentalControlService::GetExtendedPlayTimerEvent>, "GetExtendedPlayTimerEvent"},
{1954, nullptr, "IsBedtimeAlarmEnabled"},
{1955, nullptr, "GetBedtimeAlarmTime"},
{1956, nullptr, "GetBedtimeAlarmTimeHour"},
{1957, nullptr, "GetBedtimeAlarmTimeMinute"},
{145601, D<&IParentalControlService::GetPlayTimerSettingsVer2>, "GetPlayTimerSettingsVer2"},
{195101, nullptr, "SetPlayTimerSettingsForDebugVer2"},
};
// clang-format on
RegisterHandlers(functions);
@@ -377,6 +387,28 @@ Result IParentalControlService::GetPlayTimerSettings(
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerRemainingTime(Out<s64> out_remaining_time) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
// Return 0 indicating no time restriction (unlimited playtime remaining)
*out_remaining_time = 0;
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo(
Out<PlayTimerRemainingTimeDisplayInfo> out_display_info) {
LOG_WARNING(Service_PCTL, "(STUBBED) called [20.0.0+]");
// Return default values indicating no time restriction
*out_display_info = {};
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerSettingsVer2(
Out<PlayTimerSettingsVer2> out_play_timer_settings) {
LOG_WARNING(Service_PCTL, "(STUBBED) called [18.0.0+]");
*out_play_timer_settings = {};
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerEventToRequestSuspension(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_PCTL, "called");
@@ -384,6 +416,13 @@ Result IParentalControlService::GetPlayTimerEventToRequestSuspension(
R_SUCCEED();
}
Result IParentalControlService::GetExtendedPlayTimerEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_PCTL, "called [18.0.0+]");
*out_event = extended_play_timer_event.GetHandle();
R_SUCCEED();
}
Result IParentalControlService::IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled) {
*out_play_timer_alarm_disabled = false;
LOG_INFO(Service_PCTL, "called, is_play_timer_alarm_disabled={}",

View File

@@ -47,8 +47,13 @@ private:
Result IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled);
Result IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer);
Result GetPlayTimerSettings(Out<PlayTimerSettings> out_play_timer_settings);
Result GetPlayTimerRemainingTime(Out<s64> out_remaining_time);
Result GetPlayTimerRemainingTimeDisplayInfo(
Out<PlayTimerRemainingTimeDisplayInfo> out_display_info);
Result GetPlayTimerSettingsVer2(Out<PlayTimerSettingsVer2> out_play_timer_settings);
Result GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled);
Result GetExtendedPlayTimerEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction);
Result SetStereoVisionRestriction(bool stereo_vision_restriction);
@@ -81,6 +86,7 @@ private:
Event synchronization_event;
Event unlinked_event;
Event request_suspension_event;
Event extended_play_timer_event;
};
} // namespace Service::PCTL

View File

@@ -40,4 +40,28 @@ struct PlayTimerSettings {
};
static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
// This is nn::pctl::PlayTimerSettingsVer2 [18.0.0+]
// Extended version with bedtime alarm settings
struct PlayTimerSettingsVer2 {
PlayTimerSettings base_settings;
bool bedtime_alarm_enabled;
INSERT_PADDING_BYTES(3);
u32 bedtime_alarm_hour;
u32 bedtime_alarm_minute;
INSERT_PADDING_BYTES(4);
};
static_assert(sizeof(PlayTimerSettingsVer2) == 0x44, "PlayTimerSettingsVer2 has incorrect size.");
// This is nn::pctl::PlayTimerRemainingTimeDisplayInfo [20.0.0+]
struct PlayTimerRemainingTimeDisplayInfo {
s64 remaining_time_ns; // Remaining time in nanoseconds
u32 display_hours; // Hours to display
u32 display_minutes; // Minutes to display
bool is_restricted; // Whether play time is restricted
bool alarm_active; // Whether the alarm is active
INSERT_PADDING_BYTES(6);
};
static_assert(sizeof(PlayTimerRemainingTimeDisplayInfo) == 0x18,
"PlayTimerRemainingTimeDisplayInfo has incorrect size.");
} // namespace Service::PCTL