Merge pull request #2840 from Subv/apt_parameter
Services/APT: Corrected the behavior of the Receive/Send/Glance/CancelParameter functions
This commit is contained in:
		| @@ -2,6 +2,7 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <boost/optional.hpp> | ||||
| #include "common/common_paths.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| @@ -44,7 +45,7 @@ static u8 unknown_ns_state_field; | ||||
| static ScreencapPostPermission screen_capture_post_permission; | ||||
|  | ||||
| /// Parameter data to be returned in the next call to Glance/ReceiveParameter | ||||
| static MessageParameter next_parameter; | ||||
| static boost::optional<MessageParameter> next_parameter; | ||||
|  | ||||
| void SendParameter(const MessageParameter& parameter) { | ||||
|     next_parameter = parameter; | ||||
| @@ -189,8 +190,20 @@ void SendParameter(Service::Interface* self) { | ||||
|     std::shared_ptr<HLE::Applets::Applet> dest_applet = | ||||
|         HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); | ||||
|  | ||||
|     LOG_DEBUG(Service_APT, | ||||
|               "called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," | ||||
|               "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", | ||||
|               src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
|  | ||||
|     // A new parameter can not be sent if the previous one hasn't been consumed yet | ||||
|     if (next_parameter) { | ||||
|         rb.Push(ResultCode(ErrCodes::ParameterPresent, ErrorModule::Applet, | ||||
|                            ErrorSummary::InvalidState, ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (dest_applet == nullptr) { | ||||
|         LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); | ||||
|         rb.Push<u32>(-1); // TODO(Subv): Find the right error code | ||||
| @@ -206,11 +219,6 @@ void SendParameter(Service::Interface* self) { | ||||
|     Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); | ||||
|  | ||||
|     rb.Push(dest_applet->ReceiveParameter(param)); | ||||
|  | ||||
|     LOG_WARNING(Service_APT, | ||||
|                 "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," | ||||
|                 "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", | ||||
|                 src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); | ||||
| } | ||||
|  | ||||
| void ReceiveParameter(Service::Interface* self) { | ||||
| @@ -226,21 +234,40 @@ void ReceiveParameter(Service::Interface* self) { | ||||
|             "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", | ||||
|             buffer_size, static_buff_size); | ||||
|  | ||||
|     LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); | ||||
|  | ||||
|     if (!next_parameter) { | ||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
|         rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, | ||||
|                            ErrorSummary::InvalidState, ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (next_parameter->destination_id != app_id) { | ||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
|         rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, | ||||
|                            ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); | ||||
|  | ||||
|     rb.Push(RESULT_SUCCESS); // No error | ||||
|     rb.Push(next_parameter.sender_id); | ||||
|     rb.Push(next_parameter.signal); // Signal type | ||||
|     ASSERT_MSG(next_parameter.buffer.size() <= buffer_size, "Input static buffer is too small !"); | ||||
|     rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size | ||||
|     rb.Push(next_parameter->sender_id); | ||||
|     rb.Push(next_parameter->signal); // Signal type | ||||
|     ASSERT_MSG(next_parameter->buffer.size() <= buffer_size, "Input static buffer is too small !"); | ||||
|     rb.Push(static_cast<u32>(next_parameter->buffer.size())); // Parameter buffer size | ||||
|  | ||||
|     rb.PushMoveHandles((next_parameter.object != nullptr) | ||||
|                            ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap() | ||||
|     rb.PushMoveHandles((next_parameter->object != nullptr) | ||||
|                            ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() | ||||
|                            : 0); | ||||
|     rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0); | ||||
|  | ||||
|     Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); | ||||
|     rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter->buffer.size()), 0); | ||||
|  | ||||
|     LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); | ||||
|     Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); | ||||
|  | ||||
|     // Clear the parameter | ||||
|     next_parameter = boost::none; | ||||
| } | ||||
|  | ||||
| void GlanceParameter(Service::Interface* self) { | ||||
| @@ -256,36 +283,73 @@ void GlanceParameter(Service::Interface* self) { | ||||
|             "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", | ||||
|             buffer_size, static_buff_size); | ||||
|  | ||||
|     LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); | ||||
|  | ||||
|     if (!next_parameter) { | ||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
|         rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, | ||||
|                            ErrorSummary::InvalidState, ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (next_parameter->destination_id != app_id) { | ||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||
|         rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, | ||||
|                            ErrorLevel::Status)); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); | ||||
|     rb.Push(RESULT_SUCCESS); // No error | ||||
|     rb.Push(next_parameter.sender_id); | ||||
|     rb.Push(next_parameter.signal); // Signal type | ||||
|     ASSERT_MSG(next_parameter.buffer.size() <= buffer_size, "Input static buffer is too small !"); | ||||
|     rb.Push(static_cast<u32>(next_parameter.buffer.size())); // Parameter buffer size | ||||
|     rb.Push(next_parameter->sender_id); | ||||
|     rb.Push(next_parameter->signal); // Signal type | ||||
|     ASSERT_MSG(next_parameter->buffer.size() <= buffer_size, "Input static buffer is too small !"); | ||||
|     rb.Push(static_cast<u32>(next_parameter->buffer.size())); // Parameter buffer size | ||||
|  | ||||
|     rb.PushCopyHandles((next_parameter.object != nullptr) | ||||
|                            ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap() | ||||
|     rb.PushMoveHandles((next_parameter->object != nullptr) | ||||
|                            ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() | ||||
|                            : 0); | ||||
|     rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter.buffer.size()), 0); | ||||
|  | ||||
|     Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); | ||||
|     rb.PushStaticBuffer(buffer, static_cast<u32>(next_parameter->buffer.size()), 0); | ||||
|  | ||||
|     LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); | ||||
|     Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); | ||||
|  | ||||
|     // Note: The NS module always clears the DSPSleep and DSPWakeup signals even in GlanceParameter. | ||||
|     if (next_parameter->signal == static_cast<u32>(SignalType::DspSleep) || | ||||
|         next_parameter->signal == static_cast<u32>(SignalType::DspWakeup)) | ||||
|         next_parameter = boost::none; | ||||
| } | ||||
|  | ||||
| void CancelParameter(Service::Interface* self) { | ||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xF, 4, 0); // 0xF0100 | ||||
|  | ||||
|     u32 check_sender = rp.Pop<u32>(); | ||||
|     bool check_sender = rp.Pop<bool>(); | ||||
|     u32 sender_appid = rp.Pop<u32>(); | ||||
|     u32 check_receiver = rp.Pop<u32>(); | ||||
|     bool check_receiver = rp.Pop<bool>(); | ||||
|     u32 receiver_appid = rp.Pop<u32>(); | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||
|     rb.Push(RESULT_SUCCESS); // No error | ||||
|     rb.Push(true);           // Set to Success | ||||
|  | ||||
|     LOG_WARNING(Service_APT, "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, " | ||||
|                              "check_receiver=0x%08X, receiver_appid=0x%08X", | ||||
|     bool cancellation_success = true; | ||||
|  | ||||
|     if (!next_parameter) { | ||||
|         cancellation_success = false; | ||||
|     } else { | ||||
|         if (check_sender && next_parameter->sender_id != sender_appid) | ||||
|             cancellation_success = false; | ||||
|  | ||||
|         if (check_receiver && next_parameter->destination_id != receiver_appid) | ||||
|             cancellation_success = false; | ||||
|     } | ||||
|  | ||||
|     if (cancellation_success) | ||||
|         next_parameter = boost::none; | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||
|  | ||||
|     rb.Push(RESULT_SUCCESS); // No error | ||||
|     rb.Push(cancellation_success); | ||||
|  | ||||
|     LOG_DEBUG(Service_APT, "called check_sender=%u, sender_appid=0x%08X, " | ||||
|                            "check_receiver=%u, receiver_appid=0x%08X", | ||||
|               check_sender, sender_appid, check_receiver, receiver_appid); | ||||
| } | ||||
|  | ||||
| @@ -800,8 +864,10 @@ void Init() { | ||||
|     notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); | ||||
|     parameter_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Start"); | ||||
|  | ||||
|     next_parameter.signal = static_cast<u32>(SignalType::Wakeup); | ||||
|     next_parameter.destination_id = 0x300; | ||||
|     // Initialize the parameter to wake up the application. | ||||
|     next_parameter.emplace(); | ||||
|     next_parameter->signal = static_cast<u32>(SignalType::Wakeup); | ||||
|     next_parameter->destination_id = static_cast<u32>(AppletId::Application); | ||||
| } | ||||
|  | ||||
| void Shutdown() { | ||||
| @@ -812,7 +878,7 @@ void Shutdown() { | ||||
|     notification_event = nullptr; | ||||
|     parameter_event = nullptr; | ||||
|  | ||||
|     next_parameter.object = nullptr; | ||||
|     next_parameter = boost::none; | ||||
|  | ||||
|     HLE::Applets::Shutdown(); | ||||
| } | ||||
|   | ||||
| @@ -116,6 +116,12 @@ enum class ScreencapPostPermission : u32 { | ||||
|     DisableScreenshotPostingToMiiverse = 3 | ||||
| }; | ||||
|  | ||||
| namespace ErrCodes { | ||||
| enum { | ||||
|     ParameterPresent = 2, | ||||
| }; | ||||
| } | ||||
|  | ||||
| /// Send a parameter to the currently-running application, which will read it via ReceiveParameter | ||||
| void SendParameter(const MessageParameter& parameter); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei