pctl_module.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/logging/log.h"
  5. #include "core/core.h"
  6. #include "core/file_sys/control_metadata.h"
  7. #include "core/file_sys/patch_manager.h"
  8. #include "core/hle/ipc_helpers.h"
  9. #include "core/hle/kernel/k_process.h"
  10. #include "core/hle/service/pctl/pctl.h"
  11. #include "core/hle/service/pctl/pctl_module.h"
  12. namespace Service::PCTL {
  13. namespace Error {
  14. constexpr ResultCode ResultNoFreeCommunication{ErrorModule::PCTL, 101};
  15. constexpr ResultCode ResultStereoVisionRestricted{ErrorModule::PCTL, 104};
  16. constexpr ResultCode ResultNoCapability{ErrorModule::PCTL, 131};
  17. constexpr ResultCode ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
  18. } // namespace Error
  19. class IParentalControlService final : public ServiceFramework<IParentalControlService> {
  20. public:
  21. explicit IParentalControlService(Core::System& system_, Capability capability_)
  22. : ServiceFramework{system_, "IParentalControlService"}, capability{capability_} {
  23. // clang-format off
  24. static const FunctionInfo functions[] = {
  25. {1, &IParentalControlService::Initialize, "Initialize"},
  26. {1001, &IParentalControlService::CheckFreeCommunicationPermission, "CheckFreeCommunicationPermission"},
  27. {1002, nullptr, "ConfirmLaunchApplicationPermission"},
  28. {1003, nullptr, "ConfirmResumeApplicationPermission"},
  29. {1004, nullptr, "ConfirmSnsPostPermission"},
  30. {1005, nullptr, "ConfirmSystemSettingsPermission"},
  31. {1006, nullptr, "IsRestrictionTemporaryUnlocked"},
  32. {1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
  33. {1008, nullptr, "EnterRestrictedSystemSettings"},
  34. {1009, nullptr, "LeaveRestrictedSystemSettings"},
  35. {1010, nullptr, "IsRestrictedSystemSettingsEntered"},
  36. {1011, nullptr, "RevertRestrictedSystemSettingsEntered"},
  37. {1012, nullptr, "GetRestrictedFeatures"},
  38. {1013, &IParentalControlService::ConfirmStereoVisionPermission, "ConfirmStereoVisionPermission"},
  39. {1014, nullptr, "ConfirmPlayableApplicationVideoOld"},
  40. {1015, nullptr, "ConfirmPlayableApplicationVideo"},
  41. {1016, nullptr, "ConfirmShowNewsPermission"},
  42. {1017, nullptr, "EndFreeCommunication"},
  43. {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"},
  44. {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"},
  45. {1032, nullptr, "GetSafetyLevel"},
  46. {1033, nullptr, "SetSafetyLevel"},
  47. {1034, nullptr, "GetSafetyLevelSettings"},
  48. {1035, nullptr, "GetCurrentSettings"},
  49. {1036, nullptr, "SetCustomSafetyLevelSettings"},
  50. {1037, nullptr, "GetDefaultRatingOrganization"},
  51. {1038, nullptr, "SetDefaultRatingOrganization"},
  52. {1039, nullptr, "GetFreeCommunicationApplicationListCount"},
  53. {1042, nullptr, "AddToFreeCommunicationApplicationList"},
  54. {1043, nullptr, "DeleteSettings"},
  55. {1044, nullptr, "GetFreeCommunicationApplicationList"},
  56. {1045, nullptr, "UpdateFreeCommunicationApplicationList"},
  57. {1046, nullptr, "DisableFeaturesForReset"},
  58. {1047, nullptr, "NotifyApplicationDownloadStarted"},
  59. {1048, nullptr, "NotifyNetworkProfileCreated"},
  60. {1049, nullptr, "ResetFreeCommunicationApplicationList"},
  61. {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"},
  62. {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"},
  63. {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"},
  64. {1064, &IParentalControlService::ResetConfirmedStereoVisionPermission, "ResetConfirmedStereoVisionPermission"},
  65. {1065, &IParentalControlService::IsStereoVisionPermitted, "IsStereoVisionPermitted"},
  66. {1201, nullptr, "UnlockRestrictionTemporarily"},
  67. {1202, nullptr, "UnlockSystemSettingsRestriction"},
  68. {1203, nullptr, "SetPinCode"},
  69. {1204, nullptr, "GenerateInquiryCode"},
  70. {1205, nullptr, "CheckMasterKey"},
  71. {1206, nullptr, "GetPinCodeLength"},
  72. {1207, nullptr, "GetPinCodeChangedEvent"},
  73. {1208, nullptr, "GetPinCode"},
  74. {1403, nullptr, "IsPairingActive"},
  75. {1406, nullptr, "GetSettingsLastUpdated"},
  76. {1411, nullptr, "GetPairingAccountInfo"},
  77. {1421, nullptr, "GetAccountNickname"},
  78. {1424, nullptr, "GetAccountState"},
  79. {1425, nullptr, "RequestPostEvents"},
  80. {1426, nullptr, "GetPostEventInterval"},
  81. {1427, nullptr, "SetPostEventInterval"},
  82. {1432, nullptr, "GetSynchronizationEvent"},
  83. {1451, nullptr, "StartPlayTimer"},
  84. {1452, nullptr, "StopPlayTimer"},
  85. {1453, nullptr, "IsPlayTimerEnabled"},
  86. {1454, nullptr, "GetPlayTimerRemainingTime"},
  87. {1455, nullptr, "IsRestrictedByPlayTimer"},
  88. {1456, nullptr, "GetPlayTimerSettings"},
  89. {1457, nullptr, "GetPlayTimerEventToRequestSuspension"},
  90. {1458, nullptr, "IsPlayTimerAlarmDisabled"},
  91. {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
  92. {1472, nullptr, "CancelNetworkRequest"},
  93. {1473, nullptr, "GetUnlinkedEvent"},
  94. {1474, nullptr, "ClearUnlinkedEvent"},
  95. {1601, nullptr, "DisableAllFeatures"},
  96. {1602, nullptr, "PostEnableAllFeatures"},
  97. {1603, nullptr, "IsAllFeaturesDisabled"},
  98. {1901, nullptr, "DeleteFromFreeCommunicationApplicationListForDebug"},
  99. {1902, nullptr, "ClearFreeCommunicationApplicationListForDebug"},
  100. {1903, nullptr, "GetExemptApplicationListCountForDebug"},
  101. {1904, nullptr, "GetExemptApplicationListForDebug"},
  102. {1905, nullptr, "UpdateExemptApplicationListForDebug"},
  103. {1906, nullptr, "AddToExemptApplicationListForDebug"},
  104. {1907, nullptr, "DeleteFromExemptApplicationListForDebug"},
  105. {1908, nullptr, "ClearExemptApplicationListForDebug"},
  106. {1941, nullptr, "DeletePairing"},
  107. {1951, nullptr, "SetPlayTimerSettingsForDebug"},
  108. {1952, nullptr, "GetPlayTimerSpentTimeForTest"},
  109. {1953, nullptr, "SetPlayTimerAlarmDisabledForDebug"},
  110. {2001, nullptr, "RequestPairingAsync"},
  111. {2002, nullptr, "FinishRequestPairing"},
  112. {2003, nullptr, "AuthorizePairingAsync"},
  113. {2004, nullptr, "FinishAuthorizePairing"},
  114. {2005, nullptr, "RetrievePairingInfoAsync"},
  115. {2006, nullptr, "FinishRetrievePairingInfo"},
  116. {2007, nullptr, "UnlinkPairingAsync"},
  117. {2008, nullptr, "FinishUnlinkPairing"},
  118. {2009, nullptr, "GetAccountMiiImageAsync"},
  119. {2010, nullptr, "FinishGetAccountMiiImage"},
  120. {2011, nullptr, "GetAccountMiiImageContentTypeAsync"},
  121. {2012, nullptr, "FinishGetAccountMiiImageContentType"},
  122. {2013, nullptr, "SynchronizeParentalControlSettingsAsync"},
  123. {2014, nullptr, "FinishSynchronizeParentalControlSettings"},
  124. {2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
  125. {2016, nullptr, "RequestUpdateExemptionListAsync"},
  126. };
  127. // clang-format on
  128. RegisterHandlers(functions);
  129. }
  130. private:
  131. bool CheckFreeCommunicationPermissionImpl() const {
  132. if (states.temporary_unlocked) {
  133. return true;
  134. }
  135. if ((states.application_info.parental_control_flag & 1) == 0) {
  136. return true;
  137. }
  138. if (pin_code[0] == '\0') {
  139. return true;
  140. }
  141. if (!settings.is_free_communication_default_on) {
  142. return true;
  143. }
  144. // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here
  145. // but as we don't have multiproceses support yet, we can just assume our application is
  146. // valid for the time being
  147. return true;
  148. }
  149. bool ConfirmStereoVisionPermissionImpl() const {
  150. if (states.temporary_unlocked) {
  151. return true;
  152. }
  153. if (pin_code[0] == '\0') {
  154. return true;
  155. }
  156. if (!settings.is_stero_vision_restricted) {
  157. return false;
  158. }
  159. return true;
  160. }
  161. void SetStereoVisionRestrictionImpl(bool is_restricted) {
  162. if (settings.disabled) {
  163. return;
  164. }
  165. if (pin_code[0] == '\0') {
  166. return;
  167. }
  168. settings.is_stero_vision_restricted = is_restricted;
  169. }
  170. void Initialize(Kernel::HLERequestContext& ctx) {
  171. LOG_DEBUG(Service_PCTL, "called");
  172. IPC::ResponseBuilder rb{ctx, 2};
  173. if (False(capability & (Capability::Application | Capability::System))) {
  174. LOG_ERROR(Service_PCTL, "Invalid capability! capability={:X}", capability);
  175. return;
  176. }
  177. // TODO(ogniK): Recovery flag initialization for pctl:r
  178. const auto tid = system.CurrentProcess()->GetTitleID();
  179. if (tid != 0) {
  180. const FileSys::PatchManager pm{tid, system.GetFileSystemController(),
  181. system.GetContentProvider()};
  182. const auto control = pm.GetControlMetadata();
  183. if (control.first) {
  184. states.tid_from_event = 0;
  185. states.launch_time_valid = false;
  186. states.is_suspended = false;
  187. states.free_communication = false;
  188. states.stereo_vision = false;
  189. states.application_info = ApplicationInfo{
  190. .tid = tid,
  191. .age_rating = control.first->GetRatingAge(),
  192. .parental_control_flag = control.first->GetParentalControlFlag(),
  193. .capability = capability,
  194. };
  195. if (False(capability & (Capability::System | Capability::Recovery))) {
  196. // TODO(ogniK): Signal application launch event
  197. }
  198. }
  199. }
  200. rb.Push(ResultSuccess);
  201. }
  202. void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) {
  203. LOG_DEBUG(Service_PCTL, "called");
  204. IPC::ResponseBuilder rb{ctx, 2};
  205. if (!CheckFreeCommunicationPermissionImpl()) {
  206. rb.Push(Error::ResultNoFreeCommunication);
  207. } else {
  208. rb.Push(ResultSuccess);
  209. }
  210. states.free_communication = true;
  211. }
  212. void ConfirmStereoVisionPermission(Kernel::HLERequestContext& ctx) {
  213. LOG_DEBUG(Service_PCTL, "called");
  214. states.stereo_vision = true;
  215. IPC::ResponseBuilder rb{ctx, 2};
  216. rb.Push(ResultSuccess);
  217. }
  218. void IsFreeCommunicationAvailable(Kernel::HLERequestContext& ctx) {
  219. LOG_WARNING(Service_PCTL, "(STUBBED) called");
  220. IPC::ResponseBuilder rb{ctx, 2};
  221. if (!CheckFreeCommunicationPermissionImpl()) {
  222. rb.Push(Error::ResultNoFreeCommunication);
  223. } else {
  224. rb.Push(ResultSuccess);
  225. }
  226. }
  227. void IsRestrictionEnabled(Kernel::HLERequestContext& ctx) {
  228. LOG_DEBUG(Service_PCTL, "called");
  229. IPC::ResponseBuilder rb{ctx, 3};
  230. if (False(capability & (Capability::Status | Capability::Recovery))) {
  231. LOG_ERROR(Service_PCTL, "Application does not have Status or Recovery capabilities!");
  232. rb.Push(Error::ResultNoCapability);
  233. rb.Push(false);
  234. return;
  235. }
  236. rb.Push(pin_code[0] != '\0');
  237. }
  238. void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) {
  239. LOG_DEBUG(Service_PCTL, "called");
  240. IPC::ResponseBuilder rb{ctx, 2};
  241. if (False(capability & Capability::StereoVision)) {
  242. LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
  243. rb.Push(Error::ResultNoCapability);
  244. return;
  245. }
  246. if (pin_code[0] == '\0') {
  247. rb.Push(Error::ResultNoRestrictionEnabled);
  248. return;
  249. }
  250. rb.Push(ResultSuccess);
  251. }
  252. void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) {
  253. LOG_DEBUG(Service_PCTL, "called");
  254. IPC::ResponseBuilder rb{ctx, 3};
  255. if (!ConfirmStereoVisionPermissionImpl()) {
  256. rb.Push(Error::ResultStereoVisionRestricted);
  257. rb.Push(false);
  258. } else {
  259. rb.Push(ResultSuccess);
  260. rb.Push(true);
  261. }
  262. }
  263. void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) {
  264. IPC::RequestParser rp{ctx};
  265. const auto can_use = rp.Pop<bool>();
  266. LOG_DEBUG(Service_PCTL, "called, can_use={}", can_use);
  267. IPC::ResponseBuilder rb{ctx, 2};
  268. if (False(capability & Capability::StereoVision)) {
  269. LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
  270. rb.Push(Error::ResultNoCapability);
  271. return;
  272. }
  273. SetStereoVisionRestrictionImpl(can_use);
  274. rb.Push(ResultSuccess);
  275. }
  276. void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) {
  277. LOG_DEBUG(Service_PCTL, "called");
  278. IPC::ResponseBuilder rb{ctx, 3};
  279. if (False(capability & Capability::StereoVision)) {
  280. LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
  281. rb.Push(Error::ResultNoCapability);
  282. rb.Push(false);
  283. return;
  284. }
  285. rb.Push(ResultSuccess);
  286. rb.Push(settings.is_stero_vision_restricted);
  287. }
  288. void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) {
  289. LOG_DEBUG(Service_PCTL, "called");
  290. states.stereo_vision = false;
  291. IPC::ResponseBuilder rb{ctx, 2};
  292. rb.Push(ResultSuccess);
  293. }
  294. struct ApplicationInfo {
  295. u64 tid{};
  296. std::array<u8, 32> age_rating{};
  297. u32 parental_control_flag{};
  298. Capability capability{};
  299. };
  300. struct States {
  301. u64 current_tid{};
  302. ApplicationInfo application_info{};
  303. u64 tid_from_event{};
  304. bool launch_time_valid{};
  305. bool is_suspended{};
  306. bool temporary_unlocked{};
  307. bool free_communication{};
  308. bool stereo_vision{};
  309. };
  310. struct ParentalControlSettings {
  311. bool is_stero_vision_restricted{};
  312. bool is_free_communication_default_on{};
  313. bool disabled{};
  314. };
  315. States states{};
  316. ParentalControlSettings settings{};
  317. std::array<char, 8> pin_code{};
  318. Capability capability{};
  319. };
  320. void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
  321. LOG_DEBUG(Service_PCTL, "called");
  322. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  323. rb.Push(ResultSuccess);
  324. // TODO(ogniK): Get TID from process
  325. rb.PushIpcInterface<IParentalControlService>(system, capability);
  326. }
  327. void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) {
  328. LOG_DEBUG(Service_PCTL, "called");
  329. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  330. rb.Push(ResultSuccess);
  331. rb.PushIpcInterface<IParentalControlService>(system, capability);
  332. }
  333. Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_,
  334. const char* name_, Capability capability_)
  335. : ServiceFramework{system_, name_}, module{std::move(module_)}, capability{capability_} {}
  336. Module::Interface::~Interface() = default;
  337. void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
  338. auto module = std::make_shared<Module>();
  339. std::make_shared<PCTL>(system, module, "pctl",
  340. Capability::Application | Capability::SnsPost | Capability::Status |
  341. Capability::StereoVision)
  342. ->InstallAsService(service_manager);
  343. // TODO(ogniK): Implement remaining capabilities
  344. std::make_shared<PCTL>(system, module, "pctl:a", Capability::None)
  345. ->InstallAsService(service_manager);
  346. std::make_shared<PCTL>(system, module, "pctl:r", Capability::None)
  347. ->InstallAsService(service_manager);
  348. std::make_shared<PCTL>(system, module, "pctl:s", Capability::None)
  349. ->InstallAsService(service_manager);
  350. }
  351. } // namespace Service::PCTL