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