2018-11-10 02:09:37 +01:00
|
|
|
// Copyright 2018 yuzu emulator team
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2018-11-17 18:19:06 +01:00
|
|
|
#include <cstring>
|
|
|
|
#include "common/assert.h"
|
2018-11-19 20:24:36 +01:00
|
|
|
#include "core/core.h"
|
2019-03-12 00:32:59 +01:00
|
|
|
#include "core/frontend/applets/error.h"
|
|
|
|
#include "core/frontend/applets/general_frontend.h"
|
|
|
|
#include "core/frontend/applets/profile_select.h"
|
|
|
|
#include "core/frontend/applets/software_keyboard.h"
|
|
|
|
#include "core/frontend/applets/web_browser.h"
|
2018-11-27 00:34:07 +01:00
|
|
|
#include "core/hle/kernel/readable_event.h"
|
2019-01-01 00:09:41 +01:00
|
|
|
#include "core/hle/kernel/server_session.h"
|
2018-11-27 00:34:07 +01:00
|
|
|
#include "core/hle/kernel/writable_event.h"
|
2018-11-17 18:19:06 +01:00
|
|
|
#include "core/hle/service/am/am.h"
|
2018-11-10 02:09:37 +01:00
|
|
|
#include "core/hle/service/am/applets/applets.h"
|
2019-03-12 00:32:59 +01:00
|
|
|
#include "core/hle/service/am/applets/error.h"
|
|
|
|
#include "core/hle/service/am/applets/general_backend.h"
|
|
|
|
#include "core/hle/service/am/applets/profile_select.h"
|
|
|
|
#include "core/hle/service/am/applets/software_keyboard.h"
|
|
|
|
#include "core/hle/service/am/applets/web_browser.h"
|
2018-11-10 02:09:37 +01:00
|
|
|
|
|
|
|
namespace Service::AM::Applets {
|
|
|
|
|
2019-07-11 06:53:55 +02:00
|
|
|
AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
|
2019-11-03 10:10:12 +01:00
|
|
|
state_changed_event =
|
|
|
|
Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent");
|
|
|
|
pop_out_data_event =
|
|
|
|
Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
|
2018-11-27 15:18:29 +01:00
|
|
|
pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
|
2019-11-03 10:10:12 +01:00
|
|
|
kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
AppletDataBroker::~AppletDataBroker() = default;
|
|
|
|
|
2019-05-18 03:47:07 +02:00
|
|
|
AppletDataBroker::RawChannelData AppletDataBroker::PeekDataToAppletForDebug() const {
|
|
|
|
std::vector<std::vector<u8>> out_normal;
|
|
|
|
|
|
|
|
for (const auto& storage : in_channel) {
|
|
|
|
out_normal.push_back(storage->GetData());
|
|
|
|
}
|
|
|
|
|
2019-05-26 17:40:41 +02:00
|
|
|
std::vector<std::vector<u8>> out_interactive;
|
|
|
|
|
2019-05-18 03:47:07 +02:00
|
|
|
for (const auto& storage : in_interactive_channel) {
|
|
|
|
out_interactive.push_back(storage->GetData());
|
|
|
|
}
|
|
|
|
|
2019-05-26 17:40:41 +02:00
|
|
|
return {std::move(out_normal), std::move(out_interactive)};
|
2019-05-18 03:47:07 +02:00
|
|
|
}
|
|
|
|
|
2018-11-19 20:24:36 +01:00
|
|
|
std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
|
|
|
|
if (out_channel.empty())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
auto out = std::move(out_channel.front());
|
2019-05-18 03:47:07 +02:00
|
|
|
out_channel.pop_front();
|
2020-01-30 04:23:09 +01:00
|
|
|
pop_out_data_event.writable->Clear();
|
2018-11-19 20:24:36 +01:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() {
|
|
|
|
if (in_channel.empty())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
auto out = std::move(in_channel.front());
|
2019-05-18 03:47:07 +02:00
|
|
|
in_channel.pop_front();
|
2018-11-19 20:24:36 +01:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
|
|
|
|
if (out_interactive_channel.empty())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
auto out = std::move(out_interactive_channel.front());
|
2019-05-18 03:47:07 +02:00
|
|
|
out_interactive_channel.pop_front();
|
2020-01-30 04:23:09 +01:00
|
|
|
pop_interactive_out_data_event.writable->Clear();
|
2018-11-19 20:24:36 +01:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() {
|
|
|
|
if (in_interactive_channel.empty())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
auto out = std::move(in_interactive_channel.front());
|
2019-05-18 03:47:07 +02:00
|
|
|
in_interactive_channel.pop_front();
|
2018-11-19 20:24:36 +01:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppletDataBroker::PushNormalDataFromGame(IStorage storage) {
|
2019-05-18 03:47:07 +02:00
|
|
|
in_channel.push_back(std::make_unique<IStorage>(storage));
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) {
|
2019-05-18 03:47:07 +02:00
|
|
|
out_channel.push_back(std::make_unique<IStorage>(storage));
|
2018-11-27 15:18:29 +01:00
|
|
|
pop_out_data_event.writable->Signal();
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) {
|
2019-05-18 03:47:07 +02:00
|
|
|
in_interactive_channel.push_back(std::make_unique<IStorage>(storage));
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) {
|
2019-05-18 03:47:07 +02:00
|
|
|
out_interactive_channel.push_back(std::make_unique<IStorage>(storage));
|
2018-11-27 15:18:29 +01:00
|
|
|
pop_interactive_out_data_event.writable->Signal();
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletDataBroker::SignalStateChanged() const {
|
2018-11-27 15:18:29 +01:00
|
|
|
state_changed_event.writable->Signal();
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
2019-11-25 02:15:51 +01:00
|
|
|
std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
|
2018-11-27 15:18:29 +01:00
|
|
|
return pop_out_data_event.readable;
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
2019-11-25 02:15:51 +01:00
|
|
|
std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
|
2018-11-27 15:18:29 +01:00
|
|
|
return pop_interactive_out_data_event.readable;
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
2019-11-25 02:15:51 +01:00
|
|
|
std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
|
2018-11-27 15:18:29 +01:00
|
|
|
return state_changed_event.readable;
|
2018-11-19 20:24:36 +01:00
|
|
|
}
|
|
|
|
|
2019-07-11 06:53:55 +02:00
|
|
|
Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {}
|
2018-11-11 22:39:25 +01:00
|
|
|
|
|
|
|
Applet::~Applet() = default;
|
2018-11-10 02:09:37 +01:00
|
|
|
|
2018-11-20 18:02:16 +01:00
|
|
|
void Applet::Initialize() {
|
|
|
|
const auto common = broker.PopNormalDataToApplet();
|
2018-11-19 20:24:36 +01:00
|
|
|
ASSERT(common != nullptr);
|
2018-11-17 18:19:06 +01:00
|
|
|
|
2018-11-19 20:24:36 +01:00
|
|
|
const auto common_data = common->GetData();
|
2018-11-17 18:19:06 +01:00
|
|
|
|
|
|
|
ASSERT(common_data.size() >= sizeof(CommonArguments));
|
|
|
|
std::memcpy(&common_args, common_data.data(), sizeof(CommonArguments));
|
|
|
|
|
2018-11-10 02:09:37 +01:00
|
|
|
initialized = true;
|
|
|
|
}
|
|
|
|
|
2019-05-29 04:14:07 +02:00
|
|
|
AppletFrontendSet::AppletFrontendSet() = default;
|
|
|
|
|
2019-06-07 01:46:36 +02:00
|
|
|
AppletFrontendSet::AppletFrontendSet(ParentalControlsApplet parental_controls, ErrorApplet error,
|
|
|
|
PhotoViewer photo_viewer, ProfileSelect profile_select,
|
|
|
|
SoftwareKeyboard software_keyboard, WebBrowser web_browser,
|
|
|
|
ECommerceApplet e_commerce)
|
|
|
|
: parental_controls{std::move(parental_controls)}, error{std::move(error)},
|
|
|
|
photo_viewer{std::move(photo_viewer)}, profile_select{std::move(profile_select)},
|
|
|
|
software_keyboard{std::move(software_keyboard)}, web_browser{std::move(web_browser)},
|
|
|
|
e_commerce{std::move(e_commerce)} {}
|
2019-05-29 04:14:07 +02:00
|
|
|
|
|
|
|
AppletFrontendSet::~AppletFrontendSet() = default;
|
|
|
|
|
|
|
|
AppletFrontendSet::AppletFrontendSet(AppletFrontendSet&&) noexcept = default;
|
|
|
|
|
|
|
|
AppletFrontendSet& AppletFrontendSet::operator=(AppletFrontendSet&&) noexcept = default;
|
|
|
|
|
2019-07-11 06:53:55 +02:00
|
|
|
AppletManager::AppletManager(Core::System& system_) : system{system_} {}
|
2019-03-12 00:32:59 +01:00
|
|
|
|
|
|
|
AppletManager::~AppletManager() = default;
|
|
|
|
|
2019-04-29 00:43:10 +02:00
|
|
|
const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const {
|
|
|
|
return frontend;
|
|
|
|
}
|
|
|
|
|
2019-03-12 00:32:59 +01:00
|
|
|
void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
|
2019-06-05 18:13:59 +02:00
|
|
|
if (set.parental_controls != nullptr)
|
|
|
|
frontend.parental_controls = std::move(set.parental_controls);
|
2019-03-12 00:32:59 +01:00
|
|
|
if (set.error != nullptr)
|
|
|
|
frontend.error = std::move(set.error);
|
|
|
|
if (set.photo_viewer != nullptr)
|
|
|
|
frontend.photo_viewer = std::move(set.photo_viewer);
|
|
|
|
if (set.profile_select != nullptr)
|
|
|
|
frontend.profile_select = std::move(set.profile_select);
|
|
|
|
if (set.software_keyboard != nullptr)
|
|
|
|
frontend.software_keyboard = std::move(set.software_keyboard);
|
|
|
|
if (set.web_browser != nullptr)
|
|
|
|
frontend.web_browser = std::move(set.web_browser);
|
2019-06-05 18:13:59 +02:00
|
|
|
if (set.e_commerce != nullptr)
|
|
|
|
frontend.e_commerce = std::move(set.e_commerce);
|
2019-03-12 00:32:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletManager::SetDefaultAppletFrontendSet() {
|
2019-06-05 18:13:59 +02:00
|
|
|
ClearAll();
|
|
|
|
SetDefaultAppletsIfMissing();
|
2019-03-12 00:32:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletManager::SetDefaultAppletsIfMissing() {
|
2019-06-05 18:13:59 +02:00
|
|
|
if (frontend.parental_controls == nullptr) {
|
|
|
|
frontend.parental_controls =
|
|
|
|
std::make_unique<Core::Frontend::DefaultParentalControlsApplet>();
|
|
|
|
}
|
|
|
|
|
2019-03-12 00:32:59 +01:00
|
|
|
if (frontend.error == nullptr) {
|
|
|
|
frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frontend.photo_viewer == nullptr) {
|
|
|
|
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frontend.profile_select == nullptr) {
|
|
|
|
frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frontend.software_keyboard == nullptr) {
|
|
|
|
frontend.software_keyboard =
|
|
|
|
std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frontend.web_browser == nullptr) {
|
|
|
|
frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
|
|
|
|
}
|
2019-06-05 18:13:59 +02:00
|
|
|
|
|
|
|
if (frontend.e_commerce == nullptr) {
|
|
|
|
frontend.e_commerce = std::make_unique<Core::Frontend::DefaultECommerceApplet>();
|
|
|
|
}
|
2019-03-12 00:32:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppletManager::ClearAll() {
|
|
|
|
frontend = {};
|
|
|
|
}
|
|
|
|
|
2019-07-11 06:53:55 +02:00
|
|
|
std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
|
2019-03-12 00:32:59 +01:00
|
|
|
switch (id) {
|
2019-06-05 18:13:59 +02:00
|
|
|
case AppletId::Auth:
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<Auth>(system, *frontend.parental_controls);
|
2019-03-12 00:32:59 +01:00
|
|
|
case AppletId::Error:
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<Error>(system, *frontend.error);
|
2019-03-12 00:32:59 +01:00
|
|
|
case AppletId::ProfileSelect:
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<ProfileSelect>(system, *frontend.profile_select);
|
2019-03-12 00:32:59 +01:00
|
|
|
case AppletId::SoftwareKeyboard:
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<SoftwareKeyboard>(system, *frontend.software_keyboard);
|
2019-03-12 00:32:59 +01:00
|
|
|
case AppletId::PhotoViewer:
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<PhotoViewer>(system, *frontend.photo_viewer);
|
2019-06-05 18:13:59 +02:00
|
|
|
case AppletId::LibAppletShop:
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<WebBrowser>(system, *frontend.web_browser,
|
2019-06-07 01:46:36 +02:00
|
|
|
frontend.e_commerce.get());
|
2019-03-12 00:32:59 +01:00
|
|
|
case AppletId::LibAppletOff:
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<WebBrowser>(system, *frontend.web_browser);
|
2019-03-12 00:32:59 +01:00
|
|
|
default:
|
|
|
|
UNIMPLEMENTED_MSG(
|
|
|
|
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
|
|
|
|
static_cast<u8>(id));
|
2019-07-11 06:53:55 +02:00
|
|
|
return std::make_shared<StubApplet>(system, id);
|
2019-03-12 00:32:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-10 02:09:37 +01:00
|
|
|
} // namespace Service::AM::Applets
|