summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar liamwhite2022-08-12 08:40:30 -0400
committerGravatar GitHub2022-08-12 08:40:30 -0400
commit536626fdd65cbf1f937f48f11f289b8adecf1d6b (patch)
tree9a5394129ff1c41f00b70169d2778aca62856818
parentMerge pull request #8686 from lat9nq/graft-source (diff)
parentcore: ldn: Address review comments part 2 (diff)
downloadyuzu-536626fdd65cbf1f937f48f11f289b8adecf1d6b.tar.gz
yuzu-536626fdd65cbf1f937f48f11f289b8adecf1d6b.tar.xz
yuzu-536626fdd65cbf1f937f48f11f289b8adecf1d6b.zip
Merge pull request #8731 from FearlessTobi/better-ldn
ldn: Add better stubs and more data types
-rw-r--r--src/core/CMakeLists.txt3
-rw-r--r--src/core/hle/service/ldn/errors.h12
-rw-r--r--src/core/hle/service/ldn/ldn.cpp436
-rw-r--r--src/core/hle/service/ldn/ldn.h6
-rw-r--r--src/core/hle/service/ldn/ldn_results.h27
-rw-r--r--src/core/hle/service/ldn/ldn_types.h284
6 files changed, 711 insertions, 57 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 052357be4..4e39649a8 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -502,9 +502,10 @@ add_library(core STATIC
502 hle/service/jit/jit.h 502 hle/service/jit/jit.h
503 hle/service/lbl/lbl.cpp 503 hle/service/lbl/lbl.cpp
504 hle/service/lbl/lbl.h 504 hle/service/lbl/lbl.h
505 hle/service/ldn/errors.h 505 hle/service/ldn/ldn_results.h
506 hle/service/ldn/ldn.cpp 506 hle/service/ldn/ldn.cpp
507 hle/service/ldn/ldn.h 507 hle/service/ldn/ldn.h
508 hle/service/ldn/ldn_types.h
508 hle/service/ldr/ldr.cpp 509 hle/service/ldr/ldr.cpp
509 hle/service/ldr/ldr.h 510 hle/service/ldr/ldr.h
510 hle/service/lm/lm.cpp 511 hle/service/lm/lm.cpp
diff --git a/src/core/hle/service/ldn/errors.h b/src/core/hle/service/ldn/errors.h
deleted file mode 100644
index 972a74806..000000000
--- a/src/core/hle/service/ldn/errors.h
+++ /dev/null
@@ -1,12 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Service::LDN {
9
10constexpr Result ERROR_DISABLED{ErrorModule::LDN, 22};
11
12} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index 125d4dc4c..c11daff54 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -3,11 +3,15 @@
3 3
4#include <memory> 4#include <memory>
5 5
6#include "core/hle/ipc_helpers.h" 6#include "core/core.h"
7#include "core/hle/result.h"
8#include "core/hle/service/ldn/errors.h"
9#include "core/hle/service/ldn/ldn.h" 7#include "core/hle/service/ldn/ldn.h"
10#include "core/hle/service/sm/sm.h" 8#include "core/hle/service/ldn/ldn_results.h"
9#include "core/hle/service/ldn/ldn_types.h"
10#include "core/internal_network/network.h"
11#include "core/internal_network/network_interface.h"
12
13// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
14#undef CreateEvent
11 15
12namespace Service::LDN { 16namespace Service::LDN {
13 17
@@ -100,74 +104,418 @@ class IUserLocalCommunicationService final
100 : public ServiceFramework<IUserLocalCommunicationService> { 104 : public ServiceFramework<IUserLocalCommunicationService> {
101public: 105public:
102 explicit IUserLocalCommunicationService(Core::System& system_) 106 explicit IUserLocalCommunicationService(Core::System& system_)
103 : ServiceFramework{system_, "IUserLocalCommunicationService"} { 107 : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew},
108 service_context{system, "IUserLocalCommunicationService"}, room_network{
109 system_.GetRoomNetwork()} {
104 // clang-format off 110 // clang-format off
105 static const FunctionInfo functions[] = { 111 static const FunctionInfo functions[] = {
106 {0, &IUserLocalCommunicationService::GetState, "GetState"}, 112 {0, &IUserLocalCommunicationService::GetState, "GetState"},
107 {1, nullptr, "GetNetworkInfo"}, 113 {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
108 {2, nullptr, "GetIpv4Address"}, 114 {2, nullptr, "GetIpv4Address"},
109 {3, nullptr, "GetDisconnectReason"}, 115 {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"},
110 {4, nullptr, "GetSecurityParameter"}, 116 {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"},
111 {5, nullptr, "GetNetworkConfig"}, 117 {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"},
112 {100, nullptr, "AttachStateChangeEvent"}, 118 {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"},
113 {101, nullptr, "GetNetworkInfoLatestUpdate"}, 119 {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"},
114 {102, nullptr, "Scan"}, 120 {102, &IUserLocalCommunicationService::Scan, "Scan"},
115 {103, nullptr, "ScanPrivate"}, 121 {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"},
116 {104, nullptr, "SetWirelessControllerRestriction"}, 122 {104, nullptr, "SetWirelessControllerRestriction"},
117 {200, nullptr, "OpenAccessPoint"}, 123 {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
118 {201, nullptr, "CloseAccessPoint"}, 124 {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
119 {202, nullptr, "CreateNetwork"}, 125 {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
120 {203, nullptr, "CreateNetworkPrivate"}, 126 {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
121 {204, nullptr, "DestroyNetwork"}, 127 {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
122 {205, nullptr, "Reject"}, 128 {205, nullptr, "Reject"},
123 {206, nullptr, "SetAdvertiseData"}, 129 {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
124 {207, nullptr, "SetStationAcceptPolicy"}, 130 {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
125 {208, nullptr, "AddAcceptFilterEntry"}, 131 {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
126 {209, nullptr, "ClearAcceptFilter"}, 132 {209, nullptr, "ClearAcceptFilter"},
127 {300, nullptr, "OpenStation"}, 133 {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
128 {301, nullptr, "CloseStation"}, 134 {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
129 {302, nullptr, "Connect"}, 135 {302, &IUserLocalCommunicationService::Connect, "Connect"},
130 {303, nullptr, "ConnectPrivate"}, 136 {303, nullptr, "ConnectPrivate"},
131 {304, nullptr, "Disconnect"}, 137 {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
132 {400, nullptr, "Initialize"}, 138 {400, &IUserLocalCommunicationService::Initialize, "Initialize"},
133 {401, nullptr, "Finalize"}, 139 {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
134 {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, // 7.0.0+ 140 {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
135 }; 141 };
136 // clang-format on 142 // clang-format on
137 143
138 RegisterHandlers(functions); 144 RegisterHandlers(functions);
145
146 state_change_event =
147 service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
148 }
149
150 ~IUserLocalCommunicationService() {
151 service_context.CloseEvent(state_change_event);
152 }
153
154 void OnEventFired() {
155 state_change_event->GetWritableEvent().Signal();
139 } 156 }
140 157
141 void GetState(Kernel::HLERequestContext& ctx) { 158 void GetState(Kernel::HLERequestContext& ctx) {
159 State state = State::Error;
160 LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state);
161
162 IPC::ResponseBuilder rb{ctx, 3};
163 rb.Push(ResultSuccess);
164 rb.PushEnum(state);
165 }
166
167 void GetNetworkInfo(Kernel::HLERequestContext& ctx) {
168 const auto write_buffer_size = ctx.GetWriteBufferSize();
169
170 if (write_buffer_size != sizeof(NetworkInfo)) {
171 LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
172 IPC::ResponseBuilder rb{ctx, 2};
173 rb.Push(ResultBadInput);
174 return;
175 }
176
177 NetworkInfo network_info{};
178 const auto rc = ResultSuccess;
179 if (rc.IsError()) {
180 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
181 IPC::ResponseBuilder rb{ctx, 2};
182 rb.Push(rc);
183 return;
184 }
185
186 LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
187 network_info.common.ssid.GetStringValue(), network_info.ldn.node_count);
188
189 ctx.WriteBuffer<NetworkInfo>(network_info);
190 IPC::ResponseBuilder rb{ctx, 2};
191 rb.Push(rc);
192 }
193
194 void GetDisconnectReason(Kernel::HLERequestContext& ctx) {
195 const auto disconnect_reason = DisconnectReason::None;
196
197 LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason);
198
199 IPC::ResponseBuilder rb{ctx, 3};
200 rb.Push(ResultSuccess);
201 rb.PushEnum(disconnect_reason);
202 }
203
204 void GetSecurityParameter(Kernel::HLERequestContext& ctx) {
205 SecurityParameter security_parameter{};
206 NetworkInfo info{};
207 const Result rc = ResultSuccess;
208
209 if (rc.IsError()) {
210 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
211 IPC::ResponseBuilder rb{ctx, 2};
212 rb.Push(rc);
213 return;
214 }
215
216 security_parameter.session_id = info.network_id.session_id;
217 std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
218 sizeof(SecurityParameter::data));
219
142 LOG_WARNING(Service_LDN, "(STUBBED) called"); 220 LOG_WARNING(Service_LDN, "(STUBBED) called");
143 221
222 IPC::ResponseBuilder rb{ctx, 10};
223 rb.Push(rc);
224 rb.PushRaw<SecurityParameter>(security_parameter);
225 }
226
227 void GetNetworkConfig(Kernel::HLERequestContext& ctx) {
228 NetworkConfig config{};
229 NetworkInfo info{};
230 const Result rc = ResultSuccess;
231
232 if (rc.IsError()) {
233 LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
234 IPC::ResponseBuilder rb{ctx, 2};
235 rb.Push(rc);
236 return;
237 }
238
239 config.intent_id = info.network_id.intent_id;
240 config.channel = info.common.channel;
241 config.node_count_max = info.ldn.node_count_max;
242 config.local_communication_version = info.ldn.nodes[0].local_communication_version;
243
244 LOG_WARNING(Service_LDN,
245 "(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, "
246 "local_communication_version={}",
247 config.intent_id.local_communication_id, config.intent_id.scene_id,
248 config.channel, config.node_count_max, config.local_communication_version);
249
250 IPC::ResponseBuilder rb{ctx, 10};
251 rb.Push(rc);
252 rb.PushRaw<NetworkConfig>(config);
253 }
254
255 void AttachStateChangeEvent(Kernel::HLERequestContext& ctx) {
256 LOG_INFO(Service_LDN, "called");
257
258 IPC::ResponseBuilder rb{ctx, 2, 1};
259 rb.Push(ResultSuccess);
260 rb.PushCopyObjects(state_change_event->GetReadableEvent());
261 }
262
263 void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) {
264 const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
265 const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate);
266
267 if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
268 LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size,
269 node_buffer_count);
270 IPC::ResponseBuilder rb{ctx, 2};
271 rb.Push(ResultBadInput);
272 return;
273 }
274
275 NetworkInfo info;
276 std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
277
278 const auto rc = ResultSuccess;
279 if (rc.IsError()) {
280 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
281 IPC::ResponseBuilder rb{ctx, 2};
282 rb.Push(rc);
283 return;
284 }
285
286 LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}",
287 info.common.ssid.GetStringValue(), info.ldn.node_count);
288
289 ctx.WriteBuffer(info, 0);
290 ctx.WriteBuffer(latest_update, 1);
291
292 IPC::ResponseBuilder rb{ctx, 2};
293 rb.Push(ResultSuccess);
294 }
295
296 void Scan(Kernel::HLERequestContext& ctx) {
297 ScanImpl(ctx);
298 }
299
300 void ScanPrivate(Kernel::HLERequestContext& ctx) {
301 ScanImpl(ctx, true);
302 }
303
304 void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) {
305 IPC::RequestParser rp{ctx};
306 const auto channel{rp.PopEnum<WifiChannel>()};
307 const auto scan_filter{rp.PopRaw<ScanFilter>()};
308
309 const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo);
310
311 if (network_info_size == 0) {
312 LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
313 IPC::ResponseBuilder rb{ctx, 2};
314 rb.Push(ResultBadInput);
315 return;
316 }
317
318 u16 count = 0;
319 std::vector<NetworkInfo> network_infos(network_info_size);
320
321 LOG_WARNING(Service_LDN,
322 "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}",
323 channel, scan_filter.flag, scan_filter.network_type);
324
325 ctx.WriteBuffer(network_infos);
326
144 IPC::ResponseBuilder rb{ctx, 3}; 327 IPC::ResponseBuilder rb{ctx, 3};
328 rb.Push(ResultSuccess);
329 rb.Push<u32>(count);
330 }
331
332 void OpenAccessPoint(Kernel::HLERequestContext& ctx) {
333 LOG_WARNING(Service_LDN, "(STUBBED) called");
334
335 IPC::ResponseBuilder rb{ctx, 2};
336 rb.Push(ResultSuccess);
337 }
338
339 void CloseAccessPoint(Kernel::HLERequestContext& ctx) {
340 LOG_WARNING(Service_LDN, "(STUBBED) called");
341
342 IPC::ResponseBuilder rb{ctx, 2};
343 rb.Push(ResultSuccess);
344 }
345
346 void CreateNetwork(Kernel::HLERequestContext& ctx) {
347 IPC::RequestParser rp{ctx};
348 struct Parameters {
349 SecurityConfig security_config;
350 UserConfig user_config;
351 INSERT_PADDING_WORDS_NOINIT(1);
352 NetworkConfig network_config;
353 };
354 static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size.");
355
356 const auto parameters{rp.PopRaw<Parameters>()};
357
358 LOG_WARNING(Service_LDN,
359 "(STUBBED) called, passphrase_size={}, security_mode={}, "
360 "local_communication_version={}",
361 parameters.security_config.passphrase_size,
362 parameters.security_config.security_mode,
363 parameters.network_config.local_communication_version);
364
365 IPC::ResponseBuilder rb{ctx, 2};
366 rb.Push(ResultSuccess);
367 }
368
369 void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) {
370 IPC::RequestParser rp{ctx};
371 struct Parameters {
372 SecurityConfig security_config;
373 SecurityParameter security_parameter;
374 UserConfig user_config;
375 NetworkConfig network_config;
376 };
377 static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size.");
378
379 const auto parameters{rp.PopRaw<Parameters>()};
380
381 LOG_WARNING(Service_LDN,
382 "(STUBBED) called, passphrase_size={}, security_mode={}, "
383 "local_communication_version={}",
384 parameters.security_config.passphrase_size,
385 parameters.security_config.security_mode,
386 parameters.network_config.local_communication_version);
387
388 IPC::ResponseBuilder rb{ctx, 2};
389 rb.Push(ResultSuccess);
390 }
391
392 void DestroyNetwork(Kernel::HLERequestContext& ctx) {
393 LOG_WARNING(Service_LDN, "(STUBBED) called");
394
395 IPC::ResponseBuilder rb{ctx, 2};
396 rb.Push(ResultSuccess);
397 }
398
399 void SetAdvertiseData(Kernel::HLERequestContext& ctx) {
400 std::vector<u8> read_buffer = ctx.ReadBuffer();
401
402 LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size());
403
404 IPC::ResponseBuilder rb{ctx, 2};
405 rb.Push(ResultSuccess);
406 }
407
408 void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) {
409 LOG_WARNING(Service_LDN, "(STUBBED) called");
410
411 IPC::ResponseBuilder rb{ctx, 2};
412 rb.Push(ResultSuccess);
413 }
145 414
146 // Indicate a network error, as we do not actually emulate LDN 415 void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) {
147 rb.Push(static_cast<u32>(State::Error)); 416 LOG_WARNING(Service_LDN, "(STUBBED) called");
148 417
418 IPC::ResponseBuilder rb{ctx, 2};
419 rb.Push(ResultSuccess);
420 }
421
422 void OpenStation(Kernel::HLERequestContext& ctx) {
423 LOG_WARNING(Service_LDN, "(STUBBED) called");
424
425 IPC::ResponseBuilder rb{ctx, 2};
426 rb.Push(ResultSuccess);
427 }
428
429 void CloseStation(Kernel::HLERequestContext& ctx) {
430 LOG_WARNING(Service_LDN, "(STUBBED) called");
431
432 IPC::ResponseBuilder rb{ctx, 2};
433 rb.Push(ResultSuccess);
434 }
435
436 void Connect(Kernel::HLERequestContext& ctx) {
437 IPC::RequestParser rp{ctx};
438 struct Parameters {
439 SecurityConfig security_config;
440 UserConfig user_config;
441 u32 local_communication_version;
442 u32 option;
443 };
444 static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
445
446 const auto parameters{rp.PopRaw<Parameters>()};
447
448 LOG_WARNING(Service_LDN,
449 "(STUBBED) called, passphrase_size={}, security_mode={}, "
450 "local_communication_version={}",
451 parameters.security_config.passphrase_size,
452 parameters.security_config.security_mode,
453 parameters.local_communication_version);
454
455 const std::vector<u8> read_buffer = ctx.ReadBuffer();
456 NetworkInfo network_info{};
457
458 if (read_buffer.size() != sizeof(NetworkInfo)) {
459 LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
460 IPC::ResponseBuilder rb{ctx, 2};
461 rb.Push(ResultBadInput);
462 return;
463 }
464
465 std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
466
467 IPC::ResponseBuilder rb{ctx, 2};
468 rb.Push(ResultSuccess);
469 }
470
471 void Disconnect(Kernel::HLERequestContext& ctx) {
472 LOG_WARNING(Service_LDN, "(STUBBED) called");
473
474 IPC::ResponseBuilder rb{ctx, 2};
475 rb.Push(ResultSuccess);
476 }
477 void Initialize(Kernel::HLERequestContext& ctx) {
478 LOG_WARNING(Service_LDN, "(STUBBED) called");
479
480 const auto rc = InitializeImpl(ctx);
481
482 IPC::ResponseBuilder rb{ctx, 2};
483 rb.Push(rc);
484 }
485
486 void Finalize(Kernel::HLERequestContext& ctx) {
487 LOG_WARNING(Service_LDN, "(STUBBED) called");
488
489 is_initialized = false;
490
491 IPC::ResponseBuilder rb{ctx, 2};
149 rb.Push(ResultSuccess); 492 rb.Push(ResultSuccess);
150 } 493 }
151 494
152 void Initialize2(Kernel::HLERequestContext& ctx) { 495 void Initialize2(Kernel::HLERequestContext& ctx) {
153 LOG_DEBUG(Service_LDN, "called"); 496 LOG_WARNING(Service_LDN, "(STUBBED) called");
154 497
155 is_initialized = true; 498 const auto rc = InitializeImpl(ctx);
156 499
157 IPC::ResponseBuilder rb{ctx, 2}; 500 IPC::ResponseBuilder rb{ctx, 2};
158 rb.Push(ERROR_DISABLED); 501 rb.Push(rc);
502 }
503
504 Result InitializeImpl(Kernel::HLERequestContext& ctx) {
505 const auto network_interface = Network::GetSelectedNetworkInterface();
506 if (!network_interface) {
507 LOG_ERROR(Service_LDN, "No network interface is set");
508 return ResultAirplaneModeEnabled;
509 }
510
511 is_initialized = true;
512 // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
513 return ResultAirplaneModeEnabled;
159 } 514 }
160 515
161private: 516 KernelHelpers::ServiceContext service_context;
162 enum class State { 517 Kernel::KEvent* state_change_event;
163 None, 518 Network::RoomNetwork& room_network;
164 Initialized,
165 AccessPointOpened,
166 AccessPointCreated,
167 StationOpened,
168 StationConnected,
169 Error,
170 };
171 519
172 bool is_initialized{}; 520 bool is_initialized{};
173}; 521};
@@ -273,7 +621,7 @@ public:
273 LOG_WARNING(Service_LDN, "(STUBBED) called"); 621 LOG_WARNING(Service_LDN, "(STUBBED) called");
274 622
275 IPC::ResponseBuilder rb{ctx, 2}; 623 IPC::ResponseBuilder rb{ctx, 2};
276 rb.Push(ERROR_DISABLED); 624 rb.Push(ResultDisabled);
277 } 625 }
278}; 626};
279 627
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index a0031ac71..6afe2ea6f 100644
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -3,6 +3,12 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/result.h"
9#include "core/hle/service/kernel_helpers.h"
10#include "core/hle/service/sm/sm.h"
11
6namespace Core { 12namespace Core {
7class System; 13class System;
8} 14}
diff --git a/src/core/hle/service/ldn/ldn_results.h b/src/core/hle/service/ldn/ldn_results.h
new file mode 100644
index 000000000..f340bda42
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn_results.h
@@ -0,0 +1,27 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7
8namespace Service::LDN {
9
10constexpr Result ResultAdvertiseDataTooLarge{ErrorModule::LDN, 10};
11constexpr Result ResultAuthenticationFailed{ErrorModule::LDN, 20};
12constexpr Result ResultDisabled{ErrorModule::LDN, 22};
13constexpr Result ResultAirplaneModeEnabled{ErrorModule::LDN, 23};
14constexpr Result ResultInvalidNodeCount{ErrorModule::LDN, 30};
15constexpr Result ResultConnectionFailed{ErrorModule::LDN, 31};
16constexpr Result ResultBadState{ErrorModule::LDN, 32};
17constexpr Result ResultNoIpAddress{ErrorModule::LDN, 33};
18constexpr Result ResultInvalidBufferCount{ErrorModule::LDN, 50};
19constexpr Result ResultAccessPointConnectionFailed{ErrorModule::LDN, 65};
20constexpr Result ResultAuthenticationTimeout{ErrorModule::LDN, 66};
21constexpr Result ResultMaximumNodeCount{ErrorModule::LDN, 67};
22constexpr Result ResultBadInput{ErrorModule::LDN, 96};
23constexpr Result ResultLocalCommunicationIdNotFound{ErrorModule::LDN, 97};
24constexpr Result ResultLocalCommunicationVersionTooLow{ErrorModule::LDN, 113};
25constexpr Result ResultLocalCommunicationVersionTooHigh{ErrorModule::LDN, 114};
26
27} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h
new file mode 100644
index 000000000..0c07a7397
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn_types.h
@@ -0,0 +1,284 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <fmt/format.h>
7
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10#include "network/network.h"
11
12namespace Service::LDN {
13
14constexpr size_t SsidLengthMax = 32;
15constexpr size_t AdvertiseDataSizeMax = 384;
16constexpr size_t UserNameBytesMax = 32;
17constexpr int NodeCountMax = 8;
18constexpr int StationCountMax = NodeCountMax - 1;
19constexpr size_t PassphraseLengthMax = 64;
20
21enum class SecurityMode : u16 {
22 All,
23 Retail,
24 Debug,
25};
26
27enum class NodeStateChange : u8 {
28 None,
29 Connect,
30 Disconnect,
31 DisconnectAndConnect,
32};
33
34enum class ScanFilterFlag : u32 {
35 None = 0,
36 LocalCommunicationId = 1 << 0,
37 SessionId = 1 << 1,
38 NetworkType = 1 << 2,
39 Ssid = 1 << 4,
40 SceneId = 1 << 5,
41 IntentId = LocalCommunicationId | SceneId,
42 NetworkId = IntentId | SessionId,
43};
44
45enum class NetworkType : u32 {
46 None,
47 General,
48 Ldn,
49 All,
50};
51
52enum class PackedNetworkType : u8 {
53 None,
54 General,
55 Ldn,
56 All,
57};
58
59enum class State : u32 {
60 None,
61 Initialized,
62 AccessPointOpened,
63 AccessPointCreated,
64 StationOpened,
65 StationConnected,
66 Error,
67};
68
69enum class DisconnectReason : s16 {
70 Unknown = -1,
71 None,
72 DisconnectedByUser,
73 DisconnectedBySystem,
74 DestroyedByUser,
75 DestroyedBySystem,
76 Rejected,
77 SignalLost,
78};
79
80enum class NetworkError {
81 Unknown = -1,
82 None = 0,
83 PortUnreachable,
84 TooManyPlayers,
85 VersionTooLow,
86 VersionTooHigh,
87 ConnectFailure,
88 ConnectNotFound,
89 ConnectTimeout,
90 ConnectRejected,
91 RejectFailed,
92};
93
94enum class AcceptPolicy : u8 {
95 AcceptAll,
96 RejectAll,
97 BlackList,
98 WhiteList,
99};
100
101enum class WifiChannel : s16 {
102 Default = 0,
103 wifi24_1 = 1,
104 wifi24_6 = 6,
105 wifi24_11 = 11,
106 wifi50_36 = 36,
107 wifi50_40 = 40,
108 wifi50_44 = 44,
109 wifi50_48 = 48,
110};
111
112enum class LinkLevel : s8 {
113 Bad,
114 Low,
115 Good,
116 Excelent,
117};
118
119struct NodeLatestUpdate {
120 NodeStateChange state_change;
121 INSERT_PADDING_BYTES(0x7); // Unknown
122};
123static_assert(sizeof(NodeLatestUpdate) == 0x8, "NodeLatestUpdate is an invalid size");
124
125struct SessionId {
126 u64 high;
127 u64 low;
128
129 bool operator==(const SessionId&) const = default;
130};
131static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
132
133struct IntentId {
134 u64 local_communication_id;
135 INSERT_PADDING_BYTES(0x2); // Reserved
136 u16 scene_id;
137 INSERT_PADDING_BYTES(0x4); // Reserved
138};
139static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
140
141struct NetworkId {
142 IntentId intent_id;
143 SessionId session_id;
144};
145static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
146
147struct Ssid {
148 u8 length;
149 std::array<char, SsidLengthMax + 1> raw;
150
151 std::string GetStringValue() const {
152 return std::string(raw.data(), length);
153 }
154};
155static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size");
156
157struct Ipv4Address {
158 union {
159 u32 raw{};
160 std::array<u8, 4> bytes;
161 };
162
163 std::string GetStringValue() const {
164 return fmt::format("{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]);
165 }
166};
167static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
168
169struct MacAddress {
170 std::array<u8, 6> raw{};
171
172 friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
173};
174static_assert(sizeof(MacAddress) == 0x6, "MacAddress is an invalid size");
175
176struct ScanFilter {
177 NetworkId network_id;
178 NetworkType network_type;
179 MacAddress mac_address;
180 Ssid ssid;
181 INSERT_PADDING_BYTES(0x10);
182 ScanFilterFlag flag;
183};
184static_assert(sizeof(ScanFilter) == 0x60, "ScanFilter is an invalid size");
185
186struct CommonNetworkInfo {
187 MacAddress bssid;
188 Ssid ssid;
189 WifiChannel channel;
190 LinkLevel link_level;
191 PackedNetworkType network_type;
192 INSERT_PADDING_BYTES(0x4);
193};
194static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
195
196struct NodeInfo {
197 Ipv4Address ipv4_address;
198 MacAddress mac_address;
199 s8 node_id;
200 u8 is_connected;
201 std::array<u8, UserNameBytesMax + 1> user_name;
202 INSERT_PADDING_BYTES(0x1); // Reserved
203 s16 local_communication_version;
204 INSERT_PADDING_BYTES(0x10); // Reserved
205};
206static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
207
208struct LdnNetworkInfo {
209 std::array<u8, 0x10> security_parameter;
210 SecurityMode security_mode;
211 AcceptPolicy station_accept_policy;
212 u8 has_action_frame;
213 INSERT_PADDING_BYTES(0x2); // Padding
214 u8 node_count_max;
215 u8 node_count;
216 std::array<NodeInfo, NodeCountMax> nodes;
217 INSERT_PADDING_BYTES(0x2); // Reserved
218 u16 advertise_data_size;
219 std::array<u8, AdvertiseDataSizeMax> advertise_data;
220 INSERT_PADDING_BYTES(0x8C); // Reserved
221 u64 random_authentication_id;
222};
223static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
224
225struct NetworkInfo {
226 NetworkId network_id;
227 CommonNetworkInfo common;
228 LdnNetworkInfo ldn;
229};
230static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
231
232struct SecurityConfig {
233 SecurityMode security_mode;
234 u16 passphrase_size;
235 std::array<u8, PassphraseLengthMax> passphrase;
236};
237static_assert(sizeof(SecurityConfig) == 0x44, "SecurityConfig is an invalid size");
238
239struct UserConfig {
240 std::array<u8, UserNameBytesMax + 1> user_name;
241 INSERT_PADDING_BYTES(0xF); // Reserved
242};
243static_assert(sizeof(UserConfig) == 0x30, "UserConfig is an invalid size");
244
245#pragma pack(push, 4)
246struct ConnectRequest {
247 SecurityConfig security_config;
248 UserConfig user_config;
249 u32 local_communication_version;
250 u32 option_unknown;
251 NetworkInfo network_info;
252};
253static_assert(sizeof(ConnectRequest) == 0x4FC, "ConnectRequest is an invalid size");
254#pragma pack(pop)
255
256struct SecurityParameter {
257 std::array<u8, 0x10> data; // Data, used with the same key derivation as SecurityConfig
258 SessionId session_id;
259};
260static_assert(sizeof(SecurityParameter) == 0x20, "SecurityParameter is an invalid size");
261
262struct NetworkConfig {
263 IntentId intent_id;
264 WifiChannel channel;
265 u8 node_count_max;
266 INSERT_PADDING_BYTES(0x1); // Reserved
267 u16 local_communication_version;
268 INSERT_PADDING_BYTES(0xA); // Reserved
269};
270static_assert(sizeof(NetworkConfig) == 0x20, "NetworkConfig is an invalid size");
271
272struct AddressEntry {
273 Ipv4Address ipv4_address;
274 MacAddress mac_address;
275 INSERT_PADDING_BYTES(0x2); // Reserved
276};
277static_assert(sizeof(AddressEntry) == 0xC, "AddressEntry is an invalid size");
278
279struct AddressList {
280 std::array<AddressEntry, 0x8> addresses;
281};
282static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
283
284} // namespace Service::LDN