summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt20
-rw-r--r--src/core/hle/service/olsc/daemon_controller.cpp40
-rw-r--r--src/core/hle/service/olsc/daemon_controller.h20
-rw-r--r--src/core/hle/service/olsc/native_handle_holder.cpp28
-rw-r--r--src/core/hle/service/olsc/native_handle_holder.h22
-rw-r--r--src/core/hle/service/olsc/olsc.cpp223
-rw-r--r--src/core/hle/service/olsc/olsc_service_for_application.cpp63
-rw-r--r--src/core/hle/service/olsc/olsc_service_for_application.h23
-rw-r--r--src/core/hle/service/olsc/olsc_service_for_system_service.cpp117
-rw-r--r--src/core/hle/service/olsc/olsc_service_for_system_service.h27
-rw-r--r--src/core/hle/service/olsc/remote_storage_controller.cpp54
-rw-r--r--src/core/hle/service/olsc/remote_storage_controller.h19
-rw-r--r--src/core/hle/service/olsc/transfer_task_list_controller.cpp55
-rw-r--r--src/core/hle/service/olsc/transfer_task_list_controller.h20
-rw-r--r--src/core/hle/service/pctl/parental_control_service.cpp434
-rw-r--r--src/core/hle/service/pctl/parental_control_service.h86
-rw-r--r--src/core/hle/service/pctl/parental_control_service_factory.cpp40
-rw-r--r--src/core/hle/service/pctl/parental_control_service_factory.h31
-rw-r--r--src/core/hle/service/pctl/pctl.cpp27
-rw-r--r--src/core/hle/service/pctl/pctl.h9
-rw-r--r--src/core/hle/service/pctl/pctl_module.cpp550
-rw-r--r--src/core/hle/service/pctl/pctl_module.h47
-rw-r--r--src/core/hle/service/pctl/pctl_results.h15
-rw-r--r--src/core/hle/service/pctl/pctl_types.h43
-rw-r--r--src/core/hle/service/services.cpp2
25 files changed, 1187 insertions, 828 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3400c512d..0393eff33 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -879,8 +879,20 @@ add_library(core STATIC
hle/service/nvnflinger/ui/graphic_buffer.cpp
hle/service/nvnflinger/ui/graphic_buffer.h
hle/service/nvnflinger/window.h
+ hle/service/olsc/daemon_controller.cpp
+ hle/service/olsc/daemon_controller.h
+ hle/service/olsc/native_handle_holder.cpp
+ hle/service/olsc/native_handle_holder.h
+ hle/service/olsc/olsc_service_for_application.cpp
+ hle/service/olsc/olsc_service_for_application.h
+ hle/service/olsc/olsc_service_for_system_service.cpp
+ hle/service/olsc/olsc_service_for_system_service.h
hle/service/olsc/olsc.cpp
hle/service/olsc/olsc.h
+ hle/service/olsc/remote_storage_controller.cpp
+ hle/service/olsc/remote_storage_controller.h
+ hle/service/olsc/transfer_task_list_controller.cpp
+ hle/service/olsc/transfer_task_list_controller.h
hle/service/omm/omm.cpp
hle/service/omm/omm.h
hle/service/omm/operation_mode_manager.cpp
@@ -900,10 +912,14 @@ add_library(core STATIC
hle/service/os/mutex.h
hle/service/pcie/pcie.cpp
hle/service/pcie/pcie.h
+ hle/service/pctl/parental_control_service_factory.cpp
+ hle/service/pctl/parental_control_service_factory.h
+ hle/service/pctl/parental_control_service.cpp
+ hle/service/pctl/parental_control_service.h
hle/service/pctl/pctl.cpp
hle/service/pctl/pctl.h
- hle/service/pctl/pctl_module.cpp
- hle/service/pctl/pctl_module.h
+ hle/service/pctl/pctl_results.h
+ hle/service/pctl/pctl_types.h
hle/service/pcv/pcv.cpp
hle/service/pcv/pcv.h
hle/service/pm/pm.cpp
diff --git a/src/core/hle/service/olsc/daemon_controller.cpp b/src/core/hle/service/olsc/daemon_controller.cpp
new file mode 100644
index 000000000..7823780a8
--- /dev/null
+++ b/src/core/hle/service/olsc/daemon_controller.cpp
@@ -0,0 +1,40 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/olsc/daemon_controller.h"
+
+namespace Service::OLSC {
+
+IDaemonController::IDaemonController(Core::System& system_)
+ : ServiceFramework{system_, "IDaemonController"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IDaemonController::GetAutoTransferEnabledForAccountAndApplication>, "GetAutoTransferEnabledForAccountAndApplication"},
+ {1, nullptr, "SetAutoTransferEnabledForAccountAndApplication"},
+ {2, nullptr, "GetGlobalUploadEnabledForAccount"},
+ {3, nullptr, "SetGlobalUploadEnabledForAccount"},
+ {4, nullptr, "TouchAccount"},
+ {5, nullptr, "GetGlobalDownloadEnabledForAccount"},
+ {6, nullptr, "SetGlobalDownloadEnabledForAccount"},
+ {10, nullptr, "GetForbiddenSaveDataIndication"},
+ {11, nullptr, "GetStopperObject"},
+ {12, nullptr, "GetState"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDaemonController::~IDaemonController() = default;
+
+Result IDaemonController::GetAutoTransferEnabledForAccountAndApplication(Out<bool> out_is_enabled,
+ Common::UUID user_id,
+ u64 application_id) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called, user_id={} application_id={:016X}",
+ user_id.FormattedString(), application_id);
+ *out_is_enabled = false;
+ R_SUCCEED();
+}
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/daemon_controller.h b/src/core/hle/service/olsc/daemon_controller.h
new file mode 100644
index 000000000..dfad7f52a
--- /dev/null
+++ b/src/core/hle/service/olsc/daemon_controller.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/uuid.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::OLSC {
+
+class IDaemonController final : public ServiceFramework<IDaemonController> {
+public:
+ explicit IDaemonController(Core::System& system_);
+ ~IDaemonController() override;
+
+private:
+ Result GetAutoTransferEnabledForAccountAndApplication(Out<bool> out_is_enabled,
+ Common::UUID user_id, u64 application_id);
+};
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/native_handle_holder.cpp b/src/core/hle/service/olsc/native_handle_holder.cpp
new file mode 100644
index 000000000..3cb5d7b11
--- /dev/null
+++ b/src/core/hle/service/olsc/native_handle_holder.cpp
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/olsc/native_handle_holder.h"
+
+namespace Service::OLSC {
+
+INativeHandleHolder::INativeHandleHolder(Core::System& system_)
+ : ServiceFramework{system_, "INativeHandleHolder"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&INativeHandleHolder::GetNativeHandle>, "GetNativeHandle"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+INativeHandleHolder::~INativeHandleHolder() = default;
+
+Result INativeHandleHolder::GetNativeHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called");
+ *out_event = nullptr;
+ R_SUCCEED();
+}
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/native_handle_holder.h b/src/core/hle/service/olsc/native_handle_holder.h
new file mode 100644
index 000000000..a44754c20
--- /dev/null
+++ b/src/core/hle/service/olsc/native_handle_holder.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::OLSC {
+
+class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> {
+public:
+ explicit INativeHandleHolder(Core::System& system_);
+ ~INativeHandleHolder() override;
+
+private:
+ Result GetNativeHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
+};
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp
index 889f27c31..18e5ad43f 100644
--- a/src/core/hle/service/olsc/olsc.cpp
+++ b/src/core/hle/service/olsc/olsc.cpp
@@ -1,226 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/olsc/olsc.h"
+#include "core/hle/service/olsc/olsc_service_for_application.h"
+#include "core/hle/service/olsc/olsc_service_for_system_service.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
namespace Service::OLSC {
-class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> {
-public:
- explicit IOlscServiceForApplication(Core::System& system_)
- : ServiceFramework{system_, "olsc:u"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IOlscServiceForApplication::Initialize, "Initialize"},
- {10, nullptr, "VerifySaveDataBackupLicenseAsync"},
- {13, &IOlscServiceForApplication::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
- {14, &IOlscServiceForApplication::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
- {15, nullptr, "SetCustomData"},
- {16, nullptr, "DeleteSaveDataBackupSetting"},
- {18, nullptr, "GetSaveDataBackupInfoCache"},
- {19, nullptr, "UpdateSaveDataBackupInfoCacheAsync"},
- {22, nullptr, "DeleteSaveDataBackupAsync"},
- {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"},
- {26, nullptr, "DownloadSaveDataBackupAsync"},
- {27, nullptr, "UploadSaveDataBackupAsync"},
- {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"},
- {9013, nullptr, "GetSaveDataBackupSettingForDebug"},
- {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"},
- {9015, nullptr, "SetCustomDataForDebug"},
- {9016, nullptr, "DeleteSaveDataBackupSettingForDebug"},
- {9018, nullptr, "GetSaveDataBackupInfoCacheForDebug"},
- {9019, nullptr, "UpdateSaveDataBackupInfoCacheAsyncForDebug"},
- {9022, nullptr, "DeleteSaveDataBackupAsyncForDebug"},
- {9025, nullptr, "ListDownloadableSaveDataBackupInfoAsyncForDebug"},
- {9026, nullptr, "DownloadSaveDataBackupAsyncForDebug"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void Initialize(HLERequestContext& ctx) {
- LOG_WARNING(Service_OLSC, "(STUBBED) called");
-
- initialized = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetSaveDataBackupSetting(HLERequestContext& ctx) {
- LOG_WARNING(Service_OLSC, "(STUBBED) called");
-
- // backup_setting is set to 0 since real value is unknown
- constexpr u64 backup_setting = 0;
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(backup_setting);
- }
-
- void SetSaveDataBackupSettingEnabled(HLERequestContext& ctx) {
- LOG_WARNING(Service_OLSC, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- bool initialized{};
-};
-
-class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> {
-public:
- explicit INativeHandleHolder(Core::System& system_)
- : ServiceFramework{system_, "INativeHandleHolder"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetNativeHandle"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> {
-public:
- explicit ITransferTaskListController(Core::System& system_)
- : ServiceFramework{system_, "ITransferTaskListController"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "Unknown0"},
- {1, nullptr, "Unknown1"},
- {2, nullptr, "Unknown2"},
- {3, nullptr, "Unknown3"},
- {4, nullptr, "Unknown4"},
- {5, &ITransferTaskListController::GetNativeHandleHolder , "GetNativeHandleHolder"},
- {6, nullptr, "Unknown6"},
- {7, nullptr, "Unknown7"},
- {8, nullptr, "GetRemoteStorageController"},
- {9, &ITransferTaskListController::GetNativeHandleHolder, "GetNativeHandleHolder2"},
- {10, nullptr, "Unknown10"},
- {11, nullptr, "Unknown11"},
- {12, nullptr, "Unknown12"},
- {13, nullptr, "Unknown13"},
- {14, nullptr, "Unknown14"},
- {15, nullptr, "Unknown15"},
- {16, nullptr, "Unknown16"},
- {17, nullptr, "Unknown17"},
- {18, nullptr, "Unknown18"},
- {19, nullptr, "Unknown19"},
- {20, nullptr, "Unknown20"},
- {21, nullptr, "Unknown21"},
- {22, nullptr, "Unknown22"},
- {23, nullptr, "Unknown23"},
- {24, nullptr, "Unknown24"},
- {25, nullptr, "Unknown25"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void GetNativeHandleHolder(HLERequestContext& ctx) {
- LOG_INFO(Service_OLSC, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<INativeHandleHolder>(system);
- }
-};
-
-class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
-public:
- explicit IOlscServiceForSystemService(Core::System& system_)
- : ServiceFramework{system_, "olsc:s"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IOlscServiceForSystemService::OpenTransferTaskListController, "OpenTransferTaskListController"},
- {1, nullptr, "OpenRemoteStorageController"},
- {2, nullptr, "OpenDaemonController"},
- {10, nullptr, "Unknown10"},
- {11, nullptr, "Unknown11"},
- {12, nullptr, "Unknown12"},
- {13, nullptr, "Unknown13"},
- {100, nullptr, "ListLastTransferTaskErrorInfo"},
- {101, nullptr, "GetLastErrorInfoCount"},
- {102, nullptr, "RemoveLastErrorInfoOld"},
- {103, nullptr, "GetLastErrorInfo"},
- {104, nullptr, "GetLastErrorEventHolder"},
- {105, nullptr, "GetLastTransferTaskErrorInfo"},
- {200, nullptr, "GetDataTransferPolicyInfo"},
- {201, nullptr, "RemoveDataTransferPolicyInfo"},
- {202, nullptr, "UpdateDataTransferPolicyOld"},
- {203, nullptr, "UpdateDataTransferPolicy"},
- {204, nullptr, "CleanupDataTransferPolicyInfo"},
- {205, nullptr, "RequestDataTransferPolicy"},
- {300, nullptr, "GetAutoTransferSeriesInfo"},
- {301, nullptr, "UpdateAutoTransferSeriesInfo"},
- {400, nullptr, "CleanupSaveDataArchiveInfoType1"},
- {900, nullptr, "CleanupTransferTask"},
- {902, nullptr, "CleanupSeriesInfoType0"},
- {903, nullptr, "CleanupSaveDataArchiveInfoType0"},
- {904, nullptr, "CleanupApplicationAutoTransferSetting"},
- {905, nullptr, "CleanupErrorHistory"},
- {906, nullptr, "SetLastError"},
- {907, nullptr, "AddSaveDataArchiveInfoType0"},
- {908, nullptr, "RemoveSeriesInfoType0"},
- {909, nullptr, "GetSeriesInfoType0"},
- {910, nullptr, "RemoveLastErrorInfo"},
- {911, nullptr, "CleanupSeriesInfoType1"},
- {912, nullptr, "RemoveSeriesInfoType1"},
- {913, nullptr, "GetSeriesInfoType1"},
- {1000, nullptr, "UpdateIssueOld"},
- {1010, nullptr, "Unknown1010"},
- {1011, nullptr, "ListIssueInfoOld"},
- {1012, nullptr, "GetIssueOld"},
- {1013, nullptr, "GetIssue2Old"},
- {1014, nullptr, "GetIssue3Old"},
- {1020, nullptr, "RepairIssueOld"},
- {1021, nullptr, "RepairIssueWithUserIdOld"},
- {1022, nullptr, "RepairIssue2Old"},
- {1023, nullptr, "RepairIssue3Old"},
- {1024, nullptr, "Unknown1024"},
- {1100, nullptr, "UpdateIssue"},
- {1110, nullptr, "Unknown1110"},
- {1111, nullptr, "ListIssueInfo"},
- {1112, nullptr, "GetIssue"},
- {1113, nullptr, "GetIssue2"},
- {1114, nullptr, "GetIssue3"},
- {1120, nullptr, "RepairIssue"},
- {1121, nullptr, "RepairIssueWithUserId"},
- {1122, nullptr, "RepairIssue2"},
- {1123, nullptr, "RepairIssue3"},
- {1124, nullptr, "Unknown1124"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void OpenTransferTaskListController(HLERequestContext& ctx) {
- LOG_INFO(Service_OLSC, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ITransferTaskListController>(system);
- }
-};
-
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("olsc:u",
- std::make_shared<IOlscServiceForApplication>(system));
- server_manager->RegisterNamedService("olsc:s",
- std::make_shared<IOlscServiceForSystemService>(system));
+ const auto OlscFactoryForApplication = [&] {
+ return std::make_shared<IOlscServiceForApplication>(system);
+ };
+
+ const auto OlscFactoryForSystemService = [&] {
+ return std::make_shared<IOlscServiceForSystemService>(system);
+ };
+
+ server_manager->RegisterNamedService("olsc:u", OlscFactoryForApplication);
+ server_manager->RegisterNamedService("olsc:s", OlscFactoryForSystemService);
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/olsc/olsc_service_for_application.cpp b/src/core/hle/service/olsc/olsc_service_for_application.cpp
new file mode 100644
index 000000000..01360f5ef
--- /dev/null
+++ b/src/core/hle/service/olsc/olsc_service_for_application.cpp
@@ -0,0 +1,63 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/olsc/olsc_service_for_application.h"
+
+namespace Service::OLSC {
+
+IOlscServiceForApplication::IOlscServiceForApplication(Core::System& system_)
+ : ServiceFramework{system_, "olsc:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IOlscServiceForApplication::Initialize>, "Initialize"},
+ {10, nullptr, "VerifySaveDataBackupLicenseAsync"},
+ {13, D<&IOlscServiceForApplication::GetSaveDataBackupSetting>, "GetSaveDataBackupSetting"},
+ {14, D<&IOlscServiceForApplication::SetSaveDataBackupSettingEnabled>, "SetSaveDataBackupSettingEnabled"},
+ {15, nullptr, "SetCustomData"},
+ {16, nullptr, "DeleteSaveDataBackupSetting"},
+ {18, nullptr, "GetSaveDataBackupInfoCache"},
+ {19, nullptr, "UpdateSaveDataBackupInfoCacheAsync"},
+ {22, nullptr, "DeleteSaveDataBackupAsync"},
+ {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"},
+ {26, nullptr, "DownloadSaveDataBackupAsync"},
+ {27, nullptr, "UploadSaveDataBackupAsync"},
+ {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"},
+ {9013, nullptr, "GetSaveDataBackupSettingForDebug"},
+ {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"},
+ {9015, nullptr, "SetCustomDataForDebug"},
+ {9016, nullptr, "DeleteSaveDataBackupSettingForDebug"},
+ {9018, nullptr, "GetSaveDataBackupInfoCacheForDebug"},
+ {9019, nullptr, "UpdateSaveDataBackupInfoCacheAsyncForDebug"},
+ {9022, nullptr, "DeleteSaveDataBackupAsyncForDebug"},
+ {9025, nullptr, "ListDownloadableSaveDataBackupInfoAsyncForDebug"},
+ {9026, nullptr, "DownloadSaveDataBackupAsyncForDebug"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IOlscServiceForApplication::~IOlscServiceForApplication() = default;
+
+Result IOlscServiceForApplication::Initialize(ClientProcessId process_id) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called");
+ initialized = true;
+ R_SUCCEED();
+}
+
+Result IOlscServiceForApplication::GetSaveDataBackupSetting(Out<u8> out_save_data_backup_setting) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called");
+ // backup_setting is set to 0 since real value is unknown
+ *out_save_data_backup_setting = 0;
+ R_SUCCEED();
+}
+
+Result IOlscServiceForApplication::SetSaveDataBackupSettingEnabled(bool enabled,
+ NS::Uid account_id) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called, enabled={}, account_id={}", enabled,
+ account_id.uuid.FormattedString());
+ R_SUCCEED();
+}
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/olsc_service_for_application.h b/src/core/hle/service/olsc/olsc_service_for_application.h
new file mode 100644
index 000000000..3f9ac7536
--- /dev/null
+++ b/src/core/hle/service/olsc/olsc_service_for_application.h
@@ -0,0 +1,23 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::OLSC {
+
+class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> {
+public:
+ explicit IOlscServiceForApplication(Core::System& system_);
+ ~IOlscServiceForApplication() override;
+
+private:
+ Result Initialize(ClientProcessId process_id);
+ Result GetSaveDataBackupSetting(Out<u8> out_save_data_backup_setting);
+ Result SetSaveDataBackupSettingEnabled(bool enabled, NS::Uid account_id);
+
+ bool initialized{};
+};
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/olsc_service_for_system_service.cpp b/src/core/hle/service/olsc/olsc_service_for_system_service.cpp
new file mode 100644
index 000000000..f027933c9
--- /dev/null
+++ b/src/core/hle/service/olsc/olsc_service_for_system_service.cpp
@@ -0,0 +1,117 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/olsc/daemon_controller.h"
+#include "core/hle/service/olsc/olsc_service_for_system_service.h"
+#include "core/hle/service/olsc/remote_storage_controller.h"
+#include "core/hle/service/olsc/transfer_task_list_controller.h"
+
+namespace Service::OLSC {
+
+IOlscServiceForSystemService::IOlscServiceForSystemService(Core::System& system_)
+ : ServiceFramework{system_, "olsc:s"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IOlscServiceForSystemService::OpenTransferTaskListController>, "OpenTransferTaskListController"},
+ {1, D<&IOlscServiceForSystemService::OpenRemoteStorageController>, "OpenRemoteStorageController"},
+ {2, D<&IOlscServiceForSystemService::OpenDaemonController>, "OpenDaemonController"},
+ {10, nullptr, "Unknown10"},
+ {11, nullptr, "Unknown11"},
+ {12, nullptr, "Unknown12"},
+ {13, nullptr, "Unknown13"},
+ {100, nullptr, "ListLastTransferTaskErrorInfo"},
+ {101, nullptr, "GetLastErrorInfoCount"},
+ {102, nullptr, "RemoveLastErrorInfoOld"},
+ {103, nullptr, "GetLastErrorInfo"},
+ {104, nullptr, "GetLastErrorEventHolder"},
+ {105, nullptr, "GetLastTransferTaskErrorInfo"},
+ {200, D<&IOlscServiceForSystemService::GetDataTransferPolicyInfo>, "GetDataTransferPolicyInfo"},
+ {201, nullptr, "RemoveDataTransferPolicyInfo"},
+ {202, nullptr, "UpdateDataTransferPolicyOld"},
+ {203, nullptr, "UpdateDataTransferPolicy"},
+ {204, nullptr, "CleanupDataTransferPolicyInfo"},
+ {205, nullptr, "RequestDataTransferPolicy"},
+ {300, nullptr, "GetAutoTransferSeriesInfo"},
+ {301, nullptr, "UpdateAutoTransferSeriesInfo"},
+ {400, nullptr, "CleanupSaveDataArchiveInfoType1"},
+ {900, nullptr, "CleanupTransferTask"},
+ {902, nullptr, "CleanupSeriesInfoType0"},
+ {903, nullptr, "CleanupSaveDataArchiveInfoType0"},
+ {904, nullptr, "CleanupApplicationAutoTransferSetting"},
+ {905, nullptr, "CleanupErrorHistory"},
+ {906, nullptr, "SetLastError"},
+ {907, nullptr, "AddSaveDataArchiveInfoType0"},
+ {908, nullptr, "RemoveSeriesInfoType0"},
+ {909, nullptr, "GetSeriesInfoType0"},
+ {910, nullptr, "RemoveLastErrorInfo"},
+ {911, nullptr, "CleanupSeriesInfoType1"},
+ {912, nullptr, "RemoveSeriesInfoType1"},
+ {913, nullptr, "GetSeriesInfoType1"},
+ {1000, nullptr, "UpdateIssueOld"},
+ {1010, nullptr, "Unknown1010"},
+ {1011, nullptr, "ListIssueInfoOld"},
+ {1012, nullptr, "GetIssueOld"},
+ {1013, nullptr, "GetIssue2Old"},
+ {1014, nullptr, "GetIssue3Old"},
+ {1020, nullptr, "RepairIssueOld"},
+ {1021, nullptr, "RepairIssueWithUserIdOld"},
+ {1022, nullptr, "RepairIssue2Old"},
+ {1023, nullptr, "RepairIssue3Old"},
+ {1024, nullptr, "Unknown1024"},
+ {1100, nullptr, "UpdateIssue"},
+ {1110, nullptr, "Unknown1110"},
+ {1111, nullptr, "ListIssueInfo"},
+ {1112, nullptr, "GetIssue"},
+ {1113, nullptr, "GetIssue2"},
+ {1114, nullptr, "GetIssue3"},
+ {1120, nullptr, "RepairIssue"},
+ {1121, nullptr, "RepairIssueWithUserId"},
+ {1122, nullptr, "RepairIssue2"},
+ {1123, nullptr, "RepairIssue3"},
+ {1124, nullptr, "Unknown1124"},
+ {10000, D<&IOlscServiceForSystemService::CloneService>, "CloneService"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IOlscServiceForSystemService::~IOlscServiceForSystemService() = default;
+
+Result IOlscServiceForSystemService::OpenTransferTaskListController(
+ Out<SharedPointer<ITransferTaskListController>> out_interface) {
+ LOG_INFO(Service_OLSC, "called");
+ *out_interface = std::make_shared<ITransferTaskListController>(system);
+ R_SUCCEED();
+}
+
+Result IOlscServiceForSystemService::OpenRemoteStorageController(
+ Out<SharedPointer<IRemoteStorageController>> out_interface) {
+ LOG_INFO(Service_OLSC, "called");
+ *out_interface = std::make_shared<IRemoteStorageController>(system);
+ R_SUCCEED();
+}
+
+Result IOlscServiceForSystemService::OpenDaemonController(
+ Out<SharedPointer<IDaemonController>> out_interface) {
+ LOG_INFO(Service_OLSC, "called");
+ *out_interface = std::make_shared<IDaemonController>(system);
+ R_SUCCEED();
+}
+
+Result IOlscServiceForSystemService::GetDataTransferPolicyInfo(Out<u16> out_policy_info,
+ u64 application_id) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called");
+ *out_policy_info = 0;
+ R_SUCCEED();
+}
+
+Result IOlscServiceForSystemService::CloneService(
+ Out<SharedPointer<IOlscServiceForSystemService>> out_interface) {
+ LOG_INFO(Service_OLSC, "called");
+ *out_interface = std::static_pointer_cast<IOlscServiceForSystemService>(shared_from_this());
+ R_SUCCEED();
+}
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/olsc_service_for_system_service.h b/src/core/hle/service/olsc/olsc_service_for_system_service.h
new file mode 100644
index 000000000..13026272a
--- /dev/null
+++ b/src/core/hle/service/olsc/olsc_service_for_system_service.h
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::OLSC {
+
+class IDaemonController;
+class IRemoteStorageController;
+class ITransferTaskListController;
+
+class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
+public:
+ explicit IOlscServiceForSystemService(Core::System& system_);
+ ~IOlscServiceForSystemService() override;
+
+private:
+ Result OpenTransferTaskListController(
+ Out<SharedPointer<ITransferTaskListController>> out_interface);
+ Result OpenRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
+ Result OpenDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
+ Result GetDataTransferPolicyInfo(Out<u16> out_policy_info, u64 application_id);
+ Result CloneService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
+};
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/remote_storage_controller.cpp b/src/core/hle/service/olsc/remote_storage_controller.cpp
new file mode 100644
index 000000000..81d9c96ab
--- /dev/null
+++ b/src/core/hle/service/olsc/remote_storage_controller.cpp
@@ -0,0 +1,54 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/olsc/remote_storage_controller.h"
+
+namespace Service::OLSC {
+
+IRemoteStorageController::IRemoteStorageController(Core::System& system_)
+ : ServiceFramework{system_, "IRemoteStorageController"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetSaveDataArchiveInfoBySaveDataId"},
+ {1, nullptr, "GetSaveDataArchiveInfoByApplicationId"},
+ {3, nullptr, "GetSaveDataArchiveCount"},
+ {6, nullptr, "CleanupSaveDataArchives"},
+ {7, nullptr, "CreateSaveDataArchiveCacheUpdationTask"},
+ {8, nullptr, "CreateSaveDataArchiveCacheUpdationForSpecifiedApplicationTask"},
+ {9, nullptr, "Delete"},
+ {10, nullptr, "GetSeriesInfo"},
+ {11, nullptr, "CreateDeleteDataTask"},
+ {12, nullptr, "DeleteSeriesInfo"},
+ {13, nullptr, "CreateRegisterNotificationTokenTask"},
+ {14, nullptr, "UpdateSeriesInfo"},
+ {15, nullptr, "RegisterUploadSaveDataTransferTaskForAutonomyRegistration"},
+ {16, nullptr, "CreateCleanupToDeleteSaveDataArchiveInfoTask"},
+ {17, nullptr, "ListDataInfo"},
+ {18, nullptr, "GetDataInfo"},
+ {19, nullptr, "Unknown19"},
+ {20, nullptr, "CreateSaveDataArchiveInfoCacheForSaveDataBackupUpdationTask"},
+ {21, nullptr, "ListSecondarySaves"},
+ {22, D<&IRemoteStorageController::GetSecondarySave>, "GetSecondarySave"},
+ {23, nullptr, "TouchSecondarySave"},
+ {24, nullptr, "GetSecondarySaveDataInfo"},
+ {25, nullptr, "RegisterDownloadSaveDataTransferTaskForAutonomyRegistration"},
+ {900, nullptr, "Unknown900"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IRemoteStorageController::~IRemoteStorageController() = default;
+
+Result IRemoteStorageController::GetSecondarySave(Out<bool> out_has_secondary_save,
+ Out<std::array<u64, 3>> out_unknown,
+ u64 application_id) {
+ LOG_ERROR(Service_OLSC, "(STUBBED) called, application_id={:016X}", application_id);
+ *out_has_secondary_save = false;
+ *out_unknown = {};
+ R_SUCCEED();
+}
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/remote_storage_controller.h b/src/core/hle/service/olsc/remote_storage_controller.h
new file mode 100644
index 000000000..e7a0b5244
--- /dev/null
+++ b/src/core/hle/service/olsc/remote_storage_controller.h
@@ -0,0 +1,19 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::OLSC {
+
+class IRemoteStorageController final : public ServiceFramework<IRemoteStorageController> {
+public:
+ explicit IRemoteStorageController(Core::System& system_);
+ ~IRemoteStorageController() override;
+
+private:
+ Result GetSecondarySave(Out<bool> out_has_secondary_save, Out<std::array<u64, 3>> out_unknown,
+ u64 application_id);
+};
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/transfer_task_list_controller.cpp b/src/core/hle/service/olsc/transfer_task_list_controller.cpp
new file mode 100644
index 000000000..8ea9a0f1e
--- /dev/null
+++ b/src/core/hle/service/olsc/transfer_task_list_controller.cpp
@@ -0,0 +1,55 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/olsc/native_handle_holder.h"
+#include "core/hle/service/olsc/transfer_task_list_controller.h"
+
+namespace Service::OLSC {
+
+ITransferTaskListController::ITransferTaskListController(Core::System& system_)
+ : ServiceFramework{system_, "ITransferTaskListController"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown0"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ {8, nullptr, "GetRemoteStorageController"},
+ {9, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder2"},
+ {10, nullptr, "Unknown10"},
+ {11, nullptr, "Unknown11"},
+ {12, nullptr, "Unknown12"},
+ {13, nullptr, "Unknown13"},
+ {14, nullptr, "Unknown14"},
+ {15, nullptr, "Unknown15"},
+ {16, nullptr, "Unknown16"},
+ {17, nullptr, "Unknown17"},
+ {18, nullptr, "Unknown18"},
+ {19, nullptr, "Unknown19"},
+ {20, nullptr, "Unknown20"},
+ {21, nullptr, "Unknown21"},
+ {22, nullptr, "Unknown22"},
+ {23, nullptr, "Unknown23"},
+ {24, nullptr, "Unknown24"},
+ {25, nullptr, "Unknown25"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ITransferTaskListController::~ITransferTaskListController() = default;
+
+Result ITransferTaskListController::GetNativeHandleHolder(
+ Out<SharedPointer<INativeHandleHolder>> out_holder) {
+ LOG_WARNING(Service_OLSC, "(STUBBED) called");
+ *out_holder = std::make_shared<INativeHandleHolder>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/olsc/transfer_task_list_controller.h b/src/core/hle/service/olsc/transfer_task_list_controller.h
new file mode 100644
index 000000000..f10a71375
--- /dev/null
+++ b/src/core/hle/service/olsc/transfer_task_list_controller.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::OLSC {
+
+class INativeHandleHolder;
+
+class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> {
+public:
+ explicit ITransferTaskListController(Core::System& system_);
+ ~ITransferTaskListController() override;
+
+private:
+ Result GetNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
+};
+
+} // namespace Service::OLSC
diff --git a/src/core/hle/service/pctl/parental_control_service.cpp b/src/core/hle/service/pctl/parental_control_service.cpp
new file mode 100644
index 000000000..f57f2f157
--- /dev/null
+++ b/src/core/hle/service/pctl/parental_control_service.cpp
@@ -0,0 +1,434 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/pctl/parental_control_service.h"
+#include "core/hle/service/pctl/pctl_results.h"
+
+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} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, D<&IParentalControlService::Initialize>, "Initialize"},
+ {1001, D<&IParentalControlService::CheckFreeCommunicationPermission>, "CheckFreeCommunicationPermission"},
+ {1002, D<&IParentalControlService::ConfirmLaunchApplicationPermission>, "ConfirmLaunchApplicationPermission"},
+ {1003, D<&IParentalControlService::ConfirmResumeApplicationPermission>, "ConfirmResumeApplicationPermission"},
+ {1004, D<&IParentalControlService::ConfirmSnsPostPermission>, "ConfirmSnsPostPermission"},
+ {1005, nullptr, "ConfirmSystemSettingsPermission"},
+ {1006, D<&IParentalControlService::IsRestrictionTemporaryUnlocked>, "IsRestrictionTemporaryUnlocked"},
+ {1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
+ {1008, nullptr, "EnterRestrictedSystemSettings"},
+ {1009, nullptr, "LeaveRestrictedSystemSettings"},
+ {1010, D<&IParentalControlService::IsRestrictedSystemSettingsEntered>, "IsRestrictedSystemSettingsEntered"},
+ {1011, nullptr, "RevertRestrictedSystemSettingsEntered"},
+ {1012, nullptr, "GetRestrictedFeatures"},
+ {1013, D<&IParentalControlService::ConfirmStereoVisionPermission>, "ConfirmStereoVisionPermission"},
+ {1014, nullptr, "ConfirmPlayableApplicationVideoOld"},
+ {1015, nullptr, "ConfirmPlayableApplicationVideo"},
+ {1016, nullptr, "ConfirmShowNewsPermission"},
+ {1017, D<&IParentalControlService::EndFreeCommunication>, "EndFreeCommunication"},
+ {1018, D<&IParentalControlService::IsFreeCommunicationAvailable>, "IsFreeCommunicationAvailable"},
+ {1031, D<&IParentalControlService::IsRestrictionEnabled>, "IsRestrictionEnabled"},
+ {1032, D<&IParentalControlService::GetSafetyLevel>, "GetSafetyLevel"},
+ {1033, nullptr, "SetSafetyLevel"},
+ {1034, nullptr, "GetSafetyLevelSettings"},
+ {1035, D<&IParentalControlService::GetCurrentSettings>, "GetCurrentSettings"},
+ {1036, nullptr, "SetCustomSafetyLevelSettings"},
+ {1037, nullptr, "GetDefaultRatingOrganization"},
+ {1038, nullptr, "SetDefaultRatingOrganization"},
+ {1039, D<&IParentalControlService::GetFreeCommunicationApplicationListCount>, "GetFreeCommunicationApplicationListCount"},
+ {1042, nullptr, "AddToFreeCommunicationApplicationList"},
+ {1043, nullptr, "DeleteSettings"},
+ {1044, nullptr, "GetFreeCommunicationApplicationList"},
+ {1045, nullptr, "UpdateFreeCommunicationApplicationList"},
+ {1046, nullptr, "DisableFeaturesForReset"},
+ {1047, nullptr, "NotifyApplicationDownloadStarted"},
+ {1048, nullptr, "NotifyNetworkProfileCreated"},
+ {1049, nullptr, "ResetFreeCommunicationApplicationList"},
+ {1061, D<&IParentalControlService::ConfirmStereoVisionRestrictionConfigurable>, "ConfirmStereoVisionRestrictionConfigurable"},
+ {1062, D<&IParentalControlService::GetStereoVisionRestriction>, "GetStereoVisionRestriction"},
+ {1063, D<&IParentalControlService::SetStereoVisionRestriction>, "SetStereoVisionRestriction"},
+ {1064, D<&IParentalControlService::ResetConfirmedStereoVisionPermission>, "ResetConfirmedStereoVisionPermission"},
+ {1065, D<&IParentalControlService::IsStereoVisionPermitted>, "IsStereoVisionPermitted"},
+ {1201, nullptr, "UnlockRestrictionTemporarily"},
+ {1202, nullptr, "UnlockSystemSettingsRestriction"},
+ {1203, nullptr, "SetPinCode"},
+ {1204, nullptr, "GenerateInquiryCode"},
+ {1205, nullptr, "CheckMasterKey"},
+ {1206, D<&IParentalControlService::GetPinCodeLength>, "GetPinCodeLength"},
+ {1207, nullptr, "GetPinCodeChangedEvent"},
+ {1208, nullptr, "GetPinCode"},
+ {1403, D<&IParentalControlService::IsPairingActive>, "IsPairingActive"},
+ {1406, nullptr, "GetSettingsLastUpdated"},
+ {1411, nullptr, "GetPairingAccountInfo"},
+ {1421, nullptr, "GetAccountNickname"},
+ {1424, nullptr, "GetAccountState"},
+ {1425, nullptr, "RequestPostEvents"},
+ {1426, nullptr, "GetPostEventInterval"},
+ {1427, nullptr, "SetPostEventInterval"},
+ {1432, D<&IParentalControlService::GetSynchronizationEvent>, "GetSynchronizationEvent"},
+ {1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"},
+ {1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"},
+ {1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"},
+ {1454, nullptr, "GetPlayTimerRemainingTime"},
+ {1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"},
+ {1456, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"},
+ {1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"},
+ {1458, D<&IParentalControlService::IsPlayTimerAlarmDisabled>, "IsPlayTimerAlarmDisabled"},
+ {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
+ {1472, nullptr, "CancelNetworkRequest"},
+ {1473, D<&IParentalControlService::GetUnlinkedEvent>, "GetUnlinkedEvent"},
+ {1474, nullptr, "ClearUnlinkedEvent"},
+ {1601, nullptr, "DisableAllFeatures"},
+ {1602, nullptr, "PostEnableAllFeatures"},
+ {1603, nullptr, "IsAllFeaturesDisabled"},
+ {1901, nullptr, "DeleteFromFreeCommunicationApplicationListForDebug"},
+ {1902, nullptr, "ClearFreeCommunicationApplicationListForDebug"},
+ {1903, nullptr, "GetExemptApplicationListCountForDebug"},
+ {1904, nullptr, "GetExemptApplicationListForDebug"},
+ {1905, nullptr, "UpdateExemptApplicationListForDebug"},
+ {1906, nullptr, "AddToExemptApplicationListForDebug"},
+ {1907, nullptr, "DeleteFromExemptApplicationListForDebug"},
+ {1908, nullptr, "ClearExemptApplicationListForDebug"},
+ {1941, nullptr, "DeletePairing"},
+ {1951, nullptr, "SetPlayTimerSettingsForDebug"},
+ {1952, nullptr, "GetPlayTimerSpentTimeForTest"},
+ {1953, nullptr, "SetPlayTimerAlarmDisabledForDebug"},
+ {2001, nullptr, "RequestPairingAsync"},
+ {2002, nullptr, "FinishRequestPairing"},
+ {2003, nullptr, "AuthorizePairingAsync"},
+ {2004, nullptr, "FinishAuthorizePairing"},
+ {2005, nullptr, "RetrievePairingInfoAsync"},
+ {2006, nullptr, "FinishRetrievePairingInfo"},
+ {2007, nullptr, "UnlinkPairingAsync"},
+ {2008, nullptr, "FinishUnlinkPairing"},
+ {2009, nullptr, "GetAccountMiiImageAsync"},
+ {2010, nullptr, "FinishGetAccountMiiImage"},
+ {2011, nullptr, "GetAccountMiiImageContentTypeAsync"},
+ {2012, nullptr, "FinishGetAccountMiiImageContentType"},
+ {2013, nullptr, "SynchronizeParentalControlSettingsAsync"},
+ {2014, nullptr, "FinishSynchronizeParentalControlSettings"},
+ {2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
+ {2016, nullptr, "RequestUpdateExemptionListAsync"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+}
+
+IParentalControlService::~IParentalControlService() = default;
+
+bool IParentalControlService::CheckFreeCommunicationPermissionImpl() const {
+ if (states.temporary_unlocked) {
+ return true;
+ }
+ if ((states.application_info.parental_control_flag & 1) == 0) {
+ return true;
+ }
+ if (pin_code[0] == '\0') {
+ return true;
+ }
+ if (!settings.is_free_communication_default_on) {
+ return true;
+ }
+ // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here
+ // but as we don't have multiproceses support yet, we can just assume our application is
+ // valid for the time being
+ return true;
+}
+
+bool IParentalControlService::ConfirmStereoVisionPermissionImpl() const {
+ if (states.temporary_unlocked) {
+ return true;
+ }
+ if (pin_code[0] == '\0') {
+ return true;
+ }
+ if (!settings.is_stero_vision_restricted) {
+ return false;
+ }
+ return true;
+}
+
+void IParentalControlService::SetStereoVisionRestrictionImpl(bool is_restricted) {
+ if (settings.disabled) {
+ return;
+ }
+
+ if (pin_code[0] == '\0') {
+ return;
+ }
+ settings.is_stero_vision_restricted = is_restricted;
+}
+
+Result IParentalControlService::Initialize() {
+ LOG_DEBUG(Service_PCTL, "called");
+
+ if (False(capability & (Capability::Application | Capability::System))) {
+ LOG_ERROR(Service_PCTL, "Invalid capability! capability={:X}", capability);
+ R_THROW(PCTL::ResultNoCapability);
+ }
+
+ // TODO(ogniK): Recovery flag initialization for pctl:r
+
+ const auto program_id = system.GetApplicationProcessProgramID();
+ if (program_id != 0) {
+ const FileSys::PatchManager pm{program_id, system.GetFileSystemController(),
+ system.GetContentProvider()};
+ const auto control = pm.GetControlMetadata();
+ if (control.first) {
+ states.tid_from_event = 0;
+ states.launch_time_valid = false;
+ states.is_suspended = false;
+ states.free_communication = false;
+ states.stereo_vision = false;
+ states.application_info = ApplicationInfo{
+ .application_id = program_id,
+ .age_rating = control.first->GetRatingAge(),
+ .parental_control_flag = control.first->GetParentalControlFlag(),
+ .capability = capability,
+ };
+
+ if (False(capability & (Capability::System | Capability::Recovery))) {
+ // TODO(ogniK): Signal application launch event
+ }
+ }
+ }
+
+ R_SUCCEED();
+}
+
+Result IParentalControlService::CheckFreeCommunicationPermission() {
+ LOG_DEBUG(Service_PCTL, "called");
+
+ if (!CheckFreeCommunicationPermissionImpl()) {
+ R_THROW(PCTL::ResultNoFreeCommunication);
+ } else {
+ states.free_communication = true;
+ R_SUCCEED();
+ }
+}
+
+Result IParentalControlService::ConfirmLaunchApplicationPermission(
+ InBuffer<BufferAttr_HipcPointer> restriction_bitset, u64 nacp_flag, u64 application_id) {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, nacp_flag={:#x} application_id={:016X}", nacp_flag,
+ application_id);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::ConfirmResumeApplicationPermission(
+ InBuffer<BufferAttr_HipcPointer> restriction_bitset, u64 nacp_flag, u64 application_id) {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, nacp_flag={:#x} application_id={:016X}", nacp_flag,
+ application_id);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::ConfirmSnsPostPermission() {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called");
+ R_THROW(PCTL::ResultNoFreeCommunication);
+}
+
+Result IParentalControlService::IsRestrictionTemporaryUnlocked(
+ Out<bool> out_is_temporary_unlocked) {
+ *out_is_temporary_unlocked = false;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
+ *out_is_temporary_unlocked);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::IsRestrictedSystemSettingsEntered(
+ Out<bool> out_is_restricted_system_settings_entered) {
+ *out_is_restricted_system_settings_entered = false;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
+ *out_is_restricted_system_settings_entered);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::ConfirmStereoVisionPermission() {
+ LOG_DEBUG(Service_PCTL, "called");
+ states.stereo_vision = true;
+ R_SUCCEED();
+}
+
+Result IParentalControlService::EndFreeCommunication() {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IParentalControlService::IsFreeCommunicationAvailable() {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called");
+
+ if (!CheckFreeCommunicationPermissionImpl()) {
+ R_THROW(PCTL::ResultNoFreeCommunication);
+ } else {
+ R_SUCCEED();
+ }
+}
+
+Result IParentalControlService::IsRestrictionEnabled(Out<bool> out_restriction_enabled) {
+ LOG_DEBUG(Service_PCTL, "called");
+
+ if (False(capability & (Capability::Status | Capability::Recovery))) {
+ LOG_ERROR(Service_PCTL, "Application does not have Status or Recovery capabilities!");
+ *out_restriction_enabled = false;
+ R_THROW(PCTL::ResultNoCapability);
+ }
+
+ *out_restriction_enabled = pin_code[0] != '\0';
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetSafetyLevel(Out<u32> out_safety_level) {
+ *out_safety_level = 0;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, safety_level={}", *out_safety_level);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetCurrentSettings(Out<RestrictionSettings> out_settings) {
+ LOG_INFO(Service_PCTL, "called");
+ *out_settings = restriction_settings;
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetFreeCommunicationApplicationListCount(Out<s32> out_count) {
+ *out_count = 4;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, count={}", *out_count);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::ConfirmStereoVisionRestrictionConfigurable() {
+ LOG_DEBUG(Service_PCTL, "called");
+
+ if (False(capability & Capability::StereoVision)) {
+ LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
+ R_THROW(PCTL::ResultNoCapability);
+ }
+
+ if (pin_code[0] == '\0') {
+ R_THROW(PCTL::ResultNoRestrictionEnabled);
+ }
+
+ R_SUCCEED();
+}
+
+Result IParentalControlService::IsStereoVisionPermitted(Out<bool> out_is_permitted) {
+ LOG_DEBUG(Service_PCTL, "called");
+
+ if (!ConfirmStereoVisionPermissionImpl()) {
+ *out_is_permitted = false;
+ R_THROW(PCTL::ResultStereoVisionRestricted);
+ } else {
+ *out_is_permitted = true;
+ R_SUCCEED();
+ }
+}
+
+Result IParentalControlService::GetPinCodeLength(Out<s32> out_length) {
+ *out_length = 0;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, length={}", *out_length);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::IsPairingActive(Out<bool> out_is_pairing_active) {
+ *out_is_pairing_active = false;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", *out_is_pairing_active);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetSynchronizationEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_PCTL, "called");
+ *out_event = synchronization_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IParentalControlService::StartPlayTimer() {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IParentalControlService::StopPlayTimer() {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IParentalControlService::IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled) {
+ *out_is_play_timer_enabled = false;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, enabled={}", *out_is_play_timer_enabled);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer) {
+ *out_is_restricted_by_play_timer = false;
+ LOG_WARNING(Service_PCTL, "(STUBBED) called, restricted={}", *out_is_restricted_by_play_timer);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetPlayTimerSettings(
+ Out<PlayTimerSettings> out_play_timer_settings) {
+ LOG_WARNING(Service_PCTL, "(STUBBED) called");
+ *out_play_timer_settings = {};
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetPlayTimerEventToRequestSuspension(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_PCTL, "called");
+ *out_event = request_suspension_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={}",
+ *out_play_timer_alarm_disabled);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_INFO(Service_PCTL, "called");
+ *out_event = unlinked_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IParentalControlService::GetStereoVisionRestriction(
+ Out<bool> out_stereo_vision_restriction) {
+ LOG_DEBUG(Service_PCTL, "called");
+
+ if (False(capability & Capability::StereoVision)) {
+ LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
+ *out_stereo_vision_restriction = false;
+ R_THROW(PCTL::ResultNoCapability);
+ }
+
+ *out_stereo_vision_restriction = settings.is_stero_vision_restricted;
+ R_SUCCEED();
+}
+
+Result IParentalControlService::SetStereoVisionRestriction(bool stereo_vision_restriction) {
+ LOG_DEBUG(Service_PCTL, "called, can_use={}", stereo_vision_restriction);
+
+ if (False(capability & Capability::StereoVision)) {
+ LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
+ R_THROW(PCTL::ResultNoCapability);
+ }
+
+ SetStereoVisionRestrictionImpl(stereo_vision_restriction);
+ R_SUCCEED();
+}
+
+Result IParentalControlService::ResetConfirmedStereoVisionPermission() {
+ LOG_DEBUG(Service_PCTL, "called");
+
+ states.stereo_vision = false;
+
+ R_SUCCEED();
+}
+
+} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/parental_control_service.h b/src/core/hle/service/pctl/parental_control_service.h
new file mode 100644
index 000000000..03dbaa2e5
--- /dev/null
+++ b/src/core/hle/service/pctl/parental_control_service.h
@@ -0,0 +1,86 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/pctl/pctl_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::PCTL {
+
+class IParentalControlService final : public ServiceFramework<IParentalControlService> {
+public:
+ explicit IParentalControlService(Core::System& system_, Capability capability_);
+ ~IParentalControlService() override;
+
+private:
+ bool CheckFreeCommunicationPermissionImpl() const;
+ bool ConfirmStereoVisionPermissionImpl() const;
+ void SetStereoVisionRestrictionImpl(bool is_restricted);
+
+ Result Initialize();
+ Result CheckFreeCommunicationPermission();
+ Result ConfirmLaunchApplicationPermission(InBuffer<BufferAttr_HipcPointer> restriction_bitset,
+ u64 nacp_flag, u64 application_id);
+ Result ConfirmResumeApplicationPermission(InBuffer<BufferAttr_HipcPointer> restriction_bitset,
+ u64 nacp_flag, u64 application_id);
+ Result ConfirmSnsPostPermission();
+ Result IsRestrictionTemporaryUnlocked(Out<bool> out_is_temporary_unlocked);
+ Result IsRestrictedSystemSettingsEntered(Out<bool> out_is_restricted_system_settings_entered);
+ Result ConfirmStereoVisionPermission();
+ Result EndFreeCommunication();
+ Result IsFreeCommunicationAvailable();
+ Result IsRestrictionEnabled(Out<bool> out_restriction_enabled);
+ Result GetSafetyLevel(Out<u32> out_safety_level);
+ Result GetCurrentSettings(Out<RestrictionSettings> out_settings);
+ Result GetFreeCommunicationApplicationListCount(Out<s32> out_count);
+ Result ConfirmStereoVisionRestrictionConfigurable();
+ Result IsStereoVisionPermitted(Out<bool> out_is_permitted);
+ Result GetPinCodeLength(Out<s32> out_length);
+ Result IsPairingActive(Out<bool> out_is_pairing_active);
+ Result GetSynchronizationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result StartPlayTimer();
+ Result StopPlayTimer();
+ 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 GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled);
+ Result GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction);
+ Result SetStereoVisionRestriction(bool stereo_vision_restriction);
+ Result ResetConfirmedStereoVisionPermission();
+
+ struct States {
+ u64 current_tid{};
+ ApplicationInfo application_info{};
+ u64 tid_from_event{};
+ bool launch_time_valid{};
+ bool is_suspended{};
+ bool temporary_unlocked{};
+ bool free_communication{};
+ bool stereo_vision{};
+ };
+
+ struct ParentalControlSettings {
+ bool is_stero_vision_restricted{};
+ bool is_free_communication_default_on{};
+ bool disabled{};
+ };
+
+ States states{};
+ ParentalControlSettings settings{};
+ RestrictionSettings restriction_settings{};
+ std::array<char, 8> pin_code{};
+ Capability capability{};
+
+ KernelHelpers::ServiceContext service_context;
+ Event synchronization_event;
+ Event unlinked_event;
+ Event request_suspension_event;
+};
+
+} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/parental_control_service_factory.cpp b/src/core/hle/service/pctl/parental_control_service_factory.cpp
new file mode 100644
index 000000000..7d8f361e9
--- /dev/null
+++ b/src/core/hle/service/pctl/parental_control_service_factory.cpp
@@ -0,0 +1,40 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/pctl/parental_control_service.h"
+#include "core/hle/service/pctl/parental_control_service_factory.h"
+
+namespace Service::PCTL {
+
+IParentalControlServiceFactory::IParentalControlServiceFactory(Core::System& system_,
+ const char* name_,
+ Capability capability_)
+ : ServiceFramework{system_, name_}, capability{capability_} {
+ static const FunctionInfo functions[] = {
+ {0, D<&IParentalControlServiceFactory::CreateService>, "CreateService"},
+ {1, D<&IParentalControlServiceFactory::CreateServiceWithoutInitialize>,
+ "CreateServiceWithoutInitialize"},
+ };
+ RegisterHandlers(functions);
+}
+
+IParentalControlServiceFactory::~IParentalControlServiceFactory() = default;
+
+Result IParentalControlServiceFactory::CreateService(
+ Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) {
+ LOG_DEBUG(Service_PCTL, "called");
+ // TODO(ogniK): Get application id from process
+ *out_service = std::make_shared<IParentalControlService>(system, capability);
+ R_SUCCEED();
+}
+
+Result IParentalControlServiceFactory::CreateServiceWithoutInitialize(
+ Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) {
+ LOG_DEBUG(Service_PCTL, "called");
+ // TODO(ogniK): Get application id from process
+ *out_service = std::make_shared<IParentalControlService>(system, capability);
+ R_SUCCEED();
+}
+
+} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/parental_control_service_factory.h b/src/core/hle/service/pctl/parental_control_service_factory.h
new file mode 100644
index 000000000..362988add
--- /dev/null
+++ b/src/core/hle/service/pctl/parental_control_service_factory.h
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/pctl/pctl_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::PCTL {
+
+class IParentalControlService;
+
+class IParentalControlServiceFactory : public ServiceFramework<IParentalControlServiceFactory> {
+public:
+ explicit IParentalControlServiceFactory(Core::System& system_, const char* name_,
+ Capability capability_);
+ ~IParentalControlServiceFactory() override;
+
+ Result CreateService(Out<SharedPointer<IParentalControlService>> out_service,
+ ClientProcessId process_id);
+ Result CreateServiceWithoutInitialize(Out<SharedPointer<IParentalControlService>> out_service,
+ ClientProcessId process_id);
+
+private:
+ Capability capability{};
+};
+
+void LoopProcess(Core::System& system);
+
+} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp
index 3f47bf094..d92dbe216 100644
--- a/src/core/hle/service/pctl/pctl.cpp
+++ b/src/core/hle/service/pctl/pctl.cpp
@@ -1,19 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "core/hle/service/pctl/parental_control_service_factory.h"
#include "core/hle/service/pctl/pctl.h"
+#include "core/hle/service/server_manager.h"
namespace Service::PCTL {
-PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name,
- Capability capability_)
- : Interface{system_, std::move(module_), name, capability_} {
- static const FunctionInfo functions[] = {
- {0, &PCTL::CreateService, "CreateService"},
- {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"},
- };
- RegisterHandlers(functions);
+void LoopProcess(Core::System& system) {
+ auto server_manager = std::make_unique<ServerManager>(system);
+
+ server_manager->RegisterNamedService("pctl",
+ std::make_shared<IParentalControlServiceFactory>(
+ system, "pctl",
+ Capability::Application | Capability::SnsPost |
+ Capability::Status | Capability::StereoVision));
+ // TODO(ogniK): Implement remaining capabilities
+ server_manager->RegisterNamedService("pctl:a", std::make_shared<IParentalControlServiceFactory>(
+ system, "pctl:a", Capability::None));
+ server_manager->RegisterNamedService("pctl:r", std::make_shared<IParentalControlServiceFactory>(
+ system, "pctl:r", Capability::None));
+ server_manager->RegisterNamedService("pctl:s", std::make_shared<IParentalControlServiceFactory>(
+ system, "pctl:s", Capability::None));
+ ServerManager::RunServer(std::move(server_manager));
}
-PCTL::~PCTL() = default;
} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h
index 87f93161e..5f9d03d4d 100644
--- a/src/core/hle/service/pctl/pctl.h
+++ b/src/core/hle/service/pctl/pctl.h
@@ -3,19 +3,12 @@
#pragma once
-#include "core/hle/service/pctl/pctl_module.h"
-
namespace Core {
class System;
}
namespace Service::PCTL {
-class PCTL final : public Module::Interface {
-public:
- explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name,
- Capability capability_);
- ~PCTL() override;
-};
+void LoopProcess(Core::System& system);
} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp
deleted file mode 100644
index 6a7fd72bc..000000000
--- a/src/core/hle/service/pctl/pctl_module.cpp
+++ /dev/null
@@ -1,550 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/core.h"
-#include "core/file_sys/control_metadata.h"
-#include "core/file_sys/patch_manager.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/pctl/pctl.h"
-#include "core/hle/service/pctl/pctl_module.h"
-#include "core/hle/service/server_manager.h"
-
-namespace Service::PCTL {
-
-namespace Error {
-
-constexpr Result ResultNoFreeCommunication{ErrorModule::PCTL, 101};
-constexpr Result ResultStereoVisionRestricted{ErrorModule::PCTL, 104};
-constexpr Result ResultNoCapability{ErrorModule::PCTL, 131};
-constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
-
-} // namespace Error
-
-class IParentalControlService final : public ServiceFramework<IParentalControlService> {
-public:
- explicit IParentalControlService(Core::System& system_, Capability capability_)
- : ServiceFramework{system_, "IParentalControlService"}, capability{capability_},
- service_context{system_, "IParentalControlService"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1, &IParentalControlService::Initialize, "Initialize"},
- {1001, &IParentalControlService::CheckFreeCommunicationPermission, "CheckFreeCommunicationPermission"},
- {1002, nullptr, "ConfirmLaunchApplicationPermission"},
- {1003, nullptr, "ConfirmResumeApplicationPermission"},
- {1004, &IParentalControlService::ConfirmSnsPostPermission, "ConfirmSnsPostPermission"},
- {1005, nullptr, "ConfirmSystemSettingsPermission"},
- {1006, &IParentalControlService::IsRestrictionTemporaryUnlocked, "IsRestrictionTemporaryUnlocked"},
- {1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
- {1008, nullptr, "EnterRestrictedSystemSettings"},
- {1009, nullptr, "LeaveRestrictedSystemSettings"},
- {1010, nullptr, "IsRestrictedSystemSettingsEntered"},
- {1011, nullptr, "RevertRestrictedSystemSettingsEntered"},
- {1012, nullptr, "GetRestrictedFeatures"},
- {1013, &IParentalControlService::ConfirmStereoVisionPermission, "ConfirmStereoVisionPermission"},
- {1014, nullptr, "ConfirmPlayableApplicationVideoOld"},
- {1015, nullptr, "ConfirmPlayableApplicationVideo"},
- {1016, nullptr, "ConfirmShowNewsPermission"},
- {1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"},
- {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"},
- {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"},
- {1032, &IParentalControlService::GetSafetyLevel, "GetSafetyLevel"},
- {1033, nullptr, "SetSafetyLevel"},
- {1034, nullptr, "GetSafetyLevelSettings"},
- {1035, &IParentalControlService::GetCurrentSettings, "GetCurrentSettings"},
- {1036, nullptr, "SetCustomSafetyLevelSettings"},
- {1037, nullptr, "GetDefaultRatingOrganization"},
- {1038, nullptr, "SetDefaultRatingOrganization"},
- {1039, &IParentalControlService::GetFreeCommunicationApplicationListCount, "GetFreeCommunicationApplicationListCount"},
- {1042, nullptr, "AddToFreeCommunicationApplicationList"},
- {1043, nullptr, "DeleteSettings"},
- {1044, nullptr, "GetFreeCommunicationApplicationList"},
- {1045, nullptr, "UpdateFreeCommunicationApplicationList"},
- {1046, nullptr, "DisableFeaturesForReset"},
- {1047, nullptr, "NotifyApplicationDownloadStarted"},
- {1048, nullptr, "NotifyNetworkProfileCreated"},
- {1049, nullptr, "ResetFreeCommunicationApplicationList"},
- {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"},
- {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"},
- {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"},
- {1064, &IParentalControlService::ResetConfirmedStereoVisionPermission, "ResetConfirmedStereoVisionPermission"},
- {1065, &IParentalControlService::IsStereoVisionPermitted, "IsStereoVisionPermitted"},
- {1201, nullptr, "UnlockRestrictionTemporarily"},
- {1202, nullptr, "UnlockSystemSettingsRestriction"},
- {1203, nullptr, "SetPinCode"},
- {1204, nullptr, "GenerateInquiryCode"},
- {1205, nullptr, "CheckMasterKey"},
- {1206, nullptr, "GetPinCodeLength"},
- {1207, nullptr, "GetPinCodeChangedEvent"},
- {1208, nullptr, "GetPinCode"},
- {1403, &IParentalControlService::IsPairingActive, "IsPairingActive"},
- {1406, nullptr, "GetSettingsLastUpdated"},
- {1411, nullptr, "GetPairingAccountInfo"},
- {1421, nullptr, "GetAccountNickname"},
- {1424, nullptr, "GetAccountState"},
- {1425, nullptr, "RequestPostEvents"},
- {1426, nullptr, "GetPostEventInterval"},
- {1427, nullptr, "SetPostEventInterval"},
- {1432, &IParentalControlService::GetSynchronizationEvent, "GetSynchronizationEvent"},
- {1451, nullptr, "StartPlayTimer"},
- {1452, nullptr, "StopPlayTimer"},
- {1453, nullptr, "IsPlayTimerEnabled"},
- {1454, nullptr, "GetPlayTimerRemainingTime"},
- {1455, nullptr, "IsRestrictedByPlayTimer"},
- {1456, &IParentalControlService::GetPlayTimerSettings, "GetPlayTimerSettings"},
- {1457, &IParentalControlService::GetPlayTimerEventToRequestSuspension, "GetPlayTimerEventToRequestSuspension"},
- {1458, &IParentalControlService::IsPlayTimerAlarmDisabled, "IsPlayTimerAlarmDisabled"},
- {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
- {1472, nullptr, "CancelNetworkRequest"},
- {1473, &IParentalControlService::GetUnlinkedEvent, "GetUnlinkedEvent"},
- {1474, nullptr, "ClearUnlinkedEvent"},
- {1601, nullptr, "DisableAllFeatures"},
- {1602, nullptr, "PostEnableAllFeatures"},
- {1603, nullptr, "IsAllFeaturesDisabled"},
- {1901, nullptr, "DeleteFromFreeCommunicationApplicationListForDebug"},
- {1902, nullptr, "ClearFreeCommunicationApplicationListForDebug"},
- {1903, nullptr, "GetExemptApplicationListCountForDebug"},
- {1904, nullptr, "GetExemptApplicationListForDebug"},
- {1905, nullptr, "UpdateExemptApplicationListForDebug"},
- {1906, nullptr, "AddToExemptApplicationListForDebug"},
- {1907, nullptr, "DeleteFromExemptApplicationListForDebug"},
- {1908, nullptr, "ClearExemptApplicationListForDebug"},
- {1941, nullptr, "DeletePairing"},
- {1951, nullptr, "SetPlayTimerSettingsForDebug"},
- {1952, nullptr, "GetPlayTimerSpentTimeForTest"},
- {1953, nullptr, "SetPlayTimerAlarmDisabledForDebug"},
- {2001, nullptr, "RequestPairingAsync"},
- {2002, nullptr, "FinishRequestPairing"},
- {2003, nullptr, "AuthorizePairingAsync"},
- {2004, nullptr, "FinishAuthorizePairing"},
- {2005, nullptr, "RetrievePairingInfoAsync"},
- {2006, nullptr, "FinishRetrievePairingInfo"},
- {2007, nullptr, "UnlinkPairingAsync"},
- {2008, nullptr, "FinishUnlinkPairing"},
- {2009, nullptr, "GetAccountMiiImageAsync"},
- {2010, nullptr, "FinishGetAccountMiiImage"},
- {2011, nullptr, "GetAccountMiiImageContentTypeAsync"},
- {2012, nullptr, "FinishGetAccountMiiImageContentType"},
- {2013, nullptr, "SynchronizeParentalControlSettingsAsync"},
- {2014, nullptr, "FinishSynchronizeParentalControlSettings"},
- {2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
- {2016, nullptr, "RequestUpdateExemptionListAsync"},
- };
- // clang-format on
- RegisterHandlers(functions);
-
- synchronization_event =
- service_context.CreateEvent("IParentalControlService::SynchronizationEvent");
- unlinked_event = service_context.CreateEvent("IParentalControlService::UnlinkedEvent");
- request_suspension_event =
- service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent");
- }
-
- ~IParentalControlService() {
- service_context.CloseEvent(synchronization_event);
- service_context.CloseEvent(unlinked_event);
- service_context.CloseEvent(request_suspension_event);
- };
-
-private:
- bool CheckFreeCommunicationPermissionImpl() const {
- if (states.temporary_unlocked) {
- return true;
- }
- if ((states.application_info.parental_control_flag & 1) == 0) {
- return true;
- }
- if (pin_code[0] == '\0') {
- return true;
- }
- if (!settings.is_free_communication_default_on) {
- return true;
- }
- // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here
- // but as we don't have multiproceses support yet, we can just assume our application is
- // valid for the time being
- return true;
- }
-
- bool ConfirmStereoVisionPermissionImpl() const {
- if (states.temporary_unlocked) {
- return true;
- }
- if (pin_code[0] == '\0') {
- return true;
- }
- if (!settings.is_stero_vision_restricted) {
- return false;
- }
- return true;
- }
-
- void SetStereoVisionRestrictionImpl(bool is_restricted) {
- if (settings.disabled) {
- return;
- }
-
- if (pin_code[0] == '\0') {
- return;
- }
- settings.is_stero_vision_restricted = is_restricted;
- }
-
- void Initialize(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
- IPC::ResponseBuilder rb{ctx, 2};
-
- if (False(capability & (Capability::Application | Capability::System))) {
- LOG_ERROR(Service_PCTL, "Invalid capability! capability={:X}", capability);
- return;
- }
-
- // TODO(ogniK): Recovery flag initialization for pctl:r
-
- const auto tid = system.GetApplicationProcessProgramID();
- if (tid != 0) {
- const FileSys::PatchManager pm{tid, system.GetFileSystemController(),
- system.GetContentProvider()};
- const auto control = pm.GetControlMetadata();
- if (control.first) {
- states.tid_from_event = 0;
- states.launch_time_valid = false;
- states.is_suspended = false;
- states.free_communication = false;
- states.stereo_vision = false;
- states.application_info = ApplicationInfo{
- .tid = tid,
- .age_rating = control.first->GetRatingAge(),
- .parental_control_flag = control.first->GetParentalControlFlag(),
- .capability = capability,
- };
-
- if (False(capability & (Capability::System | Capability::Recovery))) {
- // TODO(ogniK): Signal application launch event
- }
- }
- }
-
- rb.Push(ResultSuccess);
- }
-
- void CheckFreeCommunicationPermission(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- if (!CheckFreeCommunicationPermissionImpl()) {
- rb.Push(Error::ResultNoFreeCommunication);
- } else {
- rb.Push(ResultSuccess);
- }
-
- states.free_communication = true;
- }
-
- void ConfirmSnsPostPermission(HLERequestContext& ctx) {
- LOG_WARNING(Service_PCTL, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(Error::ResultNoFreeCommunication);
- }
-
- void IsRestrictionTemporaryUnlocked(HLERequestContext& ctx) {
- const bool is_temporary_unlocked = false;
-
- LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
- is_temporary_unlocked);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_temporary_unlocked);
- }
-
- void ConfirmStereoVisionPermission(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
- states.stereo_vision = true;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void EndFreeCommunication(HLERequestContext& ctx) {
- LOG_WARNING(Service_PCTL, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void IsFreeCommunicationAvailable(HLERequestContext& ctx) {
- LOG_WARNING(Service_PCTL, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- if (!CheckFreeCommunicationPermissionImpl()) {
- rb.Push(Error::ResultNoFreeCommunication);
- } else {
- rb.Push(ResultSuccess);
- }
- }
-
- void IsRestrictionEnabled(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- if (False(capability & (Capability::Status | Capability::Recovery))) {
- LOG_ERROR(Service_PCTL, "Application does not have Status or Recovery capabilities!");
- rb.Push(Error::ResultNoCapability);
- rb.Push(false);
- return;
- }
-
- rb.Push(pin_code[0] != '\0');
- }
-
- void GetSafetyLevel(HLERequestContext& ctx) {
- const u32 safety_level = 0;
-
- LOG_WARNING(Service_PCTL, "(STUBBED) called, safety_level={}", safety_level);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(safety_level);
- }
-
- void GetCurrentSettings(HLERequestContext& ctx) {
- LOG_INFO(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushRaw(restriction_settings);
- }
-
- void GetFreeCommunicationApplicationListCount(HLERequestContext& ctx) {
- const u32 count = 4;
-
- LOG_WARNING(Service_PCTL, "(STUBBED) called, count={}", count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(count);
- }
-
- void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 2};
-
- if (False(capability & Capability::StereoVision)) {
- LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
- rb.Push(Error::ResultNoCapability);
- return;
- }
-
- if (pin_code[0] == '\0') {
- rb.Push(Error::ResultNoRestrictionEnabled);
- return;
- }
-
- rb.Push(ResultSuccess);
- }
-
- void IsStereoVisionPermitted(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- if (!ConfirmStereoVisionPermissionImpl()) {
- rb.Push(Error::ResultStereoVisionRestricted);
- rb.Push(false);
- } else {
- rb.Push(ResultSuccess);
- rb.Push(true);
- }
- }
-
- void IsPairingActive(HLERequestContext& ctx) {
- const bool is_pairing_active = false;
-
- LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", is_pairing_active);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_pairing_active);
- }
-
- void GetSynchronizationEvent(HLERequestContext& ctx) {
- LOG_INFO(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(synchronization_event->GetReadableEvent());
- }
-
- void GetPlayTimerSettings(HLERequestContext& ctx) {
- LOG_WARNING(Service_PCTL, "(STUBBED) called");
-
- const PlayTimerSettings timer_settings{};
-
- IPC::ResponseBuilder rb{ctx, 15};
- rb.Push(ResultSuccess);
- rb.PushRaw(timer_settings);
- }
-
- void GetPlayTimerEventToRequestSuspension(HLERequestContext& ctx) {
- LOG_INFO(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(request_suspension_event->GetReadableEvent());
- }
-
- void IsPlayTimerAlarmDisabled(HLERequestContext& ctx) {
- const bool is_play_timer_alarm_disabled = false;
-
- LOG_INFO(Service_PCTL, "called, is_play_timer_alarm_disabled={}",
- is_play_timer_alarm_disabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(is_play_timer_alarm_disabled);
- }
-
- void GetUnlinkedEvent(HLERequestContext& ctx) {
- LOG_INFO(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(unlinked_event->GetReadableEvent());
- }
-
- void SetStereoVisionRestriction(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto can_use = rp.Pop<bool>();
- LOG_DEBUG(Service_PCTL, "called, can_use={}", can_use);
-
- IPC::ResponseBuilder rb{ctx, 2};
- if (False(capability & Capability::StereoVision)) {
- LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
- rb.Push(Error::ResultNoCapability);
- return;
- }
-
- SetStereoVisionRestrictionImpl(can_use);
- rb.Push(ResultSuccess);
- }
-
- void GetStereoVisionRestriction(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- if (False(capability & Capability::StereoVision)) {
- LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
- rb.Push(Error::ResultNoCapability);
- rb.Push(false);
- return;
- }
-
- rb.Push(ResultSuccess);
- rb.Push(settings.is_stero_vision_restricted);
- }
-
- void ResetConfirmedStereoVisionPermission(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- states.stereo_vision = false;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- struct ApplicationInfo {
- u64 tid{};
- std::array<u8, 32> age_rating{};
- u32 parental_control_flag{};
- Capability capability{};
- };
-
- struct States {
- u64 current_tid{};
- ApplicationInfo application_info{};
- u64 tid_from_event{};
- bool launch_time_valid{};
- bool is_suspended{};
- bool temporary_unlocked{};
- bool free_communication{};
- bool stereo_vision{};
- };
-
- struct ParentalControlSettings {
- bool is_stero_vision_restricted{};
- bool is_free_communication_default_on{};
- bool disabled{};
- };
-
- // This is nn::pctl::RestrictionSettings
- struct RestrictionSettings {
- u8 rating_age;
- bool sns_post_restriction;
- bool free_communication_restriction;
- };
- static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size.");
-
- // This is nn::pctl::PlayTimerSettings
- struct PlayTimerSettings {
- std::array<u32, 13> settings;
- };
- static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
-
- States states{};
- ParentalControlSettings settings{};
- RestrictionSettings restriction_settings{};
- std::array<char, 8> pin_code{};
- Capability capability{};
-
- Kernel::KEvent* synchronization_event;
- Kernel::KEvent* unlinked_event;
- Kernel::KEvent* request_suspension_event;
- KernelHelpers::ServiceContext service_context;
-};
-
-void Module::Interface::CreateService(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- // TODO(ogniK): Get TID from process
-
- rb.PushIpcInterface<IParentalControlService>(system, capability);
-}
-
-void Module::Interface::CreateServiceWithoutInitialize(HLERequestContext& ctx) {
- LOG_DEBUG(Service_PCTL, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IParentalControlService>(system, capability);
-}
-
-Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_,
- const char* name_, Capability capability_)
- : ServiceFramework{system_, name_}, module{std::move(module_)}, capability{capability_} {}
-
-Module::Interface::~Interface() = default;
-
-void LoopProcess(Core::System& system) {
- auto server_manager = std::make_unique<ServerManager>(system);
-
- auto module = std::make_shared<Module>();
- server_manager->RegisterNamedService(
- "pctl", std::make_shared<PCTL>(system, module, "pctl",
- Capability::Application | Capability::SnsPost |
- Capability::Status | Capability::StereoVision));
- // TODO(ogniK): Implement remaining capabilities
- server_manager->RegisterNamedService(
- "pctl:a", std::make_shared<PCTL>(system, module, "pctl:a", Capability::None));
- server_manager->RegisterNamedService(
- "pctl:r", std::make_shared<PCTL>(system, module, "pctl:r", Capability::None));
- server_manager->RegisterNamedService(
- "pctl:s", std::make_shared<PCTL>(system, module, "pctl:s", Capability::None));
- ServerManager::RunServer(std::move(server_manager));
-}
-
-} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl_module.h b/src/core/hle/service/pctl/pctl_module.h
deleted file mode 100644
index dff0d3f08..000000000
--- a/src/core/hle/service/pctl/pctl_module.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "common/common_funcs.h"
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace Service::PCTL {
-
-enum class Capability : u32 {
- None = 0,
- Application = 1 << 0,
- SnsPost = 1 << 1,
- Recovery = 1 << 6,
- Status = 1 << 8,
- StereoVision = 1 << 9,
- System = 1 << 15,
-};
-DECLARE_ENUM_FLAG_OPERATORS(Capability);
-
-class Module final {
-public:
- class Interface : public ServiceFramework<Interface> {
- public:
- explicit Interface(Core::System& system_, std::shared_ptr<Module> module_,
- const char* name_, Capability capability_);
- ~Interface() override;
-
- void CreateService(HLERequestContext& ctx);
- void CreateServiceWithoutInitialize(HLERequestContext& ctx);
-
- protected:
- std::shared_ptr<Module> module;
-
- private:
- Capability capability{};
- };
-};
-
-void LoopProcess(Core::System& system);
-
-} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl_results.h b/src/core/hle/service/pctl/pctl_results.h
new file mode 100644
index 000000000..1fc54727b
--- /dev/null
+++ b/src/core/hle/service/pctl/pctl_results.h
@@ -0,0 +1,15 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/result.h"
+
+namespace Service::PCTL {
+
+constexpr Result ResultNoFreeCommunication{ErrorModule::PCTL, 101};
+constexpr Result ResultStereoVisionRestricted{ErrorModule::PCTL, 104};
+constexpr Result ResultNoCapability{ErrorModule::PCTL, 131};
+constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
+
+} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl_types.h b/src/core/hle/service/pctl/pctl_types.h
new file mode 100644
index 000000000..daaecdf48
--- /dev/null
+++ b/src/core/hle/service/pctl/pctl_types.h
@@ -0,0 +1,43 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_funcs.h"
+
+namespace Service::PCTL {
+
+enum class Capability : u32 {
+ None = 0,
+ Application = 1 << 0,
+ SnsPost = 1 << 1,
+ Recovery = 1 << 6,
+ Status = 1 << 8,
+ StereoVision = 1 << 9,
+ System = 1 << 15,
+};
+DECLARE_ENUM_FLAG_OPERATORS(Capability);
+
+struct ApplicationInfo {
+ u64 application_id{};
+ std::array<u8, 32> age_rating{};
+ u32 parental_control_flag{};
+ Capability capability{};
+};
+static_assert(sizeof(ApplicationInfo) == 0x30, "ApplicationInfo has incorrect size.");
+
+// This is nn::pctl::RestrictionSettings
+struct RestrictionSettings {
+ u8 rating_age;
+ bool sns_post_restriction;
+ bool free_communication_restriction;
+};
+static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size.");
+
+// This is nn::pctl::PlayTimerSettings
+struct PlayTimerSettings {
+ std::array<u32, 13> settings;
+};
+static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
+
+} // namespace Service::PCTL
diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp
index d6c6eff50..1aa85ea54 100644
--- a/src/core/hle/service/services.cpp
+++ b/src/core/hle/service/services.cpp
@@ -46,7 +46,7 @@
#include "core/hle/service/olsc/olsc.h"
#include "core/hle/service/omm/omm.h"
#include "core/hle/service/pcie/pcie.h"
-#include "core/hle/service/pctl/pctl_module.h"
+#include "core/hle/service/pctl/pctl.h"
#include "core/hle/service/pcv/pcv.h"
#include "core/hle/service/pm/pm.h"
#include "core/hle/service/prepo/prepo.h"