From 76d515327b14c54036065167cb5dedcc5bf29eb2 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:01:20 -0500 Subject: am: Implement CreateTransferMemoryStorage Creates an AM::IStorage object with the contents of the transfer memory located at the handle provided. --- src/core/hle/service/am/am.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 3758ecae1..a7716d80b 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -704,6 +704,31 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called, size={}", size); } +void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + rp.SetCurrentOffset(3); + const auto handle{rp.Pop()}; + + const auto shared_mem = + Core::System::GetInstance().CurrentProcess()->GetHandleTable().Get( + handle); + + if (shared_mem == nullptr) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(-1)); + return; + } + + std::vector memory(shared_mem->size); + std::memcpy(memory.data(), shared_mem->backing_block->data() + shared_mem->backing_block_offset, + memory.size()); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::make_shared(std::move(memory))); +} + IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { // clang-format off static const FunctionInfo functions[] = { -- cgit v1.2.3 From c7b6c9de9c4004399edf8a010b74fee1127c7682 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:04:07 -0500 Subject: am: Move IStorageAccessor to header and update backing buffer Writes to an AM::IStorage object through an IStorageAccessor will now be preserved once the accessor is destroyed. --- src/core/hle/service/am/am.cpp | 100 +++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 64 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a7716d80b..c7344608c 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -587,87 +587,59 @@ private: } }; -class ILibraryAppletAccessor final : public ServiceFramework { -public: - explicit ILibraryAppletAccessor() : ServiceFramework("ILibraryAppletAccessor") { - // clang-format off +IStorageAccessor::IStorageAccessor(IStorage& storage) + : ServiceFramework("IStorageAccessor"), backing(storage) { + // clang-format off static const FunctionInfo functions[] = { - {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, - {1, nullptr, "IsCompleted"}, - {10, &ILibraryAppletAccessor::Start, "Start"}, - {20, nullptr, "RequestExit"}, - {25, nullptr, "Terminate"}, - {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, - {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, - {100, &ILibraryAppletAccessor::PushInData, "PushInData"}, - {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"}, - {102, nullptr, "PushExtraStorage"}, - {103, nullptr, "PushInteractiveInData"}, - {104, nullptr, "PopInteractiveOutData"}, - {105, nullptr, "GetPopOutDataEvent"}, - {106, nullptr, "GetPopInteractiveOutDataEvent"}, - {110, nullptr, "NeedsToExitProcess"}, - {120, nullptr, "GetLibraryAppletInfo"}, - {150, nullptr, "RequestForAppletToGetForeground"}, - {160, nullptr, "GetIndirectLayerConsumerHandle"}, + {0, &IStorageAccessor::GetSize, "GetSize"}, + {10, &IStorageAccessor::Write, "Write"}, + {11, &IStorageAccessor::Read, "Read"}, }; - // clang-format on + // clang-format on - RegisterHandlers(functions); + RegisterHandlers(functions); +} - auto& kernel = Core::System::GetInstance().Kernel(); - state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, - "ILibraryAppletAccessor:StateChangedEvent"); - } +void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 4}; -private: - void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { - state_changed_event->Signal(); + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast(backing.buffer.size())); - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(state_changed_event); + LOG_DEBUG(Service_AM, "called"); +} - LOG_WARNING(Service_AM, "(STUBBED) called"); - } +void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; - void GetResult(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); + const u64 offset{rp.Pop()}; + const std::vector data{ctx.ReadBuffer()}; - LOG_WARNING(Service_AM, "(STUBBED) called"); - } + const auto size = std::min(data.size(), backing.buffer.size() - offset); - void Start(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); + std::memcpy(&backing.buffer[offset], data.data(), size); - LOG_WARNING(Service_AM, "(STUBBED) called"); - } + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); - void PushInData(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - storage_stack.push(rp.PopIpcInterface()); + LOG_DEBUG(Service_AM, "called, offset={}", offset); +} - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); +void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; - LOG_DEBUG(Service_AM, "called"); - } + const u64 offset{rp.Pop()}; + std::size_t size{ctx.GetWriteBufferSize()}; - void PopOutData(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(std::move(storage_stack.top())); + size = std::min(size, backing.buffer.size() - offset); - storage_stack.pop(); + ctx.WriteBuffer(backing.buffer.data() + offset, size); - LOG_DEBUG(Service_AM, "called"); - } + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); - std::stack> storage_stack; - Kernel::SharedPtr state_changed_event; -}; + LOG_DEBUG(Service_AM, "called, offset={}", offset); +} ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") { static const FunctionInfo functions[] = { @@ -675,7 +647,7 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple {1, nullptr, "TerminateAllLibraryApplets"}, {2, nullptr, "AreAnyLibraryAppletsLeft"}, {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, - {11, nullptr, "CreateTransferMemoryStorage"}, + {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, {12, nullptr, "CreateHandleStorage"}, }; RegisterHandlers(functions); -- cgit v1.2.3 From 0682a908c0ab79a5137f408cafc3aff07c7c7be5 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:04:43 -0500 Subject: am: Move AM::IStorage to header Needs to be accessible by applet files. --- src/core/hle/service/am/am.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index c7344608c..35481b201 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -481,6 +481,22 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& LOG_DEBUG(Service_AM, "called"); } +IStorage::IStorage(std::vector buffer) + : ServiceFramework("IStorage"), buffer(std::move(buffer)) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IStorage::Open, "Open"}, + {1, nullptr, "OpenTransferStorage"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +const std::vector& IStorage::GetData() const { + return buffer; +} + void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { const bool use_docked_mode{Settings::values.use_docked_mode}; IPC::ResponseBuilder rb{ctx, 3}; -- cgit v1.2.3 From 5ce6b8fea7122fb8267252d09d4416769637702d Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:06:50 -0500 Subject: am: Convert storage stack to vector std::stack was no longer suitable for non-trivial operations --- src/core/hle/service/am/am.cpp | 86 +++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 27 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 35481b201..a872bea0c 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -516,31 +516,56 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); } -class IStorageAccessor final : public ServiceFramework { +class ILibraryAppletAccessor final : public ServiceFramework { public: - explicit IStorageAccessor(std::vector buffer) - : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) { + explicit ILibraryAppletAccessor(std::shared_ptr applet) + : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)) { // clang-format off static const FunctionInfo functions[] = { - {0, &IStorageAccessor::GetSize, "GetSize"}, - {10, &IStorageAccessor::Write, "Write"}, - {11, &IStorageAccessor::Read, "Read"}, + {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, + {1, nullptr, "IsCompleted"}, + {10, &ILibraryAppletAccessor::Start, "Start"}, + {20, nullptr, "RequestExit"}, + {25, nullptr, "Terminate"}, + {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, + {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, + {100, &ILibraryAppletAccessor::PushInData, "PushInData"}, + {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"}, + {102, nullptr, "PushExtraStorage"}, + {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, + {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, + {105, nullptr, "GetPopOutDataEvent"}, + {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, + {110, nullptr, "NeedsToExitProcess"}, + {120, nullptr, "GetLibraryAppletInfo"}, + {150, nullptr, "RequestForAppletToGetForeground"}, + {160, nullptr, "GetIndirectLayerConsumerHandle"}, }; // clang-format on RegisterHandlers(functions); + + auto& kernel = Core::System::GetInstance().Kernel(); + state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, + "ILibraryAppletAccessor:StateChangedEvent"); } private: - std::vector buffer; + void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { + state_changed_event->Signal(); - void GetSize(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 4}; + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(state_changed_event); + + LOG_WARNING(Service_AM, "(STUBBED) called"); + } + void GetResult(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - rb.Push(static_cast(buffer.size())); - LOG_DEBUG(Service_AM, "called"); + LOG_WARNING(Service_AM, "(STUBBED) called"); } void Write(Kernel::HLERequestContext& ctx) { @@ -551,21 +576,25 @@ private: ASSERT(offset + data.size() <= buffer.size()); - std::memcpy(&buffer[offset], data.data(), data.size()); + void PushInData(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + storage_stack.push_back(rp.PopIpcInterface()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_DEBUG(Service_AM, "called, offset={}", offset); + LOG_DEBUG(Service_AM, "called"); } - void Read(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; + void PopOutData(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::move(storage_stack.back())); - const u64 offset{rp.Pop()}; - const std::size_t size{ctx.GetWriteBufferSize()}; + storage_stack.pop_back(); - ASSERT(offset + size <= buffer.size()); + LOG_DEBUG(Service_AM, "called"); + } ctx.WriteBuffer(buffer.data() + offset, size); @@ -590,18 +619,21 @@ public: RegisterHandlers(functions); } -private: - std::vector buffer; + std::shared_ptr applet; + std::vector> storage_stack; + std::vector> interactive_storage_stack; + Kernel::SharedPtr state_changed_event; + Kernel::SharedPtr pop_interactive_out_data_event; +}; - void Open(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +void IStorage::Open(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(buffer); + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(*this); - LOG_DEBUG(Service_AM, "called"); - } -}; + LOG_DEBUG(Service_AM, "called"); +} IStorageAccessor::IStorageAccessor(IStorage& storage) : ServiceFramework("IStorageAccessor"), backing(storage) { -- cgit v1.2.3 From ba03bfa4309664d55d585c89271d9656f8385a78 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:07:42 -0500 Subject: am: Implement PopInteractiveOutData and PushInteractiveInData Used by software keyboard applet for data transfer. --- src/core/hle/service/am/am.cpp | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a872bea0c..b78489df7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -548,6 +548,9 @@ public: auto& kernel = Core::System::GetInstance().Kernel(); state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:StateChangedEvent"); + pop_interactive_out_data_event = + Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, + "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); } private: @@ -596,27 +599,34 @@ private: LOG_DEBUG(Service_AM, "called"); } - ctx.WriteBuffer(buffer.data() + offset, size); + void PushInteractiveInData(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + interactive_storage_stack.push_back(rp.PopIpcInterface()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_DEBUG(Service_AM, "called, offset={}", offset); + LOG_DEBUG(Service_AM, "called"); } -}; -class IStorage final : public ServiceFramework { -public: - explicit IStorage(std::vector buffer) - : ServiceFramework("IStorage"), buffer(std::move(buffer)) { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IStorage::Open, "Open"}, - {1, nullptr, "OpenTransferStorage"}, - }; - // clang-format on + void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::move(interactive_storage_stack.back())); - RegisterHandlers(functions); + interactive_storage_stack.pop_back(); + + LOG_DEBUG(Service_AM, "called"); + } + + void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { + pop_interactive_out_data_event->Signal(); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(pop_interactive_out_data_event); + + LOG_WARNING(Service_AM, "(STUBBED) called"); } std::shared_ptr applet; -- cgit v1.2.3 From 731b4bd69185e741282415b66cc39fd482c039b9 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:08:25 -0500 Subject: am: Unstub ILibraryAppletAccessor::Start Now starts the applet provided in constructor. --- src/core/hle/service/am/am.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index b78489df7..4b7aacbac 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -6,10 +6,14 @@ #include #include #include +#include "applets/applets.h" +#include "applets/software_keyboard.h" +#include "audio_core/audio_renderer.h" #include "core/core.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/shared_memory.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" @@ -28,6 +32,10 @@ namespace Service::AM { +enum class AppletId : u32 { + SoftwareKeyboard = 0x11, +}; + constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA; struct LaunchParameters { @@ -571,13 +579,17 @@ private: LOG_WARNING(Service_AM, "(STUBBED) called"); } - void Write(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; + void Start(Kernel::HLERequestContext& ctx) { + ASSERT(applet != nullptr); - const u64 offset{rp.Pop()}; - const std::vector data{ctx.ReadBuffer()}; + applet->Initialize(storage_stack); + interactive_storage_stack.push_back(std::make_shared(applet->Execute())); + state_changed_event->Signal(); + pop_interactive_out_data_event->Signal(); - ASSERT(offset + data.size() <= buffer.size()); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } void PushInData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; -- cgit v1.2.3 From 48fcb43585132e52acaf9d859dd5d39fb308cb14 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:14:01 -0500 Subject: am: Construct and use proper applets with ILibraryAppletAccessor Allows use of software keyboard applet and future applets to be easily added by adding enum ID and a switch case. --- src/core/hle/service/am/am.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 4b7aacbac..53580d673 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -725,11 +725,36 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple ILibraryAppletCreator::~ILibraryAppletCreator() = default; +static std::shared_ptr GetAppletFromId(AppletId id) { + switch (id) { + case AppletId::SoftwareKeyboard: + return std::make_shared(); + default: + UNREACHABLE_MSG("Unimplemented AppletId [{:08X}]!", static_cast(id)); + return nullptr; + } +} + void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_id = rp.PopRaw(); + const auto applet_mode = rp.PopRaw(); + + LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", + static_cast(applet_id), applet_mode); + + const auto applet = GetAppletFromId(applet_id); + + if (applet == nullptr) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(-1)); + return; + } + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(); + rb.PushIpcInterface(applet); LOG_DEBUG(Service_AM, "called"); } -- cgit v1.2.3 From e696ed1f4d20f28f8b26c637498962938df7d96f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 16:39:25 -0500 Subject: am: Deglobalize software keyboard applet --- src/core/hle/service/am/am.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 53580d673..fc464270e 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -501,6 +501,8 @@ IStorage::IStorage(std::vector buffer) RegisterHandlers(functions); } +IStorage::~IStorage() = default; + const std::vector& IStorage::GetData() const { return buffer; } @@ -670,6 +672,8 @@ IStorageAccessor::IStorageAccessor(IStorage& storage) RegisterHandlers(functions); } +IStorageAccessor::~IStorageAccessor() = default; + void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; @@ -685,7 +689,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; const std::vector data{ctx.ReadBuffer()}; - const auto size = std::min(data.size(), backing.buffer.size() - offset); + const auto size = std::min(data.size(), backing.buffer.size() - offset); std::memcpy(&backing.buffer[offset], data.data(), size); @@ -701,7 +705,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; std::size_t size{ctx.GetWriteBufferSize()}; - size = std::min(size, backing.buffer.size() - offset); + size = std::min(size, backing.buffer.size() - offset); ctx.WriteBuffer(backing.buffer.data() + offset, size); @@ -787,9 +791,9 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex return; } - std::vector memory(shared_mem->size); - std::memcpy(memory.data(), shared_mem->backing_block->data() + shared_mem->backing_block_offset, - memory.size()); + const auto mem_begin = shared_mem->backing_block->begin() + shared_mem->backing_block_offset; + const auto mem_end = mem_begin + shared_mem->size; + std::vector memory{mem_begin, mem_end}; IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); -- cgit v1.2.3 From fed6ab14c37f196f2a2fd378b46d7e5bd0118224 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 16:41:31 -0500 Subject: am: Implement text check software keyboard mode Allows the game to verify and send a message to the frontend. --- src/core/hle/service/am/am.cpp | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index fc464270e..ea00c5c72 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -544,7 +544,7 @@ public: {102, nullptr, "PushExtraStorage"}, {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, - {105, nullptr, "GetPopOutDataEvent"}, + {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"}, {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, {110, nullptr, "NeedsToExitProcess"}, {120, nullptr, "GetLibraryAppletInfo"}, @@ -558,6 +558,8 @@ public: auto& kernel = Core::System::GetInstance().Kernel(); state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:StateChangedEvent"); + pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, + "ILibraryAppletAccessor:PopDataOutEvent"); pop_interactive_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); @@ -585,9 +587,16 @@ private: ASSERT(applet != nullptr); applet->Initialize(storage_stack); - interactive_storage_stack.push_back(std::make_shared(applet->Execute())); + const auto data = std::make_shared(applet->Execute()); state_changed_event->Signal(); - pop_interactive_out_data_event->Signal(); + + if (applet->TransactionComplete()) { + storage_stack.push_back(data); + pop_out_data_event->Signal(); + } else { + interactive_storage_stack.push_back(data); + pop_interactive_out_data_event->Signal(); + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -617,6 +626,19 @@ private: IPC::RequestParser rp{ctx}; interactive_storage_stack.push_back(rp.PopIpcInterface()); + ASSERT(applet->IsInitialized()); + applet->ReceiveInteractiveData(interactive_storage_stack.back()); + const auto data = std::make_shared(applet->Execute()); + state_changed_event->Signal(); + + if (applet->TransactionComplete()) { + storage_stack.push_back(data); + pop_out_data_event->Signal(); + } else { + interactive_storage_stack.push_back(data); + pop_interactive_out_data_event->Signal(); + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -633,9 +655,13 @@ private: LOG_DEBUG(Service_AM, "called"); } - void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { - pop_interactive_out_data_event->Signal(); + void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(pop_out_data_event); + } + void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(pop_interactive_out_data_event); @@ -647,6 +673,7 @@ private: std::vector> storage_stack; std::vector> interactive_storage_stack; Kernel::SharedPtr state_changed_event; + Kernel::SharedPtr pop_out_data_event; Kernel::SharedPtr pop_interactive_out_data_event; }; -- cgit v1.2.3 From 3cf7246e376445320e2b55165265228736f65214 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 16:57:59 -0500 Subject: am: Implement ILibraryAppletAccessor IsCompleted and GetResult --- src/core/hle/service/am/am.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index ea00c5c72..3201e2d4b 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -533,7 +533,7 @@ public: // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, - {1, nullptr, "IsCompleted"}, + {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, {10, &ILibraryAppletAccessor::Start, "Start"}, {20, nullptr, "RequestExit"}, {25, nullptr, "Terminate"}, @@ -576,11 +576,15 @@ private: LOG_WARNING(Service_AM, "(STUBBED) called"); } - void GetResult(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; + void IsCompleted(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); + rb.Push(applet->TransactionComplete()); + } - LOG_WARNING(Service_AM, "(STUBBED) called"); + void GetResult(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(applet->GetStatus()); } void Start(Kernel::HLERequestContext& ctx) { -- cgit v1.2.3 From 7cfb29de23836aa1873bbb108e3d25a0e9dcfa6d Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 20:16:38 -0500 Subject: am: Allow applets to push multiple and different channels of data --- src/core/hle/service/am/am.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 3201e2d4b..3f8d97d31 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -566,6 +566,16 @@ public: } private: + void AppletStorageProxyOutData(IStorage storage) { + storage_stack.push_back(std::make_shared(storage)); + pop_out_data_event->Signal(); + } + + void AppletStorageProxyOutInteractiveData(IStorage storage) { + interactive_storage_stack.push_back(std::make_shared(storage)); + pop_interactive_out_data_event->Signal(); + } + void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { state_changed_event->Signal(); @@ -591,17 +601,11 @@ private: ASSERT(applet != nullptr); applet->Initialize(storage_stack); - const auto data = std::make_shared(applet->Execute()); + applet->Execute( + [this](IStorage storage) { AppletStorageProxyOutData(storage); }, + [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }); state_changed_event->Signal(); - if (applet->TransactionComplete()) { - storage_stack.push_back(data); - pop_out_data_event->Signal(); - } else { - interactive_storage_stack.push_back(data); - pop_interactive_out_data_event->Signal(); - } - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -632,17 +636,11 @@ private: ASSERT(applet->IsInitialized()); applet->ReceiveInteractiveData(interactive_storage_stack.back()); - const auto data = std::make_shared(applet->Execute()); + applet->Execute( + [this](IStorage storage) { AppletStorageProxyOutData(storage); }, + [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }); state_changed_event->Signal(); - if (applet->TransactionComplete()) { - storage_stack.push_back(data); - pop_out_data_event->Signal(); - } else { - interactive_storage_stack.push_back(data); - pop_interactive_out_data_event->Signal(); - } - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); -- cgit v1.2.3 From 8b433beff34c382e50334bb59c4f71394845558c Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 12 Nov 2018 11:08:09 -0500 Subject: software_keyboard: Make GetText asynchronous a --- src/core/hle/service/am/am.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 3f8d97d31..d040d4776 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -718,7 +718,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; const std::vector data{ctx.ReadBuffer()}; - const auto size = std::min(data.size(), backing.buffer.size() - offset); + const auto size = std::min(data.size(), backing.buffer.size() - offset); std::memcpy(&backing.buffer[offset], data.data(), size); -- cgit v1.2.3 From 6209fe0c27a5557c20ff6350a94f6e074e0285dc Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 16 Nov 2018 22:20:09 -0500 Subject: software_keyboard: Push buffer size to offset 0x4 in output data --- src/core/hle/service/am/am.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index d040d4776..470253ef1 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -583,31 +583,38 @@ private: rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(state_changed_event); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } void IsCompleted(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); rb.Push(applet->TransactionComplete()); + + LOG_DEBUG(Service_AM, "called"); } void GetResult(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(applet->GetStatus()); + + LOG_DEBUG(Service_AM, "called"); } void Start(Kernel::HLERequestContext& ctx) { ASSERT(applet != nullptr); applet->Initialize(storage_stack); - applet->Execute( - [this](IStorage storage) { AppletStorageProxyOutData(storage); }, - [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }); - state_changed_event->Signal(); + storage_stack.clear(); + interactive_storage_stack.clear(); + applet->Execute([this](IStorage storage) { AppletStorageProxyOutData(storage); }, + [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }, + [this] { state_changed_event->Signal(); }); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); + + LOG_DEBUG(Service_AM, "called"); } void PushInData(Kernel::HLERequestContext& ctx) { @@ -636,10 +643,9 @@ private: ASSERT(applet->IsInitialized()); applet->ReceiveInteractiveData(interactive_storage_stack.back()); - applet->Execute( - [this](IStorage storage) { AppletStorageProxyOutData(storage); }, - [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }); - state_changed_event->Signal(); + applet->Execute([this](IStorage storage) { AppletStorageProxyOutData(storage); }, + [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }, + [this] { state_changed_event->Signal(); }); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -661,6 +667,8 @@ private: IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(pop_out_data_event); + + LOG_DEBUG(Service_AM, "called"); } void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { @@ -668,7 +676,7 @@ private: rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(pop_interactive_out_data_event); - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); } std::shared_ptr applet; @@ -734,7 +742,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; std::size_t size{ctx.GetWriteBufferSize()}; - size = std::min(size, backing.buffer.size() - offset); + size = std::min(size, backing.buffer.size() - offset); ctx.WriteBuffer(backing.buffer.data() + offset, size); -- cgit v1.2.3 From 19b2571aecfff680c7a414c505eafc26264b6f2f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 17 Nov 2018 12:18:03 -0500 Subject: applet: Add operation completed callback --- src/core/hle/service/am/am.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 470253ef1..5cbcb8d91 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -605,8 +605,10 @@ private: ASSERT(applet != nullptr); applet->Initialize(storage_stack); - storage_stack.clear(); - interactive_storage_stack.clear(); + while (!storage_stack.empty()) + storage_stack.pop(); + while (!interactive_storage_stack.empty()) + interactive_storage_stack.pop(); applet->Execute([this](IStorage storage) { AppletStorageProxyOutData(storage); }, [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }, [this] { state_changed_event->Signal(); }); -- cgit v1.2.3 From 4ee087fb3ca2b1e064422b73195a8ff7698721d9 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 17 Nov 2018 12:19:06 -0500 Subject: applet: Use std::queue instead of std::vector for storage stack --- src/core/hle/service/am/am.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 5cbcb8d91..d92a46b00 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -567,12 +567,12 @@ public: private: void AppletStorageProxyOutData(IStorage storage) { - storage_stack.push_back(std::make_shared(storage)); + storage_stack.push(std::make_shared(storage)); pop_out_data_event->Signal(); } void AppletStorageProxyOutInteractiveData(IStorage storage) { - interactive_storage_stack.push_back(std::make_shared(storage)); + interactive_storage_stack.push(std::make_shared(storage)); pop_interactive_out_data_event->Signal(); } @@ -621,7 +621,7 @@ private: void PushInData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - storage_stack.push_back(rp.PopIpcInterface()); + storage_stack.push(rp.PopIpcInterface()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -631,17 +631,23 @@ private: void PopOutData(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + + if (storage_stack.empty()) { + rb.Push(ResultCode(-1)); + return; + } + rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(std::move(storage_stack.back())); + rb.PushIpcInterface(std::move(storage_stack.front())); - storage_stack.pop_back(); + storage_stack.pop(); LOG_DEBUG(Service_AM, "called"); } void PushInteractiveInData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - interactive_storage_stack.push_back(rp.PopIpcInterface()); + interactive_storage_stack.push(rp.PopIpcInterface()); ASSERT(applet->IsInitialized()); applet->ReceiveInteractiveData(interactive_storage_stack.back()); @@ -657,10 +663,16 @@ private: void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + + if (interactive_storage_stack.empty()) { + rb.Push(ResultCode(-1)); + return; + } + rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(std::move(interactive_storage_stack.back())); + rb.PushIpcInterface(std::move(interactive_storage_stack.front())); - interactive_storage_stack.pop_back(); + interactive_storage_stack.pop(); LOG_DEBUG(Service_AM, "called"); } @@ -682,8 +694,8 @@ private: } std::shared_ptr applet; - std::vector> storage_stack; - std::vector> interactive_storage_stack; + std::queue> storage_stack; + std::queue> interactive_storage_stack; Kernel::SharedPtr state_changed_event; Kernel::SharedPtr pop_out_data_event; Kernel::SharedPtr pop_interactive_out_data_event; -- cgit v1.2.3 From 32775125b7af14cf488fdcbc4a61c00507c2d4a5 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 19 Nov 2018 14:24:36 -0500 Subject: applet: Add AppletDataBroker to manage HLE to AM service interaction This cleans up most of the callbacks and such in the Applets::Applet interface, while also properly implementing all four data channels. --- src/core/hle/service/am/am.cpp | 92 ++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 57 deletions(-) (limited to 'src/core/hle/service/am/am.cpp') diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index d92a46b00..fd14af1e7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -32,6 +32,9 @@ namespace Service::AM { +constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2}; +constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7}; + enum class AppletId : u32 { SoftwareKeyboard = 0x11, }; @@ -529,7 +532,8 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { class ILibraryAppletAccessor final : public ServiceFramework { public: explicit ILibraryAppletAccessor(std::shared_ptr applet) - : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)) { + : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)), + broker(std::make_shared()) { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, @@ -554,34 +558,16 @@ public: // clang-format on RegisterHandlers(functions); - - auto& kernel = Core::System::GetInstance().Kernel(); - state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, - "ILibraryAppletAccessor:StateChangedEvent"); - pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, - "ILibraryAppletAccessor:PopDataOutEvent"); - pop_interactive_out_data_event = - Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, - "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); } private: - void AppletStorageProxyOutData(IStorage storage) { - storage_stack.push(std::make_shared(storage)); - pop_out_data_event->Signal(); - } - - void AppletStorageProxyOutInteractiveData(IStorage storage) { - interactive_storage_stack.push(std::make_shared(storage)); - pop_interactive_out_data_event->Signal(); - } - void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { - state_changed_event->Signal(); + const auto event = broker->GetStateChangedEvent(); + event->Signal(); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(state_changed_event); + rb.PushCopyObjects(event); LOG_DEBUG(Service_AM, "called"); } @@ -604,14 +590,8 @@ private: void Start(Kernel::HLERequestContext& ctx) { ASSERT(applet != nullptr); - applet->Initialize(storage_stack); - while (!storage_stack.empty()) - storage_stack.pop(); - while (!interactive_storage_stack.empty()) - interactive_storage_stack.pop(); - applet->Execute([this](IStorage storage) { AppletStorageProxyOutData(storage); }, - [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }, - [this] { state_changed_event->Signal(); }); + applet->Initialize(broker); + applet->Execute(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -621,7 +601,7 @@ private: void PushInData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - storage_stack.push(rp.PopIpcInterface()); + broker->PushNormalDataFromGame(*rp.PopIpcInterface()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -632,28 +612,25 @@ private: void PopOutData(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - if (storage_stack.empty()) { - rb.Push(ResultCode(-1)); + const auto storage = broker->PopNormalDataToGame(); + if (storage == nullptr) { + rb.Push(ERR_NO_DATA_IN_CHANNEL); return; } rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(std::move(storage_stack.front())); - - storage_stack.pop(); + rb.PushIpcInterface(std::move(*storage)); LOG_DEBUG(Service_AM, "called"); } void PushInteractiveInData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - interactive_storage_stack.push(rp.PopIpcInterface()); + broker->PushInteractiveDataFromGame(*rp.PopIpcInterface()); ASSERT(applet->IsInitialized()); - applet->ReceiveInteractiveData(interactive_storage_stack.back()); - applet->Execute([this](IStorage storage) { AppletStorageProxyOutData(storage); }, - [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }, - [this] { state_changed_event->Signal(); }); + applet->ExecuteInteractive(); + applet->Execute(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -664,15 +641,14 @@ private: void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - if (interactive_storage_stack.empty()) { - rb.Push(ResultCode(-1)); + const auto storage = broker->PopInteractiveDataToGame(); + if (storage == nullptr) { + rb.Push(ERR_NO_DATA_IN_CHANNEL); return; } rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(std::move(interactive_storage_stack.front())); - - interactive_storage_stack.pop(); + rb.PushIpcInterface(std::move(*storage)); LOG_DEBUG(Service_AM, "called"); } @@ -680,7 +656,7 @@ private: void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(pop_out_data_event); + rb.PushCopyObjects(broker->GetNormalDataEvent()); LOG_DEBUG(Service_AM, "called"); } @@ -688,17 +664,13 @@ private: void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(pop_interactive_out_data_event); + rb.PushCopyObjects(broker->GetInteractiveDataEvent()); LOG_DEBUG(Service_AM, "called"); } std::shared_ptr applet; - std::queue> storage_stack; - std::queue> interactive_storage_stack; - Kernel::SharedPtr state_changed_event; - Kernel::SharedPtr pop_out_data_event; - Kernel::SharedPtr pop_interactive_out_data_event; + std::shared_ptr broker; }; void IStorage::Open(Kernel::HLERequestContext& ctx) { @@ -740,9 +712,12 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; const std::vector data{ctx.ReadBuffer()}; - const auto size = std::min(data.size(), backing.buffer.size() - offset); + if (data.size() > backing.buffer.size() - offset) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_SIZE_OUT_OF_BOUNDS); + } - std::memcpy(&backing.buffer[offset], data.data(), size); + std::memcpy(backing.buffer.data() + offset, data.data(), data.size()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -754,9 +729,12 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 offset{rp.Pop()}; - std::size_t size{ctx.GetWriteBufferSize()}; + const std::size_t size{ctx.GetWriteBufferSize()}; - size = std::min(size, backing.buffer.size() - offset); + if (size > backing.buffer.size() - offset) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_SIZE_OUT_OF_BOUNDS); + } ctx.WriteBuffer(backing.buffer.data() + offset, size); -- cgit v1.2.3