2018-11-22 03:20:02 +01:00
|
|
|
// Copyright 2018 yuzu emulator team
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2019-06-12 23:27:06 +02:00
|
|
|
#include <string_view>
|
2018-11-22 21:58:00 +01:00
|
|
|
|
2019-04-05 00:09:42 +02:00
|
|
|
#include "common/assert.h"
|
2018-11-22 03:20:02 +01:00
|
|
|
#include "common/hex_util.h"
|
2018-11-22 21:58:00 +01:00
|
|
|
#include "common/logging/log.h"
|
2019-03-12 00:38:53 +01:00
|
|
|
#include "core/core.h"
|
|
|
|
#include "core/frontend/applets/general_frontend.h"
|
|
|
|
#include "core/hle/kernel/process.h"
|
2018-11-22 21:58:00 +01:00
|
|
|
#include "core/hle/result.h"
|
|
|
|
#include "core/hle/service/am/am.h"
|
2019-03-12 00:38:53 +01:00
|
|
|
#include "core/hle/service/am/applets/general_backend.h"
|
2019-05-18 03:47:07 +02:00
|
|
|
#include "core/reporter.h"
|
2018-11-22 03:20:02 +01:00
|
|
|
|
|
|
|
namespace Service::AM::Applets {
|
|
|
|
|
2019-06-05 18:10:23 +02:00
|
|
|
constexpr ResultCode ERROR_INVALID_PIN{ErrorModule::PCTL, 221};
|
|
|
|
|
2019-06-12 23:27:06 +02:00
|
|
|
static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) {
|
2020-02-02 06:38:22 +01:00
|
|
|
std::shared_ptr<IStorage> storage = broker.PopNormalDataToApplet();
|
2018-11-22 03:20:02 +01:00
|
|
|
for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) {
|
|
|
|
const auto data = storage->GetData();
|
|
|
|
LOG_INFO(Service_AM,
|
2019-06-12 23:27:06 +02:00
|
|
|
"called (STUBBED), during {} received normal data with size={:08X}, data={}",
|
|
|
|
prefix, data.size(), Common::HexToString(data));
|
2018-11-22 03:20:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
storage = broker.PopInteractiveDataToApplet();
|
|
|
|
for (; storage != nullptr; storage = broker.PopInteractiveDataToApplet()) {
|
|
|
|
const auto data = storage->GetData();
|
|
|
|
LOG_INFO(Service_AM,
|
2019-06-12 23:27:06 +02:00
|
|
|
"called (STUBBED), during {} received interactive data with size={:08X}, data={}",
|
|
|
|
prefix, data.size(), Common::HexToString(data));
|
2018-11-22 03:20:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-11 06:53:55 +02:00
|
|
|
Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_)
|
|
|
|
: Applet{system_.Kernel()}, frontend(frontend_) {}
|
2019-06-05 18:10:23 +02:00
|
|
|
|
|
|
|
Auth::~Auth() = default;
|
|
|
|
|
|
|
|
void Auth::Initialize() {
|
|
|
|
Applet::Initialize();
|
|
|
|
complete = false;
|
|
|
|
|
|
|
|
const auto storage = broker.PopNormalDataToApplet();
|
|
|
|
ASSERT(storage != nullptr);
|
|
|
|
const auto data = storage->GetData();
|
|
|
|
ASSERT(data.size() >= 0xC);
|
|
|
|
|
|
|
|
struct Arg {
|
|
|
|
INSERT_PADDING_BYTES(4);
|
|
|
|
AuthAppletType type;
|
|
|
|
u8 arg0;
|
|
|
|
u8 arg1;
|
|
|
|
u8 arg2;
|
|
|
|
INSERT_PADDING_BYTES(1);
|
|
|
|
};
|
|
|
|
static_assert(sizeof(Arg) == 0xC, "Arg (AuthApplet) has incorrect size.");
|
|
|
|
|
|
|
|
Arg arg{};
|
|
|
|
std::memcpy(&arg, data.data(), sizeof(Arg));
|
|
|
|
|
|
|
|
type = arg.type;
|
|
|
|
arg0 = arg.arg0;
|
|
|
|
arg1 = arg.arg1;
|
|
|
|
arg2 = arg.arg2;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Auth::TransactionComplete() const {
|
|
|
|
return complete;
|
|
|
|
}
|
|
|
|
|
|
|
|
ResultCode Auth::GetStatus() const {
|
|
|
|
return successful ? RESULT_SUCCESS : ERROR_INVALID_PIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Auth::ExecuteInteractive() {
|
|
|
|
UNREACHABLE_MSG("Unexpected interactive applet data.");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Auth::Execute() {
|
|
|
|
if (complete) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto unimplemented_log = [this] {
|
|
|
|
UNIMPLEMENTED_MSG("Unimplemented Auth applet type for type={:08X}, arg0={:02X}, "
|
|
|
|
"arg1={:02X}, arg2={:02X}",
|
|
|
|
static_cast<u32>(type), arg0, arg1, arg2);
|
|
|
|
};
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case AuthAppletType::ShowParentalAuthentication: {
|
|
|
|
const auto callback = [this](bool successful) { AuthFinished(successful); };
|
|
|
|
|
|
|
|
if (arg0 == 1 && arg1 == 0 && arg2 == 1) {
|
|
|
|
// ShowAuthenticatorForConfiguration
|
|
|
|
frontend.VerifyPINForSettings(callback);
|
|
|
|
} else if (arg1 == 0 && arg2 == 0) {
|
|
|
|
// ShowParentalAuthentication(bool)
|
|
|
|
frontend.VerifyPIN(callback, static_cast<bool>(arg0));
|
|
|
|
} else {
|
|
|
|
unimplemented_log();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case AuthAppletType::RegisterParentalPasscode: {
|
|
|
|
const auto callback = [this] { AuthFinished(true); };
|
|
|
|
|
|
|
|
if (arg0 == 0 && arg1 == 0 && arg2 == 0) {
|
|
|
|
// RegisterParentalPasscode
|
|
|
|
frontend.RegisterPIN(callback);
|
|
|
|
} else {
|
|
|
|
unimplemented_log();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case AuthAppletType::ChangeParentalPasscode: {
|
|
|
|
const auto callback = [this] { AuthFinished(true); };
|
|
|
|
|
|
|
|
if (arg0 == 0 && arg1 == 0 && arg2 == 0) {
|
|
|
|
// ChangeParentalPasscode
|
|
|
|
frontend.ChangePIN(callback);
|
|
|
|
} else {
|
|
|
|
unimplemented_log();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
unimplemented_log();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Auth::AuthFinished(bool successful) {
|
|
|
|
this->successful = successful;
|
|
|
|
|
|
|
|
struct Return {
|
|
|
|
ResultCode result_code;
|
|
|
|
};
|
|
|
|
static_assert(sizeof(Return) == 0x4, "Return (AuthApplet) has incorrect size.");
|
|
|
|
|
|
|
|
Return return_{GetStatus()};
|
|
|
|
|
|
|
|
std::vector<u8> out(sizeof(Return));
|
|
|
|
std::memcpy(out.data(), &return_, sizeof(Return));
|
|
|
|
|
2020-02-02 06:38:22 +01:00
|
|
|
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(out)));
|
2019-06-05 18:10:23 +02:00
|
|
|
broker.SignalStateChanged();
|
|
|
|
}
|
|
|
|
|
2019-07-11 06:53:55 +02:00
|
|
|
PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_)
|
|
|
|
: Applet{system_.Kernel()}, frontend(frontend_), system{system_} {}
|
2019-03-12 00:38:53 +01:00
|
|
|
|
|
|
|
PhotoViewer::~PhotoViewer() = default;
|
|
|
|
|
|
|
|
void PhotoViewer::Initialize() {
|
|
|
|
Applet::Initialize();
|
|
|
|
complete = false;
|
|
|
|
|
|
|
|
const auto storage = broker.PopNormalDataToApplet();
|
|
|
|
ASSERT(storage != nullptr);
|
|
|
|
const auto data = storage->GetData();
|
|
|
|
ASSERT(!data.empty());
|
|
|
|
mode = static_cast<PhotoViewerAppletMode>(data[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PhotoViewer::TransactionComplete() const {
|
|
|
|
return complete;
|
|
|
|
}
|
|
|
|
|
|
|
|
ResultCode PhotoViewer::GetStatus() const {
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhotoViewer::ExecuteInteractive() {
|
|
|
|
UNREACHABLE_MSG("Unexpected interactive applet data.");
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhotoViewer::Execute() {
|
|
|
|
if (complete)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto callback = [this] { ViewFinished(); };
|
|
|
|
switch (mode) {
|
|
|
|
case PhotoViewerAppletMode::CurrentApp:
|
2019-07-11 06:53:55 +02:00
|
|
|
frontend.ShowPhotosForApplication(system.CurrentProcess()->GetTitleID(), callback);
|
2019-03-12 00:38:53 +01:00
|
|
|
break;
|
|
|
|
case PhotoViewerAppletMode::AllApps:
|
|
|
|
frontend.ShowAllPhotos(callback);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", static_cast<u8>(mode));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PhotoViewer::ViewFinished() {
|
2020-02-02 06:38:22 +01:00
|
|
|
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{}));
|
2019-03-12 00:38:53 +01:00
|
|
|
broker.SignalStateChanged();
|
|
|
|
}
|
|
|
|
|
2019-07-11 06:53:55 +02:00
|
|
|
StubApplet::StubApplet(Core::System& system_, AppletId id_)
|
|
|
|
: Applet{system_.Kernel()}, id(id_), system{system_} {}
|
2018-11-22 03:20:02 +01:00
|
|
|
|
|
|
|
StubApplet::~StubApplet() = default;
|
|
|
|
|
|
|
|
void StubApplet::Initialize() {
|
|
|
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
|
|
|
Applet::Initialize();
|
2019-05-18 03:47:07 +02:00
|
|
|
|
|
|
|
const auto data = broker.PeekDataToAppletForDebug();
|
2019-07-11 06:53:55 +02:00
|
|
|
system.GetReporter().SaveUnimplementedAppletReport(
|
2019-05-18 03:47:07 +02:00
|
|
|
static_cast<u32>(id), common_args.arguments_version, common_args.library_version,
|
|
|
|
common_args.theme_color, common_args.play_startup_sound, common_args.system_tick,
|
|
|
|
data.normal, data.interactive);
|
|
|
|
|
2018-11-22 03:20:02 +01:00
|
|
|
LogCurrentStorage(broker, "Initialize");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StubApplet::TransactionComplete() const {
|
|
|
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ResultCode StubApplet::GetStatus() const {
|
|
|
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StubApplet::ExecuteInteractive() {
|
|
|
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
|
|
|
LogCurrentStorage(broker, "ExecuteInteractive");
|
|
|
|
|
2020-02-02 06:38:22 +01:00
|
|
|
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000)));
|
|
|
|
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000)));
|
2018-11-22 03:20:02 +01:00
|
|
|
broker.SignalStateChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StubApplet::Execute() {
|
|
|
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
|
|
|
LogCurrentStorage(broker, "Execute");
|
|
|
|
|
2020-02-02 06:38:22 +01:00
|
|
|
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000)));
|
|
|
|
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000)));
|
2018-11-22 03:20:02 +01:00
|
|
|
broker.SignalStateChanged();
|
|
|
|
}
|
2019-03-12 00:38:53 +01:00
|
|
|
|
2018-11-22 03:20:02 +01:00
|
|
|
} // namespace Service::AM::Applets
|