1 // Copyright 2014 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #include "common/archives.h"
6 #include "core/core.h"
7 #include "core/hle/ipc_helpers.h"
8 #include "core/hle/service/ndm/ndm_u.h"
9 
10 SERIALIZE_EXPORT_IMPL(Service::NDM::NDM_U)
11 
12 namespace Service::NDM {
13 
EnterExclusiveState(Kernel::HLERequestContext & ctx)14 void NDM_U::EnterExclusiveState(Kernel::HLERequestContext& ctx) {
15     IPC::RequestParser rp(ctx, 0x01, 1, 2);
16     exclusive_state = rp.PopEnum<ExclusiveState>();
17     rp.PopPID();
18 
19     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
20     rb.Push(RESULT_SUCCESS);
21     LOG_WARNING(Service_NDM, "(STUBBED) exclusive_state=0x{:08X}", exclusive_state);
22 }
23 
LeaveExclusiveState(Kernel::HLERequestContext & ctx)24 void NDM_U::LeaveExclusiveState(Kernel::HLERequestContext& ctx) {
25     IPC::RequestParser rp(ctx, 0x02, 0, 2);
26     rp.PopPID();
27 
28     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
29     rb.Push(RESULT_SUCCESS);
30     LOG_WARNING(Service_NDM, "(STUBBED)");
31 }
32 
QueryExclusiveMode(Kernel::HLERequestContext & ctx)33 void NDM_U::QueryExclusiveMode(Kernel::HLERequestContext& ctx) {
34     IPC::RequestParser rp(ctx, 0x03, 0, 0);
35     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
36     rb.Push(RESULT_SUCCESS);
37     rb.PushEnum(exclusive_state);
38     LOG_WARNING(Service_NDM, "(STUBBED)");
39 }
40 
LockState(Kernel::HLERequestContext & ctx)41 void NDM_U::LockState(Kernel::HLERequestContext& ctx) {
42     IPC::RequestParser rp(ctx, 0x04, 0, 2);
43     rp.PopPID();
44     daemon_lock_enabled = true;
45 
46     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
47     rb.Push(RESULT_SUCCESS);
48     LOG_WARNING(Service_NDM, "(STUBBED)");
49 }
50 
UnlockState(Kernel::HLERequestContext & ctx)51 void NDM_U::UnlockState(Kernel::HLERequestContext& ctx) {
52     IPC::RequestParser rp(ctx, 0x05, 0, 2);
53     rp.PopPID();
54     daemon_lock_enabled = false;
55 
56     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
57     rb.Push(RESULT_SUCCESS);
58     LOG_WARNING(Service_NDM, "(STUBBED)");
59 }
60 
SuspendDaemons(Kernel::HLERequestContext & ctx)61 void NDM_U::SuspendDaemons(Kernel::HLERequestContext& ctx) {
62     IPC::RequestParser rp(ctx, 0x06, 1, 0);
63     u32 bit_mask = rp.Pop<u32>() & 0xF;
64     daemon_bit_mask =
65         static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask);
66     for (std::size_t index = 0; index < daemon_status.size(); ++index) {
67         if (bit_mask & (1 << index)) {
68             daemon_status[index] = DaemonStatus::Suspended;
69         }
70     }
71 
72     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
73     rb.Push(RESULT_SUCCESS);
74     LOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x{:08X}", bit_mask);
75 }
76 
ResumeDaemons(Kernel::HLERequestContext & ctx)77 void NDM_U::ResumeDaemons(Kernel::HLERequestContext& ctx) {
78     IPC::RequestParser rp(ctx, 0x07, 1, 0);
79     u32 bit_mask = rp.Pop<u32>() & 0xF;
80     daemon_bit_mask = static_cast<DaemonMask>(static_cast<u32>(daemon_bit_mask) & ~bit_mask);
81     for (std::size_t index = 0; index < daemon_status.size(); ++index) {
82         if (bit_mask & (1 << index)) {
83             daemon_status[index] = DaemonStatus::Idle;
84         }
85     }
86 
87     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
88     rb.Push(RESULT_SUCCESS);
89     LOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x{:08X}", bit_mask);
90 }
91 
SuspendScheduler(Kernel::HLERequestContext & ctx)92 void NDM_U::SuspendScheduler(Kernel::HLERequestContext& ctx) {
93     IPC::RequestParser rp(ctx, 0x08, 1, 0);
94     bool perform_in_background = rp.Pop<bool>();
95 
96     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
97     rb.Push(RESULT_SUCCESS);
98     LOG_WARNING(Service_NDM, "(STUBBED) perform_in_background={}", perform_in_background);
99 }
100 
ResumeScheduler(Kernel::HLERequestContext & ctx)101 void NDM_U::ResumeScheduler(Kernel::HLERequestContext& ctx) {
102     IPC::RequestParser rp(ctx, 0x09, 0, 0);
103     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
104     rb.Push(RESULT_SUCCESS);
105     LOG_WARNING(Service_NDM, "(STUBBED)");
106 }
107 
QueryStatus(Kernel::HLERequestContext & ctx)108 void NDM_U::QueryStatus(Kernel::HLERequestContext& ctx) {
109     IPC::RequestParser rp(ctx, 0x0D, 1, 0);
110     u8 daemon = rp.Pop<u8>();
111 
112     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
113     rb.Push(RESULT_SUCCESS);
114     rb.PushEnum(daemon_status.at(daemon));
115     LOG_WARNING(Service_NDM, "(STUBBED) daemon=0x{:02X}", daemon);
116 }
117 
GetDaemonDisableCount(Kernel::HLERequestContext & ctx)118 void NDM_U::GetDaemonDisableCount(Kernel::HLERequestContext& ctx) {
119     IPC::RequestParser rp(ctx, 0x0E, 1, 0);
120     u8 daemon = rp.Pop<u8>();
121 
122     IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
123     rb.Push(RESULT_SUCCESS);
124     rb.Push<u32>(0); // current process disable count
125     rb.Push<u32>(0); // total disable count
126     LOG_WARNING(Service_NDM, "(STUBBED) daemon=0x{:02X}", daemon);
127 }
128 
GetSchedulerDisableCount(Kernel::HLERequestContext & ctx)129 void NDM_U::GetSchedulerDisableCount(Kernel::HLERequestContext& ctx) {
130     IPC::RequestParser rp(ctx, 0x0F, 0, 0);
131 
132     IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
133     rb.Push(RESULT_SUCCESS);
134     rb.Push<u32>(0); // current process disable count
135     rb.Push<u32>(0); // total disable count
136     LOG_WARNING(Service_NDM, "(STUBBED)");
137 }
138 
SetScanInterval(Kernel::HLERequestContext & ctx)139 void NDM_U::SetScanInterval(Kernel::HLERequestContext& ctx) {
140     IPC::RequestParser rp(ctx, 0x10, 1, 0);
141     scan_interval = rp.Pop<u32>();
142 
143     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
144     rb.Push(RESULT_SUCCESS);
145     LOG_WARNING(Service_NDM, "(STUBBED) scan_interval=0x{:08X}", scan_interval);
146 }
147 
GetScanInterval(Kernel::HLERequestContext & ctx)148 void NDM_U::GetScanInterval(Kernel::HLERequestContext& ctx) {
149     IPC::RequestParser rp(ctx, 0x11, 0, 0);
150     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
151     rb.Push(RESULT_SUCCESS);
152     rb.Push(scan_interval);
153     LOG_WARNING(Service_NDM, "(STUBBED)");
154 }
155 
SetRetryInterval(Kernel::HLERequestContext & ctx)156 void NDM_U::SetRetryInterval(Kernel::HLERequestContext& ctx) {
157     IPC::RequestParser rp(ctx, 0x12, 1, 0);
158     retry_interval = rp.Pop<u32>();
159 
160     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
161     rb.Push(RESULT_SUCCESS);
162     LOG_WARNING(Service_NDM, "(STUBBED) retry_interval=0x{:08X}", retry_interval);
163 }
164 
GetRetryInterval(Kernel::HLERequestContext & ctx)165 void NDM_U::GetRetryInterval(Kernel::HLERequestContext& ctx) {
166     IPC::RequestParser rp(ctx, 0x13, 0, 0);
167     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
168     rb.Push(RESULT_SUCCESS);
169     rb.Push(retry_interval);
170     LOG_WARNING(Service_NDM, "(STUBBED)");
171 }
172 
OverrideDefaultDaemons(Kernel::HLERequestContext & ctx)173 void NDM_U::OverrideDefaultDaemons(Kernel::HLERequestContext& ctx) {
174     IPC::RequestParser rp(ctx, 0x14, 1, 0);
175     u32 bit_mask = rp.Pop<u32>() & 0xF;
176     default_daemon_bit_mask = static_cast<DaemonMask>(bit_mask);
177     daemon_bit_mask = default_daemon_bit_mask;
178     for (std::size_t index = 0; index < daemon_status.size(); ++index) {
179         if (bit_mask & (1 << index)) {
180             daemon_status[index] = DaemonStatus::Idle;
181         }
182     }
183 
184     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
185     rb.Push(RESULT_SUCCESS);
186     LOG_WARNING(Service_NDM, "(STUBBED) bit_mask=0x{:08X}", bit_mask);
187 }
188 
ResetDefaultDaemons(Kernel::HLERequestContext & ctx)189 void NDM_U::ResetDefaultDaemons(Kernel::HLERequestContext& ctx) {
190     IPC::RequestParser rp(ctx, 0x15, 0, 0);
191     default_daemon_bit_mask = DaemonMask::Default;
192 
193     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
194     rb.Push(RESULT_SUCCESS);
195     LOG_WARNING(Service_NDM, "(STUBBED)");
196 }
197 
GetDefaultDaemons(Kernel::HLERequestContext & ctx)198 void NDM_U::GetDefaultDaemons(Kernel::HLERequestContext& ctx) {
199     IPC::RequestParser rp(ctx, 0x16, 0, 0);
200     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
201     rb.Push(RESULT_SUCCESS);
202     rb.PushEnum(default_daemon_bit_mask);
203     LOG_WARNING(Service_NDM, "(STUBBED)");
204 }
205 
ClearHalfAwakeMacFilter(Kernel::HLERequestContext & ctx)206 void NDM_U::ClearHalfAwakeMacFilter(Kernel::HLERequestContext& ctx) {
207     IPC::RequestParser rp(ctx, 0x17, 0, 0);
208     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
209     rb.Push(RESULT_SUCCESS);
210     LOG_WARNING(Service_NDM, "(STUBBED)");
211 }
212 
NDM_U()213 NDM_U::NDM_U() : ServiceFramework("ndm:u", 6) {
214     static const FunctionInfo functions[] = {
215         {0x00010042, &NDM_U::EnterExclusiveState, "EnterExclusiveState"},
216         {0x00020002, &NDM_U::LeaveExclusiveState, "LeaveExclusiveState"},
217         {0x00030000, &NDM_U::QueryExclusiveMode, "QueryExclusiveMode"},
218         {0x00040002, &NDM_U::LockState, "LockState"},
219         {0x00050002, &NDM_U::UnlockState, "UnlockState"},
220         {0x00060040, &NDM_U::SuspendDaemons, "SuspendDaemons"},
221         {0x00070040, &NDM_U::ResumeDaemons, "ResumeDaemons"},
222         {0x00080040, &NDM_U::SuspendScheduler, "SuspendScheduler"},
223         {0x00090000, &NDM_U::ResumeScheduler, "ResumeScheduler"},
224         {0x000A0000, nullptr, "GetCurrentState"},
225         {0x000B0000, nullptr, "GetTargetState"},
226         {0x000C0000, nullptr, "<Stubbed>"},
227         {0x000D0040, &NDM_U::QueryStatus, "QueryStatus"},
228         {0x000E0040, &NDM_U::GetDaemonDisableCount, "GetDaemonDisableCount"},
229         {0x000F0000, &NDM_U::GetSchedulerDisableCount, "GetSchedulerDisableCount"},
230         {0x00100040, &NDM_U::SetScanInterval, "SetScanInterval"},
231         {0x00110000, &NDM_U::GetScanInterval, "GetScanInterval"},
232         {0x00120040, &NDM_U::SetRetryInterval, "SetRetryInterval"},
233         {0x00130000, &NDM_U::GetRetryInterval, "GetRetryInterval"},
234         {0x00140040, &NDM_U::OverrideDefaultDaemons, "OverrideDefaultDaemons"},
235         {0x00150000, &NDM_U::ResetDefaultDaemons, "ResetDefaultDaemons"},
236         {0x00160000, &NDM_U::GetDefaultDaemons, "GetDefaultDaemons"},
237         {0x00170000, &NDM_U::ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"},
238     };
239     RegisterHandlers(functions);
240 }
241 
InstallInterfaces(Core::System & system)242 void InstallInterfaces(Core::System& system) {
243     auto& service_manager = system.ServiceManager();
244     std::make_shared<NDM_U>()->InstallAsService(service_manager);
245 }
246 
247 } // namespace Service::NDM
248