diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/apt/apt.cpp | 132 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt.h | 6 | 
2 files changed, 105 insertions, 33 deletions
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 5c44b43bb..4e6b7b6f5 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -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,37 +283,74 @@ 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>(); + +    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(true);           // Set to Success +    rb.Push(cancellation_success); -    LOG_WARNING(Service_APT, "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, " -                             "check_receiver=0x%08X, receiver_appid=0x%08X", -                check_sender, sender_appid, check_receiver, receiver_appid); +    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);  }  void PrepareToStartApplication(Service::Interface* self) { @@ -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();  } diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index ee80926d2..106754853 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -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);  | 
