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