diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4afeec200..d5b78b29d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -274,8 +274,6 @@ add_library(core STATIC hle/service/mvd/mvd.h hle/service/mvd/mvd_std.cpp hle/service/mvd/mvd_std.h - hle/service/ndm/ndm.cpp - hle/service/ndm/ndm.h hle/service/ndm/ndm_u.cpp hle/service/ndm/ndm_u.h hle/service/news/news.cpp diff --git a/src/core/hle/service/ndm/ndm.cpp b/src/core/hle/service/ndm/ndm.cpp deleted file mode 100644 index 8a5647072..000000000 --- a/src/core/hle/service/ndm/ndm.cpp +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/hle/ipc.h" -#include "core/hle/service/ndm/ndm.h" -#include "core/hle/service/ndm/ndm_u.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace NDM { - -enum : u32 { - DEFAULT_RETRY_INTERVAL = 10, - DEFAULT_SCAN_INTERVAL = 30, -}; - -static DaemonMask daemon_bit_mask = DaemonMask::Default; -static DaemonMask default_daemon_bit_mask = DaemonMask::Default; -static std::array daemon_status = { - DaemonStatus::Idle, - DaemonStatus::Idle, - DaemonStatus::Idle, - DaemonStatus::Idle, -}; -static ExclusiveState exclusive_state = ExclusiveState::None; -static u32 scan_interval = DEFAULT_SCAN_INTERVAL; -static u32 retry_interval = DEFAULT_RETRY_INTERVAL; -static bool daemon_lock_enabled = false; - -void EnterExclusiveState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - exclusive_state = static_cast(cmd_buff[1]); - - cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x%08X", static_cast(exclusive_state)); -} - -void LeaveExclusiveState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - exclusive_state = ExclusiveState::None; - - cmd_buff[0] = IPC::MakeHeader(0x2, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x%08X", static_cast(exclusive_state)); -} - -void QueryExclusiveMode(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x3, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast(exclusive_state); - LOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x%08X", static_cast(exclusive_state)); -} - -void LockState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - daemon_lock_enabled = true; - - cmd_buff[0] = IPC::MakeHeader(0x4, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void UnlockState(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - daemon_lock_enabled = false; - - cmd_buff[0] = IPC::MakeHeader(0x5, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void SuspendDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 bit_mask = cmd_buff[1] & 0xF; - daemon_bit_mask = - static_cast(static_cast(default_daemon_bit_mask) & ~bit_mask); - for (size_t index = 0; index < daemon_status.size(); ++index) { - if (bit_mask & (1 << index)) { - daemon_status[index] = DaemonStatus::Suspended; - } - } - - cmd_buff[0] = IPC::MakeHeader(0x6, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) daemon_bit_mask=0x%08X", static_cast(daemon_bit_mask)); -} - -void ResumeDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 bit_mask = cmd_buff[1] & 0xF; - daemon_bit_mask = static_cast(static_cast(daemon_bit_mask) | bit_mask); - for (size_t index = 0; index < daemon_status.size(); ++index) { - if (bit_mask & (1 << index)) { - daemon_status[index] = DaemonStatus::Idle; - } - } - - cmd_buff[0] = IPC::MakeHeader(0x7, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) daemon_bit_mask=0x%08X", static_cast(daemon_bit_mask)); -} - -void SuspendScheduler(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x8, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void ResumeScheduler(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void QueryStatus(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 daemon = cmd_buff[1] & 0xF; - - cmd_buff[0] = IPC::MakeHeader(0xD, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast(daemon_status.at(daemon)); - LOG_WARNING(Service_NDM, "(STUBBED) daemon=0x%08X, daemon_status=0x%08X", daemon, cmd_buff[2]); -} - -void GetDaemonDisableCount(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 daemon = cmd_buff[1] & 0xF; - - cmd_buff[0] = IPC::MakeHeader(0xE, 3, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; - cmd_buff[3] = 0; - LOG_WARNING(Service_NDM, "(STUBBED) daemon=0x%08X", daemon); -} - -void GetSchedulerDisableCount(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0xF, 3, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = 0; - cmd_buff[3] = 0; - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void SetScanInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - scan_interval = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) scan_interval=0x%08X", scan_interval); -} - -void GetScanInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x11, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = scan_interval; - LOG_WARNING(Service_NDM, "(STUBBED) scan_interval=0x%08X", scan_interval); -} - -void SetRetryInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - retry_interval = cmd_buff[1]; - - cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) retry_interval=0x%08X", retry_interval); -} - -void GetRetryInterval(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x13, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = retry_interval; - LOG_WARNING(Service_NDM, "(STUBBED) retry_interval=0x%08X", retry_interval); -} - -void OverrideDefaultDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 bit_mask = cmd_buff[1] & 0xF; - default_daemon_bit_mask = static_cast(bit_mask); - daemon_bit_mask = default_daemon_bit_mask; - for (size_t index = 0; index < daemon_status.size(); ++index) { - if (bit_mask & (1 << index)) { - daemon_status[index] = DaemonStatus::Idle; - } - } - - cmd_buff[0] = IPC::MakeHeader(0x14, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) default_daemon_bit_mask=0x%08X ", - static_cast(default_daemon_bit_mask)); -} - -void ResetDefaultDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - default_daemon_bit_mask = DaemonMask::Default; - - cmd_buff[0] = IPC::MakeHeader(0x15, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) default_daemon_bit_mask=0x%08X", - static_cast(default_daemon_bit_mask)); -} - -void GetDefaultDaemons(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x16, 2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - cmd_buff[2] = static_cast(default_daemon_bit_mask); - LOG_WARNING(Service_NDM, "(STUBBED) default_daemon_bit_mask=0x%08X", - static_cast(default_daemon_bit_mask)); -} - -void ClearHalfAwakeMacFilter(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - - cmd_buff[0] = IPC::MakeHeader(0x17, 1, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_NDM, "(STUBBED) called"); -} - -void Init() { - AddService(new NDM_U_Interface); -} - -void Shutdown() {} - -} // namespace NDM -} // namespace Service diff --git a/src/core/hle/service/ndm/ndm.h b/src/core/hle/service/ndm/ndm.h deleted file mode 100644 index 979e7fcf1..000000000 --- a/src/core/hle/service/ndm/ndm.h +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -namespace Service { - -class Interface; - -namespace NDM { - -enum class Daemon : u32 { - Cec = 0, - Boss = 1, - Nim = 2, - Friend = 3, -}; - -enum class DaemonMask : u32 { - None = 0, - Cec = (1 << static_cast(Daemon::Cec)), - Boss = (1 << static_cast(Daemon::Boss)), - Nim = (1 << static_cast(Daemon::Nim)), - Friend = (1 << static_cast(Daemon::Friend)), - Default = Cec | Friend, - All = Cec | Boss | Nim | Friend, -}; - -enum class DaemonStatus : u32 { Busy = 0, Idle = 1, Suspending = 2, Suspended = 3 }; - -enum class ExclusiveState : u32 { - None = 0, - Infrastructure = 1, - LocalCommunications = 2, - Streetpass = 3, - StreetpassData = 4, -}; - -/** - * NDM::EnterExclusiveState service function - * Inputs: - * 0 : Header code [0x00010042] - * 1 : Exclusive State - * 2 : 0x20 - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void EnterExclusiveState(Service::Interface* self); - -/** - * NDM::LeaveExclusiveState service function - * Inputs: - * 0 : Header code [0x00020002] - * 1 : 0x20 - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void LeaveExclusiveState(Service::Interface* self); - -/** - * NDM::QueryExclusiveMode service function - * Inputs: - * 0 : Header code [0x00030000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Current Exclusive State - */ -void QueryExclusiveMode(Service::Interface* self); - -/** - * NDM::LockState service function - * Inputs: - * 0 : Header code [0x00040002] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void LockState(Service::Interface* self); - -/** - * NDM::UnlockState service function - * Inputs: - * 0 : Header code [0x00050002] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void UnlockState(Service::Interface* self); - -/** - * NDM::SuspendDaemons service function - * Inputs: - * 0 : Header code [0x00060040] - * 1 : Daemon bit mask - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SuspendDaemons(Service::Interface* self); - -/** - * NDM::ResumeDaemons service function - * Inputs: - * 0 : Header code [0x00070040] - * 1 : Daemon bit mask - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ResumeDaemons(Service::Interface* self); - -/** - * NDM::SuspendScheduler service function - * Inputs: - * 0 : Header code [0x00080040] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SuspendScheduler(Service::Interface* self); - -/** - * NDM::ResumeScheduler service function - * Inputs: - * 0 : Header code [0x00090000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ResumeScheduler(Service::Interface* self); - -/** - * NDM::QueryStatus service function - * Inputs: - * 0 : Header code [0x000D0040] - * 1 : Daemon - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Daemon status - */ -void QueryStatus(Service::Interface* self); - -/** - * NDM::GetDaemonDisableCount service function - * Inputs: - * 0 : Header code [0x000E0040] - * 1 : Daemon - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Current process disable count - * 3 : Total disable count - */ -void GetDaemonDisableCount(Service::Interface* self); - -/** - * NDM::GetSchedulerDisableCount service function - * Inputs: - * 0 : Header code [0x000F0000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Current process disable count - * 3 : Total disable count - */ -void GetSchedulerDisableCount(Service::Interface* self); - -/** - * NDM::SetScanInterval service function - * Inputs: - * 0 : Header code [0x00100040] - * 1 : Interval (default = 30) - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SetScanInterval(Service::Interface* self); - -/** - * NDM::GetScanInterval service function - * Inputs: - * 0 : Header code [0x00110000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Interval (default = 30) - */ -void GetScanInterval(Service::Interface* self); - -/** - * NDM::SetRetryInterval service function - * Inputs: - * 0 : Header code [0x00120040] - * 1 : Interval (default = 10) - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void SetRetryInterval(Service::Interface* self); - -/** - * NDM::GetRetryInterval service function - * Inputs: - * 0 : Header code [0x00130000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Interval (default = 10) - */ -void GetRetryInterval(Service::Interface* self); - -/** - * NDM::OverrideDefaultDaemons service function - * Inputs: - * 0 : Header code [0x00140040] - * 1 : Daemon bit mask - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void OverrideDefaultDaemons(Service::Interface* self); - -/** - * NDM::ResetDefaultDaemons service function - * Inputs: - * 0 : Header code [0x00150000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ResetDefaultDaemons(Service::Interface* self); - -/** - * NDM::GetDefaultDaemons service function - * Inputs: - * 0 : Header code [0x00160000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - * 2 : Daemon bit mask - * Note: - * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | - * DAEMONMASK_FRIENDS) - */ -void GetDefaultDaemons(Service::Interface* self); - -/** - * NDM::ClearHalfAwakeMacFilter service function - * Inputs: - * 0 : Header code [0x00170000] - * Outputs: - * 1 : Result, 0 on success, otherwise error code - */ -void ClearHalfAwakeMacFilter(Service::Interface* self); - -/// Initialize NDM service -void Init(); - -/// Shutdown NDM service -void Shutdown(); - -} // namespace NDM -} // namespace Service diff --git a/src/core/hle/service/ndm/ndm_u.cpp b/src/core/hle/service/ndm/ndm_u.cpp index f5c7a341a..7afea5399 100644 --- a/src/core/hle/service/ndm/ndm_u.cpp +++ b/src/core/hle/service/ndm/ndm_u.cpp @@ -2,40 +2,243 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/ndm/ndm.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/service/ndm/ndm_u.h" namespace Service { namespace NDM { -const Interface::FunctionInfo FunctionTable[] = { - {0x00010042, EnterExclusiveState, "EnterExclusiveState"}, - {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"}, - {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"}, - {0x00040002, LockState, "LockState"}, - {0x00050002, UnlockState, "UnlockState"}, - {0x00060040, SuspendDaemons, "SuspendDaemons"}, - {0x00070040, ResumeDaemons, "ResumeDaemons"}, - {0x00080040, SuspendScheduler, "SuspendScheduler"}, - {0x00090000, ResumeScheduler, "ResumeScheduler"}, - {0x000A0000, nullptr, "GetCurrentState"}, - {0x000B0000, nullptr, "GetTargetState"}, - {0x000C0000, nullptr, ""}, - {0x000D0040, QueryStatus, "QueryStatus"}, - {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"}, - {0x000F0000, GetSchedulerDisableCount, "GetSchedulerDisableCount"}, - {0x00100040, SetScanInterval, "SetScanInterval"}, - {0x00110000, GetScanInterval, "GetScanInterval"}, - {0x00120040, SetRetryInterval, "SetRetryInterval"}, - {0x00130000, GetRetryInterval, "GetRetryInterval"}, - {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"}, - {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"}, - {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"}, - {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"}, -}; +void NDM_U::EnterExclusiveState(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x01, 1, 2); + exclusive_state = rp.PopEnum(); + rp.PopPID(); -NDM_U_Interface::NDM_U_Interface() { - Register(FunctionTable); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x{:08X}", + static_cast(exclusive_state)); +} + +void NDM_U::LeaveExclusiveState(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x02, 0, 2); + rp.PopPID(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::QueryExclusiveMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x03, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.PushEnum(exclusive_state); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::LockState(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x04, 0, 2); + rp.PopPID(); + daemon_lock_enabled = true; + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::UnlockState(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x05, 0, 2); + rp.PopPID(); + daemon_lock_enabled = false; + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::SuspendDaemons(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x06, 1, 0); + u32 bit_mask = rp.Pop() & 0xF; + daemon_bit_mask = + static_cast(static_cast(default_daemon_bit_mask) & ~bit_mask); + for (std::size_t index = 0; index < daemon_status.size(); ++index) { + if (bit_mask & (1 << index)) { + daemon_status[index] = DaemonStatus::Suspended; + } + } + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x{:08X}", bit_mask); +} + +void NDM_U::ResumeDaemons(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x07, 1, 0); + u32 bit_mask = rp.Pop() & 0xF; + daemon_bit_mask = static_cast(static_cast(daemon_bit_mask) & ~bit_mask); + for (std::size_t index = 0; index < daemon_status.size(); ++index) { + if (bit_mask & (1 << index)) { + daemon_status[index] = DaemonStatus::Idle; + } + } + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x{:08X}", bit_mask); +} + +void NDM_U::SuspendScheduler(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x08, 1, 0); + bool perform_in_background = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED) perform_in_background={}", perform_in_background); +} + +void NDM_U::ResumeScheduler(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x09, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::QueryStatus(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x0D, 1, 0); + u8 daemon = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.PushEnum(daemon_status.at(daemon)); + NGLOG_WARNING(Service_NDM, "(STUBBED) daemon=0x{:02X}", daemon); +} + +void NDM_U::GetDaemonDisableCount(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x0E, 1, 0); + u8 daemon = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(0); // current process disable count + rb.Push(0); // total disable count + NGLOG_WARNING(Service_NDM, "(STUBBED) daemon=0x{:02X}", daemon); +} + +void NDM_U::GetSchedulerDisableCount(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x0F, 0, 0); + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(0); // current process disable count + rb.Push(0); // total disable count + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::SetScanInterval(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x10, 1, 0); + scan_interval = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED) scan_interval=0x{:08X}", scan_interval); +} + +void NDM_U::GetScanInterval(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x11, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(scan_interval); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::SetRetryInterval(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x12, 1, 0); + retry_interval = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED) retry_interval=0x{:08X}", retry_interval); +} + +void NDM_U::GetRetryInterval(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x13, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(retry_interval); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::OverrideDefaultDaemons(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x14, 1, 0); + u32 bit_mask = rp.Pop() & 0xF; + default_daemon_bit_mask = static_cast(bit_mask); + daemon_bit_mask = default_daemon_bit_mask; + for (std::size_t index = 0; index < daemon_status.size(); ++index) { + if (bit_mask & (1 << index)) { + daemon_status[index] = DaemonStatus::Idle; + } + } + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x{:08X}", bit_mask); +} + +void NDM_U::ResetDefaultDaemons(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x15, 0, 0); + default_daemon_bit_mask = DaemonMask::Default; + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::GetDefaultDaemons(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x16, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.PushEnum(default_daemon_bit_mask); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +void NDM_U::ClearHalfAwakeMacFilter(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x17, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + NGLOG_WARNING(Service_NDM, "(STUBBED)"); +} + +NDM_U::NDM_U() : ServiceFramework("ndm:u", 6) { + static const FunctionInfo functions[] = { + {0x00010042, &NDM_U::EnterExclusiveState, "EnterExclusiveState"}, + {0x00020002, &NDM_U::LeaveExclusiveState, "LeaveExclusiveState"}, + {0x00030000, &NDM_U::QueryExclusiveMode, "QueryExclusiveMode"}, + {0x00040002, &NDM_U::LockState, "LockState"}, + {0x00050002, &NDM_U::UnlockState, "UnlockState"}, + {0x00060040, &NDM_U::SuspendDaemons, "SuspendDaemons"}, + {0x00070040, &NDM_U::ResumeDaemons, "ResumeDaemons"}, + {0x00080040, &NDM_U::SuspendScheduler, "SuspendScheduler"}, + {0x00090000, &NDM_U::ResumeScheduler, "ResumeScheduler"}, + {0x000A0000, nullptr, "GetCurrentState"}, + {0x000B0000, nullptr, "GetTargetState"}, + {0x000C0000, nullptr, ""}, + {0x000D0040, &NDM_U::QueryStatus, "QueryStatus"}, + {0x000E0040, &NDM_U::GetDaemonDisableCount, "GetDaemonDisableCount"}, + {0x000F0000, &NDM_U::GetSchedulerDisableCount, "GetSchedulerDisableCount"}, + {0x00100040, &NDM_U::SetScanInterval, "SetScanInterval"}, + {0x00110000, &NDM_U::GetScanInterval, "GetScanInterval"}, + {0x00120040, &NDM_U::SetRetryInterval, "SetRetryInterval"}, + {0x00130000, &NDM_U::GetRetryInterval, "GetRetryInterval"}, + {0x00140040, &NDM_U::OverrideDefaultDaemons, "OverrideDefaultDaemons"}, + {0x00150000, &NDM_U::ResetDefaultDaemons, "ResetDefaultDaemons"}, + {0x00160000, &NDM_U::GetDefaultDaemons, "GetDefaultDaemons"}, + {0x00170000, &NDM_U::ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"}, + }; + RegisterHandlers(functions); +} + +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared()->InstallAsService(service_manager); } } // namespace NDM diff --git a/src/core/hle/service/ndm/ndm_u.h b/src/core/hle/service/ndm/ndm_u.h index d567abc84..cfac12620 100644 --- a/src/core/hle/service/ndm/ndm_u.h +++ b/src/core/hle/service/ndm/ndm_u.h @@ -4,19 +4,272 @@ #pragma once +#include #include "core/hle/service/service.h" namespace Service { namespace NDM { -class NDM_U_Interface : public Service::Interface { +class NDM_U final : public ServiceFramework { public: - NDM_U_Interface(); + NDM_U(); - std::string GetPortName() const override { - return "ndm:u"; - } +private: + /** + * NDM::EnterExclusiveState service function + * Inputs: + * 0 : Header code [0x00010042] + * 1 : Exclusive State + * 2 : 0x20 + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void EnterExclusiveState(Kernel::HLERequestContext& ctx); + + /** + * NDM::LeaveExclusiveState service function + * Inputs: + * 0 : Header code [0x00020002] + * 1 : 0x20 + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void LeaveExclusiveState(Kernel::HLERequestContext& ctx); + + /** + * NDM::QueryExclusiveMode service function + * Inputs: + * 0 : Header code [0x00030000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : Current Exclusive State + */ + void QueryExclusiveMode(Kernel::HLERequestContext& ctx); + + /** + * NDM::LockState service function + * Inputs: + * 0 : Header code [0x00040002] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void LockState(Kernel::HLERequestContext& ctx); + + /** + * NDM::UnlockState service function + * Inputs: + * 0 : Header code [0x00050002] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void UnlockState(Kernel::HLERequestContext& ctx); + + /** + * NDM::SuspendDaemons service function + * Inputs: + * 0 : Header code [0x00060040] + * 1 : Daemon bit mask + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void SuspendDaemons(Kernel::HLERequestContext& ctx); + + /** + * NDM::ResumeDaemons service function + * Inputs: + * 0 : Header code [0x00070040] + * 1 : Daemon bit mask + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void ResumeDaemons(Kernel::HLERequestContext& ctx); + + /** + * NDM::SuspendScheduler service function + * Inputs: + * 0 : Header code [0x00080040] + * 1 : (u8/bool) 0 = Wait for completion, 1 = Perform in background + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void SuspendScheduler(Kernel::HLERequestContext& ctx); + + /** + * NDM::ResumeScheduler service function + * Inputs: + * 0 : Header code [0x00090000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void ResumeScheduler(Kernel::HLERequestContext& ctx); + + /** + * NDM::QueryStatus service function + * Inputs: + * 0 : Header code [0x000D0040] + * 1 : Daemon + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : Daemon status + */ + void QueryStatus(Kernel::HLERequestContext& ctx); + + /** + * NDM::GetDaemonDisableCount service function + * Inputs: + * 0 : Header code [0x000E0040] + * 1 : Daemon + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : Current process disable count + * 3 : Total disable count + */ + void GetDaemonDisableCount(Kernel::HLERequestContext& ctx); + + /** + * NDM::GetSchedulerDisableCount service function + * Inputs: + * 0 : Header code [0x000F0000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : Current process disable count + * 3 : Total disable count + */ + void GetSchedulerDisableCount(Kernel::HLERequestContext& ctx); + + /** + * NDM::SetScanInterval service function + * Inputs: + * 0 : Header code [0x00100040] + * 1 : Interval (default = 30) + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void SetScanInterval(Kernel::HLERequestContext& ctx); + + /** + * NDM::GetScanInterval service function + * Inputs: + * 0 : Header code [0x00110000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : Interval (default = 30) + */ + void GetScanInterval(Kernel::HLERequestContext& ctx); + + /** + * NDM::SetRetryInterval service function + * Inputs: + * 0 : Header code [0x00120040] + * 1 : Interval (default = 10) + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void SetRetryInterval(Kernel::HLERequestContext& ctx); + + /** + * NDM::GetRetryInterval service function + * Inputs: + * 0 : Header code [0x00130000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : Interval (default = 10) + */ + void GetRetryInterval(Kernel::HLERequestContext& ctx); + + /** + * NDM::OverrideDefaultDaemons service function + * Inputs: + * 0 : Header code [0x00140040] + * 1 : Daemon bit mask + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void OverrideDefaultDaemons(Kernel::HLERequestContext& ctx); + + /** + * NDM::ResetDefaultDaemons service function + * Inputs: + * 0 : Header code [0x00150000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void ResetDefaultDaemons(Kernel::HLERequestContext& ctx); + + /** + * NDM::GetDefaultDaemons service function + * Inputs: + * 0 : Header code [0x00160000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + * 2 : Daemon bit mask + * Note: + * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | + * DAEMONMASK_FRIENDS) + */ + void GetDefaultDaemons(Kernel::HLERequestContext& ctx); + + /** + * NDM::ClearHalfAwakeMacFilter service function + * Inputs: + * 0 : Header code [0x00170000] + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ + void ClearHalfAwakeMacFilter(Kernel::HLERequestContext& ctx); + + enum class Daemon : u32 { + Cec = 0, + Boss = 1, + Nim = 2, + Friend = 3, + }; + + enum class DaemonMask : u32 { + None = 0, + Cec = (1 << static_cast(Daemon::Cec)), + Boss = (1 << static_cast(Daemon::Boss)), + Nim = (1 << static_cast(Daemon::Nim)), + Friend = (1 << static_cast(Daemon::Friend)), + Default = Cec | Friend, + All = Cec | Boss | Nim | Friend, + }; + + enum class DaemonStatus : u32 { + Busy = 0, + Idle = 1, + Suspending = 2, + Suspended = 3, + }; + + enum class ExclusiveState : u32 { + None = 0, + Infrastructure = 1, + LocalCommunications = 2, + Streetpass = 3, + StreetpassData = 4, + }; + + enum : u32 { + DEFAULT_RETRY_INTERVAL = 10, + DEFAULT_SCAN_INTERVAL = 30, + }; + + DaemonMask daemon_bit_mask = DaemonMask::Default; + DaemonMask default_daemon_bit_mask = DaemonMask::Default; + std::array daemon_status = { + DaemonStatus::Idle, + DaemonStatus::Idle, + DaemonStatus::Idle, + DaemonStatus::Idle, + }; + ExclusiveState exclusive_state = ExclusiveState::None; + u32 scan_interval = DEFAULT_SCAN_INTERVAL; + u32 retry_interval = DEFAULT_RETRY_INTERVAL; + bool daemon_lock_enabled = false; }; +void InstallInterfaces(SM::ServiceManager& service_manager); + } // namespace NDM } // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 813893985..55eb8e5eb 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -37,7 +37,7 @@ #include "core/hle/service/ldr_ro/ldr_ro.h" #include "core/hle/service/mic_u.h" #include "core/hle/service/mvd/mvd.h" -#include "core/hle/service/ndm/ndm.h" +#include "core/hle/service/ndm/ndm_u.h" #include "core/hle/service/news/news.h" #include "core/hle/service/nfc/nfc.h" #include "core/hle/service/nim/nim.h" @@ -250,7 +250,7 @@ void Init(std::shared_ptr& sm) { HID::InstallInterfaces(*sm); IR::InstallInterfaces(*sm); MVD::Init(); - NDM::Init(); + NDM::InstallInterfaces(*sm); NEWS::InstallInterfaces(*sm); NFC::InstallInterfaces(*sm); NIM::InstallInterfaces(*sm); @@ -272,7 +272,6 @@ void Init(std::shared_ptr& sm) { /// Shutdown ServiceManager void Shutdown() { - NDM::Shutdown(); DLP::Shutdown(); CECD::Shutdown(); BOSS::Shutdown();