diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/service/am/am.cpp | 37 | ||||
-rw-r--r-- | src/core/hle/service/am/applets/applets.h | 5 | ||||
-rw-r--r-- | src/core/hle/service/am/applets/software_keyboard.cpp | 67 |
3 files changed, 95 insertions, 14 deletions
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<IStorage>(applet->Execute())); + const auto data = std::make_shared<IStorage>(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<IStorage>()); + ASSERT(applet->IsInitialized()); + applet->ReceiveInteractiveData(interactive_storage_stack.back()); + const auto data = std::make_shared<IStorage>(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<std::shared_ptr<IStorage>> storage_stack; std::vector<std::shared_ptr<IStorage>> interactive_storage_stack; Kernel::SharedPtr<Kernel::Event> state_changed_event; + Kernel::SharedPtr<Kernel::Event> pop_out_data_event; Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event; }; diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 47db22fb4..6d90eb608 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -8,6 +8,8 @@ #include <vector> #include "common/swap.h" +union ResultCode; + namespace Frontend { class SoftwareKeyboardApplet; } @@ -25,6 +27,9 @@ public: virtual void Initialize(std::vector<std::shared_ptr<IStorage>> storage); + virtual bool TransactionComplete() const = 0; + virtual ResultCode GetStatus() const = 0; + virtual void ReceiveInteractiveData(std::shared_ptr<IStorage> storage) = 0; virtual IStorage Execute() = 0; bool IsInitialized() const { diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 556dea3e4..044a16264 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -50,28 +50,77 @@ void SoftwareKeyboard::Initialize(std::vector<std::shared_ptr<IStorage>> storage ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); - ASSERT_MSG(config.text_check == 0, "Text check software keyboard mode is not implemented!"); - const auto& work_buffer = storage_stack[2]->GetData(); - std::memcpy(initial_text.data(), work_buffer.data() + config.initial_string_offset, - config.initial_string_size); + + if (config.initial_string_size == 0) + return; + + std::vector<char16_t> string(config.initial_string_size); + std::memcpy(string.data(), work_buffer.data() + 4, string.size() * 2); + initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()); +} + +bool SoftwareKeyboard::TransactionComplete() const { + return complete; +} + +ResultCode SoftwareKeyboard::GetStatus() const { + return RESULT_SUCCESS; +} + +void SoftwareKeyboard::ReceiveInteractiveData(std::shared_ptr<IStorage> storage) { + if (complete) + return; + + const auto data = storage->GetData(); + const auto status = static_cast<bool>(data[0]); + + if (status == INTERACTIVE_STATUS_OK) { + complete = true; + } else { + const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; + + std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string; + std::memcpy(string.data(), data.data() + 4, string.size() * 2); + frontend.SendTextCheckDialog( + Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size())); + } } IStorage SoftwareKeyboard::Execute() { - const auto frontend{GetSoftwareKeyboard()}; - ASSERT(frontend != nullptr); + if (complete) + return IStorage{final_data}; + + const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; const auto parameters = ConvertToFrontendParameters(config, initial_text); std::u16string text; - const auto success = frontend->GetText(parameters, text); + const auto success = frontend.GetText(parameters, text); std::vector<u8> output(SWKBD_OUTPUT_BUFFER_SIZE); if (success) { - output[0] = 1; + if (config.text_check) { + const auto size = static_cast<u32>(text.size() * 2 + 4); + std::memcpy(output.data(), &size, sizeof(u32)); + } else { + output[0] = 1; + } + std::memcpy(output.data() + 4, text.data(), - std::min<std::size_t>(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); + std::min(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); + } else { + complete = true; + final_data = std::move(output); + return IStorage{final_data}; + } + + complete = !config.text_check; + + if (complete) { + final_data = std::move(output); + return IStorage{final_data}; } return IStorage{output}; |