Merge pull request #8731 from FearlessTobi/better-ldn
ldn: Add better stubs and more data types
This commit is contained in:
		| @@ -502,9 +502,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,15 @@ | |||||||
|  |  | ||||||
| #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/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 { | namespace Service::LDN { | ||||||
|  |  | ||||||
| @@ -100,74 +104,418 @@ class IUserLocalCommunicationService final | |||||||
|     : public ServiceFramework<IUserLocalCommunicationService> { |     : public ServiceFramework<IUserLocalCommunicationService> { | ||||||
| public: | public: | ||||||
|     explicit IUserLocalCommunicationService(Core::System& system_) |     explicit IUserLocalCommunicationService(Core::System& system_) | ||||||
|         : ServiceFramework{system_, "IUserLocalCommunicationService"} { |         : ServiceFramework{system_, "IUserLocalCommunicationService", ServiceThreadType::CreateNew}, | ||||||
|  |           service_context{system, "IUserLocalCommunicationService"}, room_network{ | ||||||
|  |                                                                          system_.GetRoomNetwork()} { | ||||||
|         // 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); | ||||||
|  |  | ||||||
|  |         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) { |     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}; |         IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|  |         rb.Push(ResultSuccess); | ||||||
|  |         rb.PushEnum(state); | ||||||
|  |     } | ||||||
|  |  | ||||||
|         // Indicate a network error, as we do not actually emulate LDN |     void GetNetworkInfo(Kernel::HLERequestContext& ctx) { | ||||||
|         rb.Push(static_cast<u32>(State::Error)); |         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); |         rb.Push(ResultSuccess); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Initialize2(Kernel::HLERequestContext& ctx) { |     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}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(ERROR_DISABLED); |         rb.Push(rc); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| private: |     Result InitializeImpl(Kernel::HLERequestContext& ctx) { | ||||||
|     enum class State { |         const auto network_interface = Network::GetSelectedNetworkInterface(); | ||||||
|         None, |         if (!network_interface) { | ||||||
|         Initialized, |             LOG_ERROR(Service_LDN, "No network interface is set"); | ||||||
|         AccessPointOpened, |             return ResultAirplaneModeEnabled; | ||||||
|         AccessPointCreated, |         } | ||||||
|         StationOpened, |  | ||||||
|         StationConnected, |         is_initialized = true; | ||||||
|         Error, |         // 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{}; |     bool is_initialized{}; | ||||||
| }; | }; | ||||||
| @@ -273,7 +621,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,12 @@ | |||||||
|  |  | ||||||
| #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/sm/sm.h" | ||||||
|  |  | ||||||
| namespace Core { | namespace Core { | ||||||
| class System; | 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 | ||||||
		Reference in New Issue
	
	Block a user