diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/file_sys/control_metadata.cpp | 8 | ||||
| -rw-r--r-- | src/core/file_sys/control_metadata.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/pctl/module.cpp | 248 | ||||
| -rw-r--r-- | src/core/hle/service/pctl/module.h | 19 | ||||
| -rw-r--r-- | src/core/hle/service/pctl/pctl.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/pctl/pctl.h | 3 |
6 files changed, 254 insertions, 31 deletions
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index b0a130345..f66759815 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp | |||
| @@ -100,6 +100,14 @@ u64 NACP::GetDeviceSaveDataSize() const { | |||
| 100 | return raw.device_save_data_size; | 100 | return raw.device_save_data_size; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | u32 NACP::GetParentalControlFlag() const { | ||
| 104 | return raw.parental_control; | ||
| 105 | } | ||
| 106 | |||
| 107 | const std::array<u8, 0x20>& NACP::GetRatingAge() const { | ||
| 108 | return raw.rating_age; | ||
| 109 | } | ||
| 110 | |||
| 103 | std::vector<u8> NACP::GetRawBytes() const { | 111 | std::vector<u8> NACP::GetRawBytes() const { |
| 104 | std::vector<u8> out(sizeof(RawNACP)); | 112 | std::vector<u8> out(sizeof(RawNACP)); |
| 105 | std::memcpy(out.data(), &raw, sizeof(RawNACP)); | 113 | std::memcpy(out.data(), &raw, sizeof(RawNACP)); |
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 403c4219a..dd9837cf5 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h | |||
| @@ -114,6 +114,8 @@ public: | |||
| 114 | std::vector<u8> GetRawBytes() const; | 114 | std::vector<u8> GetRawBytes() const; |
| 115 | bool GetUserAccountSwitchLock() const; | 115 | bool GetUserAccountSwitchLock() const; |
| 116 | u64 GetDeviceSaveDataSize() const; | 116 | u64 GetDeviceSaveDataSize() const; |
| 117 | u32 GetParentalControlFlag() const; | ||
| 118 | const std::array<u8, 0x20>& GetRatingAge() const; | ||
| 117 | 119 | ||
| 118 | private: | 120 | private: |
| 119 | RawNACP raw{}; | 121 | RawNACP raw{}; |
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp index e6cd4b3c7..dc59702f1 100644 --- a/src/core/hle/service/pctl/module.cpp +++ b/src/core/hle/service/pctl/module.cpp | |||
| @@ -3,16 +3,30 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/core.h" | ||
| 7 | #include "core/file_sys/control_metadata.h" | ||
| 8 | #include "core/file_sys/patch_manager.h" | ||
| 6 | #include "core/hle/ipc_helpers.h" | 9 | #include "core/hle/ipc_helpers.h" |
| 10 | #include "core/hle/kernel/process.h" | ||
| 7 | #include "core/hle/service/pctl/module.h" | 11 | #include "core/hle/service/pctl/module.h" |
| 8 | #include "core/hle/service/pctl/pctl.h" | 12 | #include "core/hle/service/pctl/pctl.h" |
| 9 | 13 | ||
| 10 | namespace Service::PCTL { | 14 | namespace Service::PCTL { |
| 11 | 15 | ||
| 16 | namespace Error { | ||
| 17 | |||
| 18 | constexpr ResultCode ResultNoFreeCommunication{ErrorModule::PCTL, 101}; | ||
| 19 | constexpr ResultCode ResultStereoVisionRestricted{ErrorModule::PCTL, 104}; | ||
| 20 | constexpr ResultCode ResultNoCapability{ErrorModule::PCTL, 131}; | ||
| 21 | constexpr ResultCode ResultNoRestrictionEnabled{ErrorModule::PCTL, 181}; | ||
| 22 | |||
| 23 | } // namespace Error | ||
| 24 | |||
| 12 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { | 25 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { |
| 13 | public: | 26 | public: |
| 14 | explicit IParentalControlService(Core::System& system_) | 27 | explicit IParentalControlService(Core::System& system_, Capability capability) |
| 15 | : ServiceFramework{system_, "IParentalControlService"} { | 28 | : ServiceFramework{system_, "IParentalControlService"}, system(system_), |
| 29 | capability(capability) { | ||
| 16 | // clang-format off | 30 | // clang-format off |
| 17 | static const FunctionInfo functions[] = { | 31 | static const FunctionInfo functions[] = { |
| 18 | {1, &IParentalControlService::Initialize, "Initialize"}, | 32 | {1, &IParentalControlService::Initialize, "Initialize"}, |
| @@ -28,13 +42,13 @@ public: | |||
| 28 | {1010, nullptr, "IsRestrictedSystemSettingsEntered"}, | 42 | {1010, nullptr, "IsRestrictedSystemSettingsEntered"}, |
| 29 | {1011, nullptr, "RevertRestrictedSystemSettingsEntered"}, | 43 | {1011, nullptr, "RevertRestrictedSystemSettingsEntered"}, |
| 30 | {1012, nullptr, "GetRestrictedFeatures"}, | 44 | {1012, nullptr, "GetRestrictedFeatures"}, |
| 31 | {1013, nullptr, "ConfirmStereoVisionPermission"}, | 45 | {1013, &IParentalControlService::ConfirmStereoVisionPermission, "ConfirmStereoVisionPermission"}, |
| 32 | {1014, nullptr, "ConfirmPlayableApplicationVideoOld"}, | 46 | {1014, nullptr, "ConfirmPlayableApplicationVideoOld"}, |
| 33 | {1015, nullptr, "ConfirmPlayableApplicationVideo"}, | 47 | {1015, nullptr, "ConfirmPlayableApplicationVideo"}, |
| 34 | {1016, nullptr, "ConfirmShowNewsPermission"}, | 48 | {1016, nullptr, "ConfirmShowNewsPermission"}, |
| 35 | {1017, nullptr, "EndFreeCommunication"}, | 49 | {1017, nullptr, "EndFreeCommunication"}, |
| 36 | {1018, nullptr, "IsFreeCommunicationAvailable"}, | 50 | {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"}, |
| 37 | {1031, nullptr, "IsRestrictionEnabled"}, | 51 | {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"}, |
| 38 | {1032, nullptr, "GetSafetyLevel"}, | 52 | {1032, nullptr, "GetSafetyLevel"}, |
| 39 | {1033, nullptr, "SetSafetyLevel"}, | 53 | {1033, nullptr, "SetSafetyLevel"}, |
| 40 | {1034, nullptr, "GetSafetyLevelSettings"}, | 54 | {1034, nullptr, "GetSafetyLevelSettings"}, |
| @@ -122,62 +136,235 @@ public: | |||
| 122 | } | 136 | } |
| 123 | 137 | ||
| 124 | private: | 138 | private: |
| 139 | bool CheckFreeCommunicationPermissionImpl() const { | ||
| 140 | if (states.temporary_unlocked) { | ||
| 141 | return true; | ||
| 142 | } | ||
| 143 | if ((states.application_info.parental_control_flag & 1) == 0) { | ||
| 144 | return true; | ||
| 145 | } | ||
| 146 | if (pin_code[0] == '\0') { | ||
| 147 | return true; | ||
| 148 | } | ||
| 149 | if (!settings.is_free_communication_default_on) { | ||
| 150 | return true; | ||
| 151 | } | ||
| 152 | // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here | ||
| 153 | // but as we don't have multiproceses support yet, we can just assume our application is | ||
| 154 | // valid for the time being | ||
| 155 | return true; | ||
| 156 | } | ||
| 157 | |||
| 158 | bool ConfirmStereoVisionPermissionImpl() const { | ||
| 159 | if (states.temporary_unlocked) { | ||
| 160 | return true; | ||
| 161 | } | ||
| 162 | if (pin_code[0] == '\0') { | ||
| 163 | return true; | ||
| 164 | } | ||
| 165 | if (!settings.is_stero_vision_restricted) { | ||
| 166 | return false; | ||
| 167 | } | ||
| 168 | return true; | ||
| 169 | } | ||
| 170 | |||
| 171 | void SetStereoVisionRestrictionImpl(bool is_restricted) { | ||
| 172 | if (settings.disabled) { | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | if (pin_code[0] == '\0') { | ||
| 177 | return; | ||
| 178 | } | ||
| 179 | settings.is_stero_vision_restricted = is_restricted; | ||
| 180 | } | ||
| 181 | |||
| 125 | void Initialize(Kernel::HLERequestContext& ctx) { | 182 | void Initialize(Kernel::HLERequestContext& ctx) { |
| 126 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 183 | LOG_DEBUG(Service_PCTL, "called"); |
| 184 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 185 | |||
| 186 | if (False(capability & (Capability::Application | Capability::System))) { | ||
| 187 | LOG_ERROR(Service_PCTL, "Invalid capability! capability={:X}", capability); | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | |||
| 191 | // TODO(ogniK): Recovery flag initialization for pctl:r | ||
| 192 | |||
| 193 | const auto tid = system.CurrentProcess()->GetTitleID(); | ||
| 194 | if (tid != 0) { | ||
| 195 | const FileSys::PatchManager pm{tid, system.GetFileSystemController(), | ||
| 196 | system.GetContentProvider()}; | ||
| 197 | const auto control = pm.GetControlMetadata(); | ||
| 198 | if (control.first) { | ||
| 199 | states.tid_from_event = 0; | ||
| 200 | states.launch_time_valid = false; | ||
| 201 | states.is_suspended = false; | ||
| 202 | states.free_communication = false; | ||
| 203 | states.stereo_vision = false; | ||
| 204 | states.application_info = ApplicationInfo{ | ||
| 205 | .tid = tid, | ||
| 206 | .age_rating = control.first->GetRatingAge(), | ||
| 207 | .parental_control_flag = control.first->GetParentalControlFlag(), | ||
| 208 | .capability = capability, | ||
| 209 | }; | ||
| 210 | |||
| 211 | if (False(capability & (Capability::System | Capability::Recovery))) { | ||
| 212 | // TODO(ogniK): Signal application launch event | ||
| 213 | } | ||
| 214 | } | ||
| 215 | } | ||
| 127 | 216 | ||
| 128 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; | ||
| 129 | rb.Push(RESULT_SUCCESS); | 217 | rb.Push(RESULT_SUCCESS); |
| 130 | } | 218 | } |
| 131 | 219 | ||
| 132 | void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) { | 220 | void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) { |
| 133 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 221 | LOG_DEBUG(Service_PCTL, "called"); |
| 222 | |||
| 223 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 224 | if (!CheckFreeCommunicationPermissionImpl()) { | ||
| 225 | rb.Push(Error::ResultNoFreeCommunication); | ||
| 226 | } else { | ||
| 227 | rb.Push(RESULT_SUCCESS); | ||
| 228 | } | ||
| 229 | |||
| 230 | states.free_communication = true; | ||
| 231 | } | ||
| 232 | |||
| 233 | void ConfirmStereoVisionPermission(Kernel::HLERequestContext& ctx) { | ||
| 234 | LOG_DEBUG(Service_PCTL, "called"); | ||
| 235 | states.stereo_vision = true; | ||
| 134 | 236 | ||
| 135 | IPC::ResponseBuilder rb{ctx, 2}; | 237 | IPC::ResponseBuilder rb{ctx, 2}; |
| 136 | rb.Push(RESULT_SUCCESS); | 238 | rb.Push(RESULT_SUCCESS); |
| 137 | } | 239 | } |
| 138 | 240 | ||
| 139 | void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) { | 241 | void IsFreeCommunicationAvailable(Kernel::HLERequestContext& ctx) { |
| 140 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 242 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); |
| 141 | 243 | ||
| 142 | IPC::ResponseBuilder rb{ctx, 2}; | 244 | IPC::ResponseBuilder rb{ctx, 2}; |
| 245 | if (!CheckFreeCommunicationPermissionImpl()) { | ||
| 246 | rb.Push(Error::ResultNoFreeCommunication); | ||
| 247 | } else { | ||
| 248 | rb.Push(RESULT_SUCCESS); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | void IsRestrictionEnabled(Kernel::HLERequestContext& ctx) { | ||
| 253 | LOG_DEBUG(Service_PCTL, "called"); | ||
| 254 | |||
| 255 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 256 | if (False(capability & (Capability::Status | Capability::Recovery))) { | ||
| 257 | LOG_ERROR(Service_PCTL, "Application does not have Status or Recovery capabilities!"); | ||
| 258 | rb.Push(Error::ResultNoCapability); | ||
| 259 | rb.Push(false); | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | |||
| 263 | rb.Push(pin_code[0] != '\0'); | ||
| 264 | } | ||
| 265 | |||
| 266 | void ConfirmStereoVisionRestrictionConfigurable(Kernel::HLERequestContext& ctx) { | ||
| 267 | LOG_DEBUG(Service_PCTL, "called"); | ||
| 268 | |||
| 269 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 270 | |||
| 271 | if (False(capability & Capability::StereoVision)) { | ||
| 272 | LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!"); | ||
| 273 | rb.Push(Error::ResultNoCapability); | ||
| 274 | return; | ||
| 275 | } | ||
| 276 | |||
| 277 | if (pin_code[0] == '\0') { | ||
| 278 | rb.Push(Error::ResultNoRestrictionEnabled); | ||
| 279 | return; | ||
| 280 | } | ||
| 281 | |||
| 143 | rb.Push(RESULT_SUCCESS); | 282 | rb.Push(RESULT_SUCCESS); |
| 144 | } | 283 | } |
| 145 | 284 | ||
| 146 | void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) { | 285 | void IsStereoVisionPermitted(Kernel::HLERequestContext& ctx) { |
| 147 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 286 | LOG_DEBUG(Service_PCTL, "called"); |
| 148 | 287 | ||
| 149 | IPC::ResponseBuilder rb{ctx, 3}; | 288 | IPC::ResponseBuilder rb{ctx, 3}; |
| 150 | rb.Push(RESULT_SUCCESS); | 289 | if (!ConfirmStereoVisionPermissionImpl()) { |
| 151 | rb.Push(true); | 290 | rb.Push(Error::ResultStereoVisionRestricted); |
| 291 | rb.Push(false); | ||
| 292 | } else { | ||
| 293 | rb.Push(RESULT_SUCCESS); | ||
| 294 | rb.Push(true); | ||
| 295 | } | ||
| 152 | } | 296 | } |
| 153 | 297 | ||
| 154 | void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { | 298 | void SetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { |
| 155 | IPC::RequestParser rp{ctx}; | 299 | IPC::RequestParser rp{ctx}; |
| 156 | const auto can_use = rp.Pop<bool>(); | 300 | const auto can_use = rp.Pop<bool>(); |
| 157 | LOG_WARNING(Service_PCTL, "(STUBBED) called, can_use={}", can_use); | 301 | LOG_DEBUG(Service_PCTL, "called, can_use={}", can_use); |
| 158 | |||
| 159 | can_use_stereo_vision = can_use; | ||
| 160 | 302 | ||
| 161 | IPC::ResponseBuilder rb{ctx, 2}; | 303 | IPC::ResponseBuilder rb{ctx, 2}; |
| 304 | if (False(capability & Capability::StereoVision)) { | ||
| 305 | LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!"); | ||
| 306 | rb.Push(Error::ResultNoCapability); | ||
| 307 | return; | ||
| 308 | } | ||
| 309 | |||
| 310 | SetStereoVisionRestrictionImpl(can_use); | ||
| 162 | rb.Push(RESULT_SUCCESS); | 311 | rb.Push(RESULT_SUCCESS); |
| 163 | } | 312 | } |
| 164 | 313 | ||
| 165 | void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { | 314 | void GetStereoVisionRestriction(Kernel::HLERequestContext& ctx) { |
| 166 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 315 | LOG_DEBUG(Service_PCTL, "called"); |
| 167 | 316 | ||
| 168 | IPC::ResponseBuilder rb{ctx, 3}; | 317 | IPC::ResponseBuilder rb{ctx, 3}; |
| 318 | if (False(capability & Capability::StereoVision)) { | ||
| 319 | LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!"); | ||
| 320 | rb.Push(Error::ResultNoCapability); | ||
| 321 | rb.Push(false); | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | |||
| 169 | rb.Push(RESULT_SUCCESS); | 325 | rb.Push(RESULT_SUCCESS); |
| 170 | rb.Push(can_use_stereo_vision); | 326 | rb.Push(settings.is_stero_vision_restricted); |
| 171 | } | 327 | } |
| 172 | 328 | ||
| 173 | void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) { | 329 | void ResetConfirmedStereoVisionPermission(Kernel::HLERequestContext& ctx) { |
| 174 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | 330 | LOG_DEBUG(Service_PCTL, "called"); |
| 331 | |||
| 332 | states.stereo_vision = false; | ||
| 175 | 333 | ||
| 176 | IPC::ResponseBuilder rb{ctx, 2}; | 334 | IPC::ResponseBuilder rb{ctx, 2}; |
| 177 | rb.Push(RESULT_SUCCESS); | 335 | rb.Push(RESULT_SUCCESS); |
| 178 | } | 336 | } |
| 179 | 337 | ||
| 338 | struct ApplicationInfo { | ||
| 339 | u64 tid{}; | ||
| 340 | std::array<u8, 32> age_rating{}; | ||
| 341 | u32 parental_control_flag{}; | ||
| 342 | Capability capability{}; | ||
| 343 | }; | ||
| 344 | |||
| 345 | struct States { | ||
| 346 | u64 current_tid{}; | ||
| 347 | ApplicationInfo application_info{}; | ||
| 348 | u64 tid_from_event{}; | ||
| 349 | bool launch_time_valid{}; | ||
| 350 | bool is_suspended{}; | ||
| 351 | bool temporary_unlocked{}; | ||
| 352 | bool free_communication{}; | ||
| 353 | bool stereo_vision{}; | ||
| 354 | }; | ||
| 355 | |||
| 356 | struct ParentalControlSettings { | ||
| 357 | bool is_stero_vision_restricted{}; | ||
| 358 | bool is_free_communication_default_on{}; | ||
| 359 | bool disabled{}; | ||
| 360 | }; | ||
| 361 | |||
| 362 | States states{}; | ||
| 363 | ParentalControlSettings settings{}; | ||
| 364 | std::array<char, 8> pin_code{}; | ||
| 180 | bool can_use_stereo_vision = true; | 365 | bool can_use_stereo_vision = true; |
| 366 | Core::System& system; | ||
| 367 | Capability capability{}; | ||
| 181 | }; | 368 | }; |
| 182 | 369 | ||
| 183 | void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { | 370 | void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { |
| @@ -185,7 +372,9 @@ void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { | |||
| 185 | 372 | ||
| 186 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 373 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 187 | rb.Push(RESULT_SUCCESS); | 374 | rb.Push(RESULT_SUCCESS); |
| 188 | rb.PushIpcInterface<IParentalControlService>(system); | 375 | // TODO(ogniK): Get TID from process |
| 376 | |||
| 377 | rb.PushIpcInterface<IParentalControlService>(system, capability); | ||
| 189 | } | 378 | } |
| 190 | 379 | ||
| 191 | void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) { | 380 | void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) { |
| @@ -193,21 +382,28 @@ void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext | |||
| 193 | 382 | ||
| 194 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 383 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 195 | rb.Push(RESULT_SUCCESS); | 384 | rb.Push(RESULT_SUCCESS); |
| 196 | rb.PushIpcInterface<IParentalControlService>(system); | 385 | rb.PushIpcInterface<IParentalControlService>(system, capability); |
| 197 | } | 386 | } |
| 198 | 387 | ||
| 199 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, | 388 | Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, |
| 200 | const char* name) | 389 | const char* name, Capability capability) |
| 201 | : ServiceFramework{system_, name}, module{std::move(module_)} {} | 390 | : ServiceFramework{system_, name}, module{std::move(module_)}, capability(capability) {} |
| 202 | 391 | ||
| 203 | Module::Interface::~Interface() = default; | 392 | Module::Interface::~Interface() = default; |
| 204 | 393 | ||
| 205 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { | 394 | void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { |
| 206 | auto module = std::make_shared<Module>(); | 395 | auto module = std::make_shared<Module>(); |
| 207 | std::make_shared<PCTL>(system, module, "pctl")->InstallAsService(service_manager); | 396 | std::make_shared<PCTL>(system, module, "pctl", |
| 208 | std::make_shared<PCTL>(system, module, "pctl:a")->InstallAsService(service_manager); | 397 | Capability::Application | Capability::SnsPost | Capability::Status | |
| 209 | std::make_shared<PCTL>(system, module, "pctl:r")->InstallAsService(service_manager); | 398 | Capability::StereoVision) |
| 210 | std::make_shared<PCTL>(system, module, "pctl:s")->InstallAsService(service_manager); | 399 | ->InstallAsService(service_manager); |
| 400 | // TODO(ogniK): Implement remaining capabilities | ||
| 401 | std::make_shared<PCTL>(system, module, "pctl:a", Capability::None) | ||
| 402 | ->InstallAsService(service_manager); | ||
| 403 | std::make_shared<PCTL>(system, module, "pctl:r", Capability::None) | ||
| 404 | ->InstallAsService(service_manager); | ||
| 405 | std::make_shared<PCTL>(system, module, "pctl:s", Capability::None) | ||
| 406 | ->InstallAsService(service_manager); | ||
| 211 | } | 407 | } |
| 212 | 408 | ||
| 213 | } // namespace Service::PCTL | 409 | } // namespace Service::PCTL |
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h index 4c7e09a3b..032481b00 100644 --- a/src/core/hle/service/pctl/module.h +++ b/src/core/hle/service/pctl/module.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_funcs.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Core { | 10 | namespace Core { |
| @@ -12,12 +13,23 @@ class System; | |||
| 12 | 13 | ||
| 13 | namespace Service::PCTL { | 14 | namespace Service::PCTL { |
| 14 | 15 | ||
| 16 | enum class Capability : u32 { | ||
| 17 | None = 0, | ||
| 18 | Application = 1 << 0, | ||
| 19 | SnsPost = 1 << 1, | ||
| 20 | Recovery = 1 << 6, | ||
| 21 | Status = 1 << 8, | ||
| 22 | StereoVision = 1 << 9, | ||
| 23 | System = 1 << 15, | ||
| 24 | }; | ||
| 25 | DECLARE_ENUM_FLAG_OPERATORS(Capability); | ||
| 26 | |||
| 15 | class Module final { | 27 | class Module final { |
| 16 | public: | 28 | public: |
| 17 | class Interface : public ServiceFramework<Interface> { | 29 | class Interface : public ServiceFramework<Interface> { |
| 18 | public: | 30 | public: |
| 19 | explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, | 31 | explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 20 | const char* name); | 32 | Capability capability); |
| 21 | ~Interface() override; | 33 | ~Interface() override; |
| 22 | 34 | ||
| 23 | void CreateService(Kernel::HLERequestContext& ctx); | 35 | void CreateService(Kernel::HLERequestContext& ctx); |
| @@ -25,6 +37,9 @@ public: | |||
| 25 | 37 | ||
| 26 | protected: | 38 | protected: |
| 27 | std::shared_ptr<Module> module; | 39 | std::shared_ptr<Module> module; |
| 40 | |||
| 41 | private: | ||
| 42 | Capability capability{}; | ||
| 28 | }; | 43 | }; |
| 29 | }; | 44 | }; |
| 30 | 45 | ||
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp index 16dd34f90..e4d155c86 100644 --- a/src/core/hle/service/pctl/pctl.cpp +++ b/src/core/hle/service/pctl/pctl.cpp | |||
| @@ -6,8 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::PCTL { | 7 | namespace Service::PCTL { |
| 8 | 8 | ||
| 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name) | 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 10 | : Interface{system_, std::move(module_), name} { | 10 | Capability capability) |
| 11 | : Interface{system_, std::move(module_), name, capability} { | ||
| 11 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 12 | {0, &PCTL::CreateService, "CreateService"}, | 13 | {0, &PCTL::CreateService, "CreateService"}, |
| 13 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, | 14 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, |
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h index 275d23007..fd0a1e486 100644 --- a/src/core/hle/service/pctl/pctl.h +++ b/src/core/hle/service/pctl/pctl.h | |||
| @@ -14,7 +14,8 @@ namespace Service::PCTL { | |||
| 14 | 14 | ||
| 15 | class PCTL final : public Module::Interface { | 15 | class PCTL final : public Module::Interface { |
| 16 | public: | 16 | public: |
| 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name); | 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 18 | Capability capability); | ||
| 18 | ~PCTL() override; | 19 | ~PCTL() override; |
| 19 | }; | 20 | }; |
| 20 | 21 | ||