179 lines
5.9 KiB
C++
179 lines
5.9 KiB
C++
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "common/scope_exit.h"
|
|
#include "core/hle/service/am/am_results.h"
|
|
#include "core/hle/service/am/frontend/applets.h"
|
|
#include "core/hle/service/am/library_applet_accessor.h"
|
|
#include "core/hle/service/am/storage.h"
|
|
#include "core/hle/service/ipc_helpers.h"
|
|
|
|
namespace Service::AM {
|
|
|
|
ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
|
|
std::shared_ptr<AppletStorageHolder> storage_,
|
|
std::shared_ptr<Applet> applet_)
|
|
: ServiceFramework{system_, "ILibraryAppletAccessor"}, storage{std::move(storage_)},
|
|
applet{std::move(applet_)} {
|
|
// clang-format off
|
|
static const FunctionInfo functions[] = {
|
|
{0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
|
|
{1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
|
|
{10, &ILibraryAppletAccessor::Start, "Start"},
|
|
{20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
|
|
{25, nullptr, "Terminate"},
|
|
{30, &ILibraryAppletAccessor::GetResult, "GetResult"},
|
|
{50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
|
|
{60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
|
|
{100, &ILibraryAppletAccessor::PushInData, "PushInData"},
|
|
{101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
|
|
{102, nullptr, "PushExtraStorage"},
|
|
{103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
|
|
{104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
|
|
{105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
|
|
{106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
|
|
{110, nullptr, "NeedsToExitProcess"},
|
|
{120, nullptr, "GetLibraryAppletInfo"},
|
|
{150, nullptr, "RequestForAppletToGetForeground"},
|
|
{160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
|
|
};
|
|
// clang-format on
|
|
|
|
RegisterHandlers(functions);
|
|
}
|
|
|
|
ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
|
|
|
|
void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushCopyObjects(storage->state_changed_event.GetHandle());
|
|
}
|
|
|
|
void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
std::scoped_lock lk{applet->lock};
|
|
|
|
IPC::ResponseBuilder rb{ctx, 3};
|
|
rb.Push(ResultSuccess);
|
|
rb.Push<u32>(applet->is_completed);
|
|
}
|
|
|
|
void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(applet->terminate_result);
|
|
}
|
|
|
|
void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
applet->process->Run();
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
ASSERT(applet != nullptr);
|
|
applet->message_queue.RequestExit();
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
storage->in_data.PushData(rp.PopIpcInterface<IStorage>().lock());
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
std::shared_ptr<IStorage> data;
|
|
const auto res = storage->out_data.PopData(&data);
|
|
|
|
if (res.IsSuccess()) {
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
rb.Push(res);
|
|
rb.PushIpcInterface(std::move(data));
|
|
} else {
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(res);
|
|
}
|
|
}
|
|
|
|
void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
IPC::RequestParser rp{ctx};
|
|
storage->interactive_in_data.PushData(rp.PopIpcInterface<IStorage>().lock());
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(ResultSuccess);
|
|
}
|
|
|
|
void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
std::shared_ptr<IStorage> data;
|
|
const auto res = storage->interactive_out_data.PopData(&data);
|
|
|
|
if (res.IsSuccess()) {
|
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
rb.Push(res);
|
|
rb.PushIpcInterface(std::move(data));
|
|
} else {
|
|
IPC::ResponseBuilder rb{ctx, 2};
|
|
rb.Push(res);
|
|
}
|
|
}
|
|
|
|
void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushCopyObjects(storage->out_data.GetEvent());
|
|
}
|
|
|
|
void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
|
|
LOG_DEBUG(Service_AM, "called");
|
|
|
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
rb.Push(ResultSuccess);
|
|
rb.PushCopyObjects(storage->interactive_out_data.GetEvent());
|
|
}
|
|
|
|
void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
|
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
|
|
// We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
|
|
// actually used anywhere
|
|
constexpr u64 handle = 0xdeadbeef;
|
|
|
|
IPC::ResponseBuilder rb{ctx, 4};
|
|
rb.Push(ResultSuccess);
|
|
rb.Push(handle);
|
|
}
|
|
|
|
} // namespace Service::AM
|