mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	Merge pull request #8731 from FearlessTobi/better-ldn
ldn: Add better stubs and more data types
This commit is contained in:
		
						commit
						536626fdd6
					
				| @ -502,9 +502,10 @@ add_library(core STATIC | ||||
|     hle/service/jit/jit.h | ||||
|     hle/service/lbl/lbl.cpp | ||||
|     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.h | ||||
|     hle/service/ldn/ldn_types.h | ||||
|     hle/service/ldr/ldr.cpp | ||||
|     hle/service/ldr/ldr.h | ||||
|     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,15 @@ | ||||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "core/hle/ipc_helpers.h" | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/service/ldn/errors.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/ldn/ldn.h" | ||||
| #include "core/hle/service/sm/sm.h" | ||||
| #include "core/hle/service/ldn/ldn_results.h" | ||||
| #include "core/hle/service/ldn/ldn_types.h" | ||||
| #include "core/internal_network/network.h" | ||||
| #include "core/internal_network/network_interface.h" | ||||
| 
 | ||||
| // This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
 | ||||
| #undef CreateEvent | ||||
| 
 | ||||
| namespace Service::LDN { | ||||
| 
 | ||||
| @ -100,74 +104,418 @@ class IUserLocalCommunicationService final | ||||
|     : public ServiceFramework<IUserLocalCommunicationService> { | ||||
| public: | ||||
|     explicit IUserLocalCommunicationService(Core::System& system_) | ||||
|         : ServiceFramework{system_, "IUserLocalCommunicationService"} { | ||||
|         : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew}, | ||||
|           service_context{system, "IUserLocalCommunicationService"}, room_network{ | ||||
|                                                                          system_.GetRoomNetwork()} { | ||||
|         // clang-format off
 | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {0, &IUserLocalCommunicationService::GetState, "GetState"}, | ||||
|             {1, nullptr, "GetNetworkInfo"}, | ||||
|             {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"}, | ||||
|             {2, nullptr, "GetIpv4Address"}, | ||||
|             {3, nullptr, "GetDisconnectReason"}, | ||||
|             {4, nullptr, "GetSecurityParameter"}, | ||||
|             {5, nullptr, "GetNetworkConfig"}, | ||||
|             {100, nullptr, "AttachStateChangeEvent"}, | ||||
|             {101, nullptr, "GetNetworkInfoLatestUpdate"}, | ||||
|             {102, nullptr, "Scan"}, | ||||
|             {103, nullptr, "ScanPrivate"}, | ||||
|             {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"}, | ||||
|             {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"}, | ||||
|             {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"}, | ||||
|             {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"}, | ||||
|             {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"}, | ||||
|             {102, &IUserLocalCommunicationService::Scan, "Scan"}, | ||||
|             {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"}, | ||||
|             {104, nullptr, "SetWirelessControllerRestriction"}, | ||||
|             {200, nullptr, "OpenAccessPoint"}, | ||||
|             {201, nullptr, "CloseAccessPoint"}, | ||||
|             {202, nullptr, "CreateNetwork"}, | ||||
|             {203, nullptr, "CreateNetworkPrivate"}, | ||||
|             {204, nullptr, "DestroyNetwork"}, | ||||
|             {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"}, | ||||
|             {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"}, | ||||
|             {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"}, | ||||
|             {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"}, | ||||
|             {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"}, | ||||
|             {205, nullptr, "Reject"}, | ||||
|             {206, nullptr, "SetAdvertiseData"}, | ||||
|             {207, nullptr, "SetStationAcceptPolicy"}, | ||||
|             {208, nullptr, "AddAcceptFilterEntry"}, | ||||
|             {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"}, | ||||
|             {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"}, | ||||
|             {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"}, | ||||
|             {209, nullptr, "ClearAcceptFilter"}, | ||||
|             {300, nullptr, "OpenStation"}, | ||||
|             {301, nullptr, "CloseStation"}, | ||||
|             {302, nullptr, "Connect"}, | ||||
|             {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"}, | ||||
|             {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"}, | ||||
|             {302, &IUserLocalCommunicationService::Connect, "Connect"}, | ||||
|             {303, nullptr, "ConnectPrivate"}, | ||||
|             {304, nullptr, "Disconnect"}, | ||||
|             {400, nullptr, "Initialize"}, | ||||
|             {401, nullptr, "Finalize"}, | ||||
|             {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, // 7.0.0+
 | ||||
|             {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"}, | ||||
|             {400, &IUserLocalCommunicationService::Initialize, "Initialize"}, | ||||
|             {401, &IUserLocalCommunicationService::Finalize, "Finalize"}, | ||||
|             {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, | ||||
|         }; | ||||
|         // clang-format on
 | ||||
| 
 | ||||
|         RegisterHandlers(functions); | ||||
| 
 | ||||
|         state_change_event = | ||||
|             service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent"); | ||||
|     } | ||||
| 
 | ||||
|     ~IUserLocalCommunicationService() { | ||||
|         service_context.CloseEvent(state_change_event); | ||||
|     } | ||||
| 
 | ||||
|     void OnEventFired() { | ||||
|         state_change_event->GetWritableEvent().Signal(); | ||||
|     } | ||||
| 
 | ||||
|     void GetState(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
|         State state = State::Error; | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called, state = {}", state); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 3}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushEnum(state); | ||||
|     } | ||||
| 
 | ||||
|         // Indicate a network error, as we do not actually emulate LDN
 | ||||
|         rb.Push(static_cast<u32>(State::Error)); | ||||
|     void 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; | ||||
|         } | ||||
| 
 | ||||
|         NetworkInfo network_info{}; | ||||
|         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={}", | ||||
|                     network_info.common.ssid.GetStringValue(), network_info.ldn.node_count); | ||||
| 
 | ||||
|         ctx.WriteBuffer<NetworkInfo>(network_info); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(rc); | ||||
|     } | ||||
| 
 | ||||
|     void 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 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 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 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 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(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}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void Scan(Kernel::HLERequestContext& ctx) { | ||||
|         ScanImpl(ctx); | ||||
|     } | ||||
| 
 | ||||
|     void ScanPrivate(Kernel::HLERequestContext& ctx) { | ||||
|         ScanImpl(ctx, true); | ||||
|     } | ||||
| 
 | ||||
|     void ScanImpl(Kernel::HLERequestContext& ctx, bool is_private = false) { | ||||
|         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; | ||||
|         } | ||||
| 
 | ||||
|         u16 count = 0; | ||||
|         std::vector<NetworkInfo> network_infos(network_info_size); | ||||
| 
 | ||||
|         LOG_WARNING(Service_LDN, | ||||
|                     "(STUBBED) called, channel={}, filter_scan_flag={}, filter_network_type={}", | ||||
|                     channel, scan_filter.flag, scan_filter.network_type); | ||||
| 
 | ||||
|         ctx.WriteBuffer(network_infos); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 3}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.Push<u32>(count); | ||||
|     } | ||||
| 
 | ||||
|     void OpenAccessPoint(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void CloseAccessPoint(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void CreateNetwork(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         struct Parameters { | ||||
|             SecurityConfig security_config; | ||||
|             UserConfig user_config; | ||||
|             INSERT_PADDING_WORDS_NOINIT(1); | ||||
|             NetworkConfig network_config; | ||||
|         }; | ||||
|         static_assert(sizeof(Parameters) == 0x98, "Parameters has incorrect size."); | ||||
| 
 | ||||
|         const auto parameters{rp.PopRaw<Parameters>()}; | ||||
| 
 | ||||
|         LOG_WARNING(Service_LDN, | ||||
|                     "(STUBBED) called, passphrase_size={}, security_mode={}, " | ||||
|                     "local_communication_version={}", | ||||
|                     parameters.security_config.passphrase_size, | ||||
|                     parameters.security_config.security_mode, | ||||
|                     parameters.network_config.local_communication_version); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void CreateNetworkPrivate(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         struct Parameters { | ||||
|             SecurityConfig security_config; | ||||
|             SecurityParameter security_parameter; | ||||
|             UserConfig user_config; | ||||
|             NetworkConfig network_config; | ||||
|         }; | ||||
|         static_assert(sizeof(Parameters) == 0xB8, "Parameters has incorrect size."); | ||||
| 
 | ||||
|         const auto parameters{rp.PopRaw<Parameters>()}; | ||||
| 
 | ||||
|         LOG_WARNING(Service_LDN, | ||||
|                     "(STUBBED) called, passphrase_size={}, security_mode={}, " | ||||
|                     "local_communication_version={}", | ||||
|                     parameters.security_config.passphrase_size, | ||||
|                     parameters.security_config.security_mode, | ||||
|                     parameters.network_config.local_communication_version); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void DestroyNetwork(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void 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 SetStationAcceptPolicy(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void AddAcceptFilterEntry(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void OpenStation(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void CloseStation(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void Connect(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         struct Parameters { | ||||
|             SecurityConfig security_config; | ||||
|             UserConfig user_config; | ||||
|             u32 local_communication_version; | ||||
|             u32 option; | ||||
|         }; | ||||
|         static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size."); | ||||
| 
 | ||||
|         const auto parameters{rp.PopRaw<Parameters>()}; | ||||
| 
 | ||||
|         LOG_WARNING(Service_LDN, | ||||
|                     "(STUBBED) called, passphrase_size={}, security_mode={}, " | ||||
|                     "local_communication_version={}", | ||||
|                     parameters.security_config.passphrase_size, | ||||
|                     parameters.security_config.security_mode, | ||||
|                     parameters.local_communication_version); | ||||
| 
 | ||||
|         const std::vector<u8> read_buffer = ctx.ReadBuffer(); | ||||
|         NetworkInfo network_info{}; | ||||
| 
 | ||||
|         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(&network_info, read_buffer.data(), read_buffer.size()); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void Disconnect(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
|     void Initialize(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         const auto rc = InitializeImpl(ctx); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(rc); | ||||
|     } | ||||
| 
 | ||||
|     void Finalize(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         is_initialized = false; | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void Initialize2(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_LDN, "called"); | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         is_initialized = true; | ||||
|         const auto rc = InitializeImpl(ctx); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ERROR_DISABLED); | ||||
|         rb.Push(rc); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     enum class State { | ||||
|         None, | ||||
|         Initialized, | ||||
|         AccessPointOpened, | ||||
|         AccessPointCreated, | ||||
|         StationOpened, | ||||
|         StationConnected, | ||||
|         Error, | ||||
|     }; | ||||
|     Result InitializeImpl(Kernel::HLERequestContext& ctx) { | ||||
|         const auto network_interface = Network::GetSelectedNetworkInterface(); | ||||
|         if (!network_interface) { | ||||
|             LOG_ERROR(Service_LDN, "No network interface is set"); | ||||
|             return ResultAirplaneModeEnabled; | ||||
|         } | ||||
| 
 | ||||
|         is_initialized = true; | ||||
|         // TODO (flTobi): Change this to ResultSuccess when LDN is fully implemented
 | ||||
|         return ResultAirplaneModeEnabled; | ||||
|     } | ||||
| 
 | ||||
|     KernelHelpers::ServiceContext service_context; | ||||
|     Kernel::KEvent* state_change_event; | ||||
|     Network::RoomNetwork& room_network; | ||||
| 
 | ||||
|     bool is_initialized{}; | ||||
| }; | ||||
| @ -273,7 +621,7 @@ public: | ||||
|         LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ERROR_DISABLED); | ||||
|         rb.Push(ResultDisabled); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -3,6 +3,12 @@ | ||||
| 
 | ||||
| #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/sm/sm.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
							
								
								
									
										27
									
								
								src/core/hle/service/ldn/ldn_results.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/core/hle/service/ldn/ldn_results.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-3.0-or-later
 | ||||
| 
 | ||||
| #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
 | ||||
							
								
								
									
										284
									
								
								src/core/hle/service/ldn/ldn_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								src/core/hle/service/ldn/ldn_types.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,284 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-3.0-or-later
 | ||||
| 
 | ||||
| #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, | ||||
| }; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
|     bool operator==(const SessionId&) const = default; | ||||
| }; | ||||
| 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; | ||||
| 
 | ||||
|     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; | ||||
|     }; | ||||
| 
 | ||||
|     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…
	
		Reference in New Issue
	
	Block a user