forked from eden-emu/eden
		
	ldn: Add better stubs and more data types
Co-Authored-By: Narr the Reg <5944268+german77@users.noreply.github.com> Co-Authored-By: Morph <39850852+Morph1984@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									9dc8d02acc
								
							
						
					
					
						commit
						12dc05032b
					
				
					 6 changed files with 774 additions and 73 deletions
				
			
		|  | @ -504,9 +504,10 @@ add_library(core STATIC | ||||||
|     hle/service/jit/jit.h |     hle/service/jit/jit.h | ||||||
|     hle/service/lbl/lbl.cpp |     hle/service/lbl/lbl.cpp | ||||||
|     hle/service/lbl/lbl.h |     hle/service/lbl/lbl.h | ||||||
|     hle/service/ldn/errors.h |     hle/service/ldn/ldn_results.h | ||||||
|     hle/service/ldn/ldn.cpp |     hle/service/ldn/ldn.cpp | ||||||
|     hle/service/ldn/ldn.h |     hle/service/ldn/ldn.h | ||||||
|  |     hle/service/ldn/ldn_types.h | ||||||
|     hle/service/ldr/ldr.cpp |     hle/service/ldr/ldr.cpp | ||||||
|     hle/service/ldr/ldr.h |     hle/service/ldr/ldr.h | ||||||
|     hle/service/lm/lm.cpp |     hle/service/lm/lm.cpp | ||||||
|  |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 |  | ||||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include "core/hle/result.h" |  | ||||||
| 
 |  | ||||||
| namespace Service::LDN { |  | ||||||
| 
 |  | ||||||
| constexpr Result ERROR_DISABLED{ErrorModule::LDN, 22}; |  | ||||||
| 
 |  | ||||||
| } // namespace Service::LDN
 |  | ||||||
|  | @ -3,11 +3,12 @@ | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
| #include "core/hle/ipc_helpers.h" | #include "core/core.h" | ||||||
| #include "core/hle/result.h" |  | ||||||
| #include "core/hle/service/ldn/errors.h" |  | ||||||
| #include "core/hle/service/ldn/ldn.h" | #include "core/hle/service/ldn/ldn.h" | ||||||
| #include "core/hle/service/sm/sm.h" | #include "core/internal_network/network.h" | ||||||
|  | #include "core/internal_network/network_interface.h" | ||||||
|  | 
 | ||||||
|  | #undef CreateEvent | ||||||
| 
 | 
 | ||||||
| namespace Service::LDN { | namespace Service::LDN { | ||||||
| 
 | 
 | ||||||
|  | @ -96,81 +97,393 @@ public: | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class IUserLocalCommunicationService final | IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_) | ||||||
|     : public ServiceFramework<IUserLocalCommunicationService> { |     : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew}, | ||||||
| public: |       service_context{system, "IUserLocalCommunicationService"}, room_network{ | ||||||
|     explicit IUserLocalCommunicationService(Core::System& system_) |                                                                      system_.GetRoomNetwork()} { | ||||||
|         : ServiceFramework{system_, "IUserLocalCommunicationService"} { |  | ||||||
|     // clang-format off
 |     // clang-format off
 | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, &IUserLocalCommunicationService::GetState, "GetState"}, |             {0, &IUserLocalCommunicationService::GetState, "GetState"}, | ||||||
|             {1, nullptr, "GetNetworkInfo"}, |             {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"}, | ||||||
|             {2, nullptr, "GetIpv4Address"}, |             {2, nullptr, "GetIpv4Address"}, | ||||||
|             {3, nullptr, "GetDisconnectReason"}, |             {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"}, | ||||||
|             {4, nullptr, "GetSecurityParameter"}, |             {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"}, | ||||||
|             {5, nullptr, "GetNetworkConfig"}, |             {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"}, | ||||||
|             {100, nullptr, "AttachStateChangeEvent"}, |             {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"}, | ||||||
|             {101, nullptr, "GetNetworkInfoLatestUpdate"}, |             {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"}, | ||||||
|             {102, nullptr, "Scan"}, |             {102, &IUserLocalCommunicationService::Scan, "Scan"}, | ||||||
|             {103, nullptr, "ScanPrivate"}, |             {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"}, | ||||||
|             {104, nullptr, "SetWirelessControllerRestriction"}, |             {104, nullptr, "SetWirelessControllerRestriction"}, | ||||||
|             {200, nullptr, "OpenAccessPoint"}, |             {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"}, | ||||||
|             {201, nullptr, "CloseAccessPoint"}, |             {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"}, | ||||||
|             {202, nullptr, "CreateNetwork"}, |             {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"}, | ||||||
|             {203, nullptr, "CreateNetworkPrivate"}, |             {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"}, | ||||||
|             {204, nullptr, "DestroyNetwork"}, |             {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"}, | ||||||
|             {205, nullptr, "Reject"}, |             {205, nullptr, "Reject"}, | ||||||
|             {206, nullptr, "SetAdvertiseData"}, |             {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"}, | ||||||
|             {207, nullptr, "SetStationAcceptPolicy"}, |             {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"}, | ||||||
|             {208, nullptr, "AddAcceptFilterEntry"}, |             {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"}, | ||||||
|             {209, nullptr, "ClearAcceptFilter"}, |             {209, nullptr, "ClearAcceptFilter"}, | ||||||
|             {300, nullptr, "OpenStation"}, |             {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"}, | ||||||
|             {301, nullptr, "CloseStation"}, |             {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"}, | ||||||
|             {302, nullptr, "Connect"}, |             {302, &IUserLocalCommunicationService::Connect, "Connect"}, | ||||||
|             {303, nullptr, "ConnectPrivate"}, |             {303, nullptr, "ConnectPrivate"}, | ||||||
|             {304, nullptr, "Disconnect"}, |             {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"}, | ||||||
|             {400, nullptr, "Initialize"}, |             {400, &IUserLocalCommunicationService::Initialize, "Initialize"}, | ||||||
|             {401, nullptr, "Finalize"}, |             {401, &IUserLocalCommunicationService::Finalize, "Finalize"}, | ||||||
|             {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, // 7.0.0+
 |             {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, | ||||||
|         }; |         }; | ||||||
|     // clang-format on
 |     // clang-format on
 | ||||||
| 
 | 
 | ||||||
|     RegisterHandlers(functions); |     RegisterHandlers(functions); | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     void GetState(Kernel::HLERequestContext& ctx) { |     state_change_event = | ||||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); |         service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IUserLocalCommunicationService::~IUserLocalCommunicationService() { | ||||||
|  |     service_context.CloseEvent(state_change_event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::OnEventFired() { | ||||||
|  |     state_change_event->GetWritableEvent().Signal(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::GetState(Kernel::HLERequestContext& ctx) { | ||||||
|  |     State state = State::Error; | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 3}; |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
| 
 |  | ||||||
|         // Indicate a network error, as we do not actually emulate LDN
 |  | ||||||
|         rb.Push(static_cast<u32>(State::Error)); |  | ||||||
| 
 |  | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|  |     rb.PushEnum(state); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::GetNetworkInfo(Kernel::HLERequestContext& ctx) { | ||||||
|  |     const auto write_buffer_size = ctx.GetWriteBufferSize(); | ||||||
|  | 
 | ||||||
|  |     if (write_buffer_size != sizeof(NetworkInfo)) { | ||||||
|  |         LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(ResultBadInput); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Initialize2(Kernel::HLERequestContext& ctx) { |     NetworkInfo networkInfo{}; | ||||||
|         LOG_DEBUG(Service_LDN, "called"); |     const auto rc = ResultSuccess; | ||||||
|  |     if (rc.IsError()) { | ||||||
|  |         LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(rc); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         is_initialized = true; |     LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}", | ||||||
|  |                 networkInfo.common.ssid.GetStringValue(), networkInfo.ldn.node_count); | ||||||
|  | 
 | ||||||
|  |     ctx.WriteBuffer<NetworkInfo>(networkInfo); | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(rc); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::GetDisconnectReason(Kernel::HLERequestContext& ctx) { | ||||||
|  |     const auto disconnect_reason = DisconnectReason::None; | ||||||
|  | 
 | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called, disconnect_reason={}", disconnect_reason); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  |     rb.PushEnum(disconnect_reason); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::GetSecurityParameter(Kernel::HLERequestContext& ctx) { | ||||||
|  |     SecurityParameter security_parameter; | ||||||
|  |     NetworkInfo info; | ||||||
|  |     const Result rc = ResultSuccess; | ||||||
|  | 
 | ||||||
|  |     if (rc.IsError()) { | ||||||
|  |         LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(rc); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     security_parameter.session_id = info.network_id.session_id; | ||||||
|  |     std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(), | ||||||
|  |                 sizeof(SecurityParameter::data)); | ||||||
|  | 
 | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 10}; | ||||||
|  |     rb.Push(rc); | ||||||
|  |     rb.PushRaw<SecurityParameter>(security_parameter); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::GetNetworkConfig(Kernel::HLERequestContext& ctx) { | ||||||
|  |     NetworkConfig config; | ||||||
|  |     NetworkInfo info; | ||||||
|  |     const Result rc = ResultSuccess; | ||||||
|  | 
 | ||||||
|  |     if (rc.IsError()) { | ||||||
|  |         LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(rc); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     config.intent_id = info.network_id.intent_id; | ||||||
|  |     config.channel = info.common.channel; | ||||||
|  |     config.node_count_max = info.ldn.node_count_max; | ||||||
|  |     config.local_communication_version = info.ldn.nodes[0].local_communication_version; | ||||||
|  | 
 | ||||||
|  |     LOG_WARNING(Service_LDN, | ||||||
|  |                 "(STUBBED) called, intent_id={}/{}, channel={}, node_count_max={}, " | ||||||
|  |                 "local_communication_version={}", | ||||||
|  |                 config.intent_id.local_communication_id, config.intent_id.scene_id, config.channel, | ||||||
|  |                 config.node_count_max, config.local_communication_version); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 10}; | ||||||
|  |     rb.Push(rc); | ||||||
|  |     rb.PushRaw<NetworkConfig>(config); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::AttachStateChangeEvent(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_INFO(Service_LDN, "called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  |     rb.PushCopyObjects(state_change_event->GetReadableEvent()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx) { | ||||||
|  |     const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0); | ||||||
|  |     const std::size_t node_buffer_count = ctx.GetWriteBufferSize(1) / sizeof(NodeLatestUpdate); | ||||||
|  | 
 | ||||||
|  |     if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) { | ||||||
|  |         LOG_ERROR(Service_LDN, "Invalid buffer size {}, {}", network_buffer_size, | ||||||
|  |                   node_buffer_count); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(ResultBadInput); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     NetworkInfo info; | ||||||
|  |     std::vector<NodeLatestUpdate> latest_update{}; | ||||||
|  |     latest_update.resize(node_buffer_count); | ||||||
|  | 
 | ||||||
|  |     const auto rc = ResultSuccess; | ||||||
|  |     if (rc.IsError()) { | ||||||
|  |         LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(rc); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called, ssid='{}', nodes={}", | ||||||
|  |                 info.common.ssid.GetStringValue(), info.ldn.node_count); | ||||||
|  | 
 | ||||||
|  |     ctx.WriteBuffer(info, 0); | ||||||
|  |     ctx.WriteBuffer(latest_update, 1); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 2}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(ERROR_DISABLED); |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::Scan(Kernel::HLERequestContext& ctx) { | ||||||
|  |     ScanImpl(ctx); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::ScanPrivate(Kernel::HLERequestContext& ctx) { | ||||||
|  |     ScanImpl(ctx, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::ScanImpl(Kernel::HLERequestContext& ctx, bool is_private) { | ||||||
|  |     IPC::RequestParser rp{ctx}; | ||||||
|  |     const auto channel{rp.PopEnum<WifiChannel>()}; | ||||||
|  |     const auto scan_filter{rp.PopRaw<ScanFilter>()}; | ||||||
|  | 
 | ||||||
|  |     const std::size_t network_info_size = ctx.GetWriteBufferSize() / sizeof(NetworkInfo); | ||||||
|  | 
 | ||||||
|  |     if (network_info_size == 0) { | ||||||
|  |         LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(ResultBadInput); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: |     u16 count = 0; | ||||||
|     enum class State { |     std::vector<NetworkInfo> networks_info{}; | ||||||
|         None, |     networks_info.resize(network_info_size); | ||||||
|         Initialized, |  | ||||||
|         AccessPointOpened, |  | ||||||
|         AccessPointCreated, |  | ||||||
|         StationOpened, |  | ||||||
|         StationConnected, |  | ||||||
|         Error, |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     bool is_initialized{}; |     LOG_WARNING(Service_LDN, | ||||||
| }; |                 "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}", | ||||||
|  |                 channel, scan_filter.flag, scan_filter.network_type); | ||||||
|  | 
 | ||||||
|  |     ctx.WriteBuffer(networks_info); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  |     rb.Push<u32>(count); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::OpenAccessPoint(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::CloseAccessPoint(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::CreateNetwork(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     CreateNetworkImpl(ctx, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::CreateNetworkPrivate(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     CreateNetworkImpl(ctx, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::CreateNetworkImpl(Kernel::HLERequestContext& ctx, | ||||||
|  |                                                        bool is_private) { | ||||||
|  |     IPC::RequestParser rp{ctx}; | ||||||
|  | 
 | ||||||
|  |     const auto security_config{rp.PopRaw<SecurityConfig>()}; | ||||||
|  |     [[maybe_unused]] const auto security_parameter{is_private ? rp.PopRaw<SecurityParameter>() | ||||||
|  |                                                               : SecurityParameter{}}; | ||||||
|  |     const auto user_config{rp.PopRaw<UserConfig>()}; | ||||||
|  |     rp.Pop<u32>(); // Padding
 | ||||||
|  |     const auto network_Config{rp.PopRaw<NetworkConfig>()}; | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | void IUserLocalCommunicationService::DestroyNetwork(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::SetAdvertiseData(Kernel::HLERequestContext& ctx) { | ||||||
|  |     std::vector<u8> read_buffer = ctx.ReadBuffer(); | ||||||
|  | 
 | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called, size {}", read_buffer.size()); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::OpenStation(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::CloseStation(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::Connect(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::RequestParser rp{ctx}; | ||||||
|  | 
 | ||||||
|  |     [[maybe_unused]] const auto securityConfig{rp.PopRaw<SecurityConfig>()}; | ||||||
|  |     const auto user_config{rp.PopRaw<UserConfig>()}; | ||||||
|  |     const auto local_communication_version{rp.Pop<u32>()}; | ||||||
|  |     [[maybe_unused]] const auto option{rp.Pop<u32>()}; | ||||||
|  | 
 | ||||||
|  |     std::vector<u8> read_buffer = ctx.ReadBuffer(); | ||||||
|  |     NetworkInfo networkInfo{}; | ||||||
|  | 
 | ||||||
|  |     if (read_buffer.size() != sizeof(NetworkInfo)) { | ||||||
|  |         LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!"); | ||||||
|  |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |         rb.Push(ResultBadInput); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::memcpy(&networkInfo, read_buffer.data(), read_buffer.size()); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::Disconnect(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | void IUserLocalCommunicationService::Initialize(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     const auto rc = InitializeImpl(ctx); | ||||||
|  |     if (rc.IsError()) { | ||||||
|  |         LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(rc); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::Finalize(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     is_initialized = false; | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(ResultSuccess); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IUserLocalCommunicationService::Initialize2(Kernel::HLERequestContext& ctx) { | ||||||
|  |     LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
|  | 
 | ||||||
|  |     const auto rc = InitializeImpl(ctx); | ||||||
|  |     if (rc.IsError()) { | ||||||
|  |         LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(rc); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Result IUserLocalCommunicationService::InitializeImpl(Kernel::HLERequestContext& ctx) { | ||||||
|  |     const auto network_interface = Network::GetSelectedNetworkInterface(); | ||||||
|  |     if (!network_interface) { | ||||||
|  |         return ResultAirplaneModeEnabled; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     is_initialized = true; | ||||||
|  |     // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
 | ||||||
|  |     return ResultAirplaneModeEnabled; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| class LDNS final : public ServiceFramework<LDNS> { | class LDNS final : public ServiceFramework<LDNS> { | ||||||
| public: | public: | ||||||
|  | @ -273,7 +586,7 @@ public: | ||||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); |         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||||
| 
 | 
 | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(ERROR_DISABLED); |         rb.Push(ResultDisabled); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,14 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include "core/hle/ipc_helpers.h" | ||||||
|  | #include "core/hle/kernel/k_event.h" | ||||||
|  | #include "core/hle/result.h" | ||||||
|  | #include "core/hle/service/kernel_helpers.h" | ||||||
|  | #include "core/hle/service/ldn/ldn_results.h" | ||||||
|  | #include "core/hle/service/ldn/ldn_types.h" | ||||||
|  | #include "core/hle/service/sm/sm.h" | ||||||
|  | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
| class System; | class System; | ||||||
| } | } | ||||||
|  | @ -16,4 +24,69 @@ namespace Service::LDN { | ||||||
| /// Registers all LDN services with the specified service manager.
 | /// Registers all LDN services with the specified service manager.
 | ||||||
| void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); | void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); | ||||||
| 
 | 
 | ||||||
|  | class IUserLocalCommunicationService final | ||||||
|  |     : public ServiceFramework<IUserLocalCommunicationService> { | ||||||
|  | public: | ||||||
|  |     explicit IUserLocalCommunicationService(Core::System& system_); | ||||||
|  |     ~IUserLocalCommunicationService() override; | ||||||
|  | 
 | ||||||
|  |     void GetState(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void GetNetworkInfo(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void GetDisconnectReason(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void GetSecurityParameter(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void GetNetworkConfig(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void AttachStateChangeEvent(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void GetNetworkInfoLatestUpdate(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void Scan(Kernel::HLERequestContext& ctx); | ||||||
|  |     void ScanPrivate(Kernel::HLERequestContext& ctx); | ||||||
|  |     void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false); | ||||||
|  | 
 | ||||||
|  |     void OpenAccessPoint(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void CloseAccessPoint(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void CreateNetwork(Kernel::HLERequestContext& ctx); | ||||||
|  |     void CreateNetworkPrivate(Kernel::HLERequestContext& ctx); | ||||||
|  |     void CreateNetworkImpl(Kernel::HLERequestContext& ctx, bool is_private); | ||||||
|  | 
 | ||||||
|  |     void DestroyNetwork(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void SetAdvertiseData(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void SetStationAcceptPolicy(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void OpenStation(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void CloseStation(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void Disconnect(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void Connect(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void Initialize(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void Finalize(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  |     void Initialize2(Kernel::HLERequestContext& ctx); | ||||||
|  |     Result InitializeImpl(Kernel::HLERequestContext& ctx); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     void OnEventFired(); | ||||||
|  | 
 | ||||||
|  |     KernelHelpers::ServiceContext service_context; | ||||||
|  |     Kernel::KEvent* state_change_event; | ||||||
|  |     Network::RoomNetwork& room_network; | ||||||
|  | 
 | ||||||
|  |     bool is_initialized{}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| } // namespace Service::LDN
 | } // namespace Service::LDN
 | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								src/core/hle/service/ldn/ldn_results.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/core/hle/service/ldn/ldn_results.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | // Copyright 2022 yuzu Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "core/hle/result.h" | ||||||
|  | 
 | ||||||
|  | namespace Service::LDN { | ||||||
|  | 
 | ||||||
|  | constexpr Result ResultAdvertiseDataTooLarge{ErrorModule::LDN, 10}; | ||||||
|  | constexpr Result ResultAuthenticationFailed{ErrorModule::LDN, 20}; | ||||||
|  | constexpr Result ResultDisabled{ErrorModule::LDN, 22}; | ||||||
|  | constexpr Result ResultAirplaneModeEnabled{ErrorModule::LDN, 23}; | ||||||
|  | constexpr Result ResultInvalidNodeCount{ErrorModule::LDN, 30}; | ||||||
|  | constexpr Result ResultConnectionFailed{ErrorModule::LDN, 31}; | ||||||
|  | constexpr Result ResultBadState{ErrorModule::LDN, 32}; | ||||||
|  | constexpr Result ResultNoIpAddress{ErrorModule::LDN, 33}; | ||||||
|  | constexpr Result ResultInvalidBufferCount{ErrorModule::LDN, 50}; | ||||||
|  | constexpr Result ResultAccessPointConnectionFailed{ErrorModule::LDN, 65}; | ||||||
|  | constexpr Result ResultAuthenticationTimeout{ErrorModule::LDN, 66}; | ||||||
|  | constexpr Result ResultMaximumNodeCount{ErrorModule::LDN, 67}; | ||||||
|  | constexpr Result ResultBadInput{ErrorModule::LDN, 96}; | ||||||
|  | constexpr Result ResultLocalCommunicationIdNotFound{ErrorModule::LDN, 97}; | ||||||
|  | constexpr Result ResultLocalCommunicationVersionTooLow{ErrorModule::LDN, 113}; | ||||||
|  | constexpr Result ResultLocalCommunicationVersionTooHigh{ErrorModule::LDN, 114}; | ||||||
|  | 
 | ||||||
|  | } // namespace Service::LDN
 | ||||||
							
								
								
									
										298
									
								
								src/core/hle/service/ldn/ldn_types.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								src/core/hle/service/ldn/ldn_types.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,298 @@ | ||||||
|  | // Copyright 2022 yuzu emulator team
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <fmt/format.h> | ||||||
|  | 
 | ||||||
|  | #include "common/common_funcs.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "network/network.h" | ||||||
|  | 
 | ||||||
|  | namespace Service::LDN { | ||||||
|  | 
 | ||||||
|  | constexpr size_t SsidLengthMax = 32; | ||||||
|  | constexpr size_t AdvertiseDataSizeMax = 384; | ||||||
|  | constexpr size_t UserNameBytesMax = 32; | ||||||
|  | constexpr int NodeCountMax = 8; | ||||||
|  | constexpr int StationCountMax = NodeCountMax - 1; | ||||||
|  | constexpr size_t PassphraseLengthMax = 64; | ||||||
|  | 
 | ||||||
|  | enum class SecurityMode : u16 { | ||||||
|  |     All, | ||||||
|  |     Retail, | ||||||
|  |     Debug, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class NodeStateChange : u8 { | ||||||
|  |     None, | ||||||
|  |     Connect, | ||||||
|  |     Disconnect, | ||||||
|  |     DisconnectAndConnect, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | inline NodeStateChange operator|(NodeStateChange a, NodeStateChange b) { | ||||||
|  |     return static_cast<NodeStateChange>(static_cast<u8>(a) | static_cast<u8>(b)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline NodeStateChange operator|=(NodeStateChange& a, NodeStateChange b) { | ||||||
|  |     return a = a | b; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum class ScanFilterFlag : u32 { | ||||||
|  |     None = 0, | ||||||
|  |     LocalCommunicationId = 1 << 0, | ||||||
|  |     SessionId = 1 << 1, | ||||||
|  |     NetworkType = 1 << 2, | ||||||
|  |     Ssid = 1 << 4, | ||||||
|  |     SceneId = 1 << 5, | ||||||
|  |     IntentId = LocalCommunicationId | SceneId, | ||||||
|  |     NetworkId = IntentId | SessionId, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class NetworkType : u32 { | ||||||
|  |     None, | ||||||
|  |     General, | ||||||
|  |     Ldn, | ||||||
|  |     All, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class PackedNetworkType : u8 { | ||||||
|  |     None, | ||||||
|  |     General, | ||||||
|  |     Ldn, | ||||||
|  |     All, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class State : u32 { | ||||||
|  |     None, | ||||||
|  |     Initialized, | ||||||
|  |     AccessPointOpened, | ||||||
|  |     AccessPointCreated, | ||||||
|  |     StationOpened, | ||||||
|  |     StationConnected, | ||||||
|  |     Error, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class DisconnectReason : s16 { | ||||||
|  |     Unknown = -1, | ||||||
|  |     None, | ||||||
|  |     DisconnectedByUser, | ||||||
|  |     DisconnectedBySystem, | ||||||
|  |     DestroyedByUser, | ||||||
|  |     DestroyedBySystem, | ||||||
|  |     Rejected, | ||||||
|  |     SignalLost, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class NetworkError { | ||||||
|  |     Unknown = -1, | ||||||
|  |     None = 0, | ||||||
|  |     PortUnreachable, | ||||||
|  |     TooManyPlayers, | ||||||
|  |     VersionTooLow, | ||||||
|  |     VersionTooHigh, | ||||||
|  |     ConnectFailure, | ||||||
|  |     ConnectNotFound, | ||||||
|  |     ConnectTimeout, | ||||||
|  |     ConnectRejected, | ||||||
|  |     RejectFailed, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class AcceptPolicy : u8 { | ||||||
|  |     AcceptAll, | ||||||
|  |     RejectAll, | ||||||
|  |     BlackList, | ||||||
|  |     WhiteList, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class WifiChannel : s16 { | ||||||
|  |     Default = 0, | ||||||
|  |     wifi24_1 = 1, | ||||||
|  |     wifi24_6 = 6, | ||||||
|  |     wifi24_11 = 11, | ||||||
|  |     wifi50_36 = 36, | ||||||
|  |     wifi50_40 = 40, | ||||||
|  |     wifi50_44 = 44, | ||||||
|  |     wifi50_48 = 48, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class LinkLevel : s8 { | ||||||
|  |     Bad, | ||||||
|  |     Low, | ||||||
|  |     Good, | ||||||
|  |     Excelent, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct NodeLatestUpdate { | ||||||
|  |     NodeStateChange state_change; | ||||||
|  |     INSERT_PADDING_BYTES(0x7); // Unknown
 | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(NodeLatestUpdate) == 0x8, "NodeLatestUpdate is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct SessionId { | ||||||
|  |     u64 high; | ||||||
|  |     u64 low; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     bool operator==(const SessionId& b) const { | ||||||
|  |         return (low == b.low) && (high == b.high); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct IntentId { | ||||||
|  |     u64 local_communication_id; | ||||||
|  |     INSERT_PADDING_BYTES(0x2); // Reserved
 | ||||||
|  |     u16 scene_id; | ||||||
|  |     INSERT_PADDING_BYTES(0x4); // Reserved
 | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct NetworkId { | ||||||
|  |     IntentId intent_id; | ||||||
|  |     SessionId session_id; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct Ssid { | ||||||
|  |     u8 length; | ||||||
|  |     std::array<char, SsidLengthMax + 1> raw; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     std::string GetStringValue() const { | ||||||
|  |         return std::string(raw.data(), length); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(Ssid) == 0x22, "Ssid is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct Ipv4Address { | ||||||
|  |     union { | ||||||
|  |         u32 raw{}; | ||||||
|  |         std::array<u8, 4> bytes; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     std::string GetStringValue() const { | ||||||
|  |         return fmt::format("{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct MacAddress { | ||||||
|  |     std::array<u8, 6> raw{}; | ||||||
|  | 
 | ||||||
|  |     friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(MacAddress) == 0x6, "MacAddress is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct ScanFilter { | ||||||
|  |     NetworkId network_id; | ||||||
|  |     NetworkType network_type; | ||||||
|  |     MacAddress mac_address; | ||||||
|  |     Ssid ssid; | ||||||
|  |     INSERT_PADDING_BYTES(0x10); | ||||||
|  |     ScanFilterFlag flag; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(ScanFilter) == 0x60, "ScanFilter is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct CommonNetworkInfo { | ||||||
|  |     MacAddress bssid; | ||||||
|  |     Ssid ssid; | ||||||
|  |     WifiChannel channel; | ||||||
|  |     LinkLevel link_level; | ||||||
|  |     PackedNetworkType network_type; | ||||||
|  |     INSERT_PADDING_BYTES(0x4); | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct NodeInfo { | ||||||
|  |     Ipv4Address ipv4_address; | ||||||
|  |     MacAddress mac_address; | ||||||
|  |     s8 node_id; | ||||||
|  |     u8 is_connected; | ||||||
|  |     std::array<u8, UserNameBytesMax + 1> user_name; | ||||||
|  |     INSERT_PADDING_BYTES(0x1); // Reserved
 | ||||||
|  |     s16 local_communication_version; | ||||||
|  |     INSERT_PADDING_BYTES(0x10); // Reserved
 | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct LdnNetworkInfo { | ||||||
|  |     std::array<u8, 0x10> security_parameter; | ||||||
|  |     SecurityMode security_mode; | ||||||
|  |     AcceptPolicy station_accept_policy; | ||||||
|  |     u8 has_action_frame; | ||||||
|  |     INSERT_PADDING_BYTES(0x2); // Padding
 | ||||||
|  |     u8 node_count_max; | ||||||
|  |     u8 node_count; | ||||||
|  |     std::array<NodeInfo, NodeCountMax> nodes; | ||||||
|  |     INSERT_PADDING_BYTES(0x2); // Reserved
 | ||||||
|  |     u16 advertise_data_size; | ||||||
|  |     std::array<u8, AdvertiseDataSizeMax> advertise_data; | ||||||
|  |     INSERT_PADDING_BYTES(0x8C); // Reserved
 | ||||||
|  |     u64 random_authentication_id; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct NetworkInfo { | ||||||
|  |     NetworkId network_id; | ||||||
|  |     CommonNetworkInfo common; | ||||||
|  |     LdnNetworkInfo ldn; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct SecurityConfig { | ||||||
|  |     SecurityMode security_mode; | ||||||
|  |     u16 passphrase_size; | ||||||
|  |     std::array<u8, PassphraseLengthMax> passphrase; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(SecurityConfig) == 0x44, "SecurityConfig is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct UserConfig { | ||||||
|  |     std::array<u8, UserNameBytesMax + 1> user_name; | ||||||
|  |     INSERT_PADDING_BYTES(0xF); // Reserved
 | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(UserConfig) == 0x30, "UserConfig is an invalid size"); | ||||||
|  | 
 | ||||||
|  | #pragma pack(push, 4) | ||||||
|  | struct ConnectRequest { | ||||||
|  |     SecurityConfig security_config; | ||||||
|  |     UserConfig user_config; | ||||||
|  |     u32 local_communication_version; | ||||||
|  |     u32 option_unknown; | ||||||
|  |     NetworkInfo network_info; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(ConnectRequest) == 0x4FC, "ConnectRequest is an invalid size"); | ||||||
|  | #pragma pack(pop) | ||||||
|  | 
 | ||||||
|  | struct SecurityParameter { | ||||||
|  |     std::array<u8, 0x10> data; // Data, used with the same key derivation as SecurityConfig
 | ||||||
|  |     SessionId session_id; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(SecurityParameter) == 0x20, "SecurityParameter is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct NetworkConfig { | ||||||
|  |     IntentId intent_id; | ||||||
|  |     WifiChannel channel; | ||||||
|  |     u8 node_count_max; | ||||||
|  |     INSERT_PADDING_BYTES(0x1); // Reserved
 | ||||||
|  |     u16 local_communication_version; | ||||||
|  |     INSERT_PADDING_BYTES(0xA); // Reserved
 | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(NetworkConfig) == 0x20, "NetworkConfig is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct AddressEntry { | ||||||
|  |     Ipv4Address ipv4_address; | ||||||
|  |     MacAddress mac_address; | ||||||
|  |     INSERT_PADDING_BYTES(0x2); // Reserved
 | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(AddressEntry) == 0xC, "AddressEntry is an invalid size"); | ||||||
|  | 
 | ||||||
|  | struct AddressList { | ||||||
|  |     std::array<AddressEntry, 0x8> addresses; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size"); | ||||||
|  | 
 | ||||||
|  | } // namespace Service::LDN
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 FearlessTobi
						FearlessTobi