Skip to content
Snippets Groups Projects
Unverified Commit 95d96cfe authored by liamwhite's avatar liamwhite Committed by GitHub
Browse files

Merge pull request #12974 from german77/ldn-interface

service: ldn: Migrate and refractor service to new IPC
parents f75fceb3 2053ff96
No related branches found
No related tags found
No related merge requests found
Showing
with 910 additions and 778 deletions
......@@ -668,6 +668,18 @@ add_library(core STATIC
hle/service/ldn/ldn.h
hle/service/ldn/ldn_results.h
hle/service/ldn/ldn_types.h
hle/service/ldn/monitor_service.cpp
hle/service/ldn/monitor_service.h
hle/service/ldn/sf_monitor_service.cpp
hle/service/ldn/sf_monitor_service.h
hle/service/ldn/sf_service.cpp
hle/service/ldn/sf_service.h
hle/service/ldn/sf_service_monitor.cpp
hle/service/ldn/sf_service_monitor.h
hle/service/ldn/system_local_communication_service.cpp
hle/service/ldn/system_local_communication_service.h
hle/service/ldn/user_local_communication_service.cpp
hle/service/ldn/user_local_communication_service.h
hle/service/ldr/ldr.cpp
hle/service/ldr/ldr.h
hle/service/lm/lm.cpp
......
......@@ -85,15 +85,14 @@ Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network) const {
}
Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network,
std::vector<NodeLatestUpdate>& out_updates,
std::size_t buffer_count) {
if (buffer_count > NodeCountMax) {
std::span<NodeLatestUpdate> out_updates) {
if (out_updates.size() > NodeCountMax) {
return ResultInvalidBufferCount;
}
if (state == State::AccessPointCreated || state == State::StationConnected) {
std::memcpy(&out_network, &network_info, sizeof(network_info));
for (std::size_t i = 0; i < buffer_count; i++) {
for (std::size_t i = 0; i < out_updates.size(); i++) {
out_updates[i].state_change = node_changes[i].state_change;
node_changes[i].state_change = NodeStateChange::None;
}
......@@ -107,15 +106,8 @@ DisconnectReason LANDiscovery::GetDisconnectReason() const {
return disconnect_reason;
}
Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
Result LANDiscovery::Scan(std::span<NetworkInfo> out_networks, s16& out_count,
const ScanFilter& filter) {
if (!IsFlagSet(filter.flag, ScanFilterFlag::NetworkType) ||
filter.network_type <= NetworkType::All) {
if (!IsFlagSet(filter.flag, ScanFilterFlag::Ssid) && filter.ssid.length >= SsidLengthMax) {
return ResultBadInput;
}
}
{
std::scoped_lock lock{packet_mutex};
scan_results.clear();
......@@ -128,7 +120,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
std::scoped_lock lock{packet_mutex};
for (const auto& [key, info] : scan_results) {
if (count >= networks.size()) {
if (out_count >= static_cast<s16>(out_networks.size())) {
break;
}
......@@ -159,7 +151,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
}
}
networks[count++] = info;
out_networks[out_count++] = info;
}
return ResultSuccess;
......
......@@ -54,11 +54,10 @@ public:
void SetState(State new_state);
Result GetNetworkInfo(NetworkInfo& out_network) const;
Result GetNetworkInfo(NetworkInfo& out_network, std::vector<NodeLatestUpdate>& out_updates,
std::size_t buffer_count);
Result GetNetworkInfo(NetworkInfo& out_network, std::span<NodeLatestUpdate> out_updates);
DisconnectReason GetDisconnectReason() const;
Result Scan(std::vector<NetworkInfo>& networks, u16& count, const ScanFilter& filter);
Result Scan(std::span<NetworkInfo> out_networks, s16& out_count, const ScanFilter& filter);
Result SetAdvertiseData(std::span<const u8> data);
Result OpenAccessPoint();
......
This diff is collapsed.
......@@ -3,12 +3,6 @@
#pragma once
#include "core/hle/kernel/k_event.h"
#include "core/hle/result.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/sm/sm.h"
namespace Core {
class System;
}
......
......@@ -123,6 +123,18 @@ enum class NodeStatus : u8 {
Connected,
};
enum class WirelessControllerRestriction : u32 {
None,
Default,
};
struct ConnectOption {
union {
u32 raw;
};
};
static_assert(sizeof(ConnectOption) == 0x4, "ConnectOption is an invalid size");
struct NodeLatestUpdate {
NodeStateChange state_change;
INSERT_PADDING_BYTES(0x7); // Unknown
......@@ -139,9 +151,9 @@ static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
struct IntentId {
u64 local_communication_id;
INSERT_PADDING_BYTES(0x2); // Reserved
INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
u16 scene_id;
INSERT_PADDING_BYTES(0x4); // Reserved
INSERT_PADDING_BYTES_NOINIT(0x4); // Reserved
};
static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
......@@ -152,13 +164,14 @@ struct NetworkId {
static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
struct Ssid {
u8 length{};
std::array<char, SsidLengthMax + 1> raw{};
u8 length;
std::array<char, SsidLengthMax + 1> raw;
Ssid() = default;
constexpr explicit Ssid(std::string_view data) {
length = static_cast<u8>(std::min(data.size(), SsidLengthMax));
raw = {};
data.copy(raw.data(), length);
raw[length] = 0;
}
......@@ -181,7 +194,7 @@ using Ipv4Address = std::array<u8, 4>;
static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
struct MacAddress {
std::array<u8, 6> raw{};
std::array<u8, 6> raw;
friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
};
......@@ -211,7 +224,7 @@ struct CommonNetworkInfo {
WifiChannel channel;
LinkLevel link_level;
PackedNetworkType network_type;
INSERT_PADDING_BYTES(0x4);
INSERT_PADDING_BYTES_NOINIT(0x4);
};
static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
......@@ -221,9 +234,9 @@ struct NodeInfo {
s8 node_id;
u8 is_connected;
std::array<u8, UserNameBytesMax + 1> user_name;
INSERT_PADDING_BYTES(0x1); // Reserved
INSERT_PADDING_BYTES_NOINIT(0x1); // Reserved
s16 local_communication_version;
INSERT_PADDING_BYTES(0x10); // Reserved
INSERT_PADDING_BYTES_NOINIT(0x10); // Reserved
};
static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
......@@ -232,14 +245,14 @@ struct LdnNetworkInfo {
SecurityMode security_mode;
AcceptPolicy station_accept_policy;
u8 has_action_frame;
INSERT_PADDING_BYTES(0x2); // Padding
INSERT_PADDING_BYTES_NOINIT(0x2); // Padding
u8 node_count_max;
u8 node_count;
std::array<NodeInfo, NodeCountMax> nodes;
INSERT_PADDING_BYTES(0x2); // Reserved
INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
u16 advertise_data_size;
std::array<u8, AdvertiseDataSizeMax> advertise_data;
INSERT_PADDING_BYTES(0x8C); // Reserved
INSERT_PADDING_BYTES_NOINIT(0x8C); // Reserved
u64 random_authentication_id;
};
static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
......@@ -250,6 +263,7 @@ struct NetworkInfo {
LdnNetworkInfo ldn;
};
static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
static_assert(std::is_trivial_v<NetworkInfo>, "NetworkInfo type must be trivially copyable.");
struct SecurityConfig {
SecurityMode security_mode;
......@@ -303,4 +317,36 @@ struct AddressList {
};
static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
struct GroupInfo {
std::array<u8, 0x200> info;
};
struct CreateNetworkConfig {
SecurityConfig security_config;
UserConfig user_config;
INSERT_PADDING_BYTES(0x4);
NetworkConfig network_config;
};
static_assert(sizeof(CreateNetworkConfig) == 0x98, "CreateNetworkConfig is an invalid size");
#pragma pack(push, 4)
struct CreateNetworkConfigPrivate {
SecurityConfig security_config;
SecurityParameter security_parameter;
UserConfig user_config;
INSERT_PADDING_BYTES(0x4);
NetworkConfig network_config;
};
#pragma pack(pop)
static_assert(sizeof(CreateNetworkConfigPrivate) == 0xB8,
"CreateNetworkConfigPrivate is an invalid size");
struct ConnectNetworkData {
SecurityConfig security_config;
UserConfig user_config;
s32 local_communication_version;
ConnectOption option;
};
static_assert(sizeof(ConnectNetworkData) == 0x7c, "ConnectNetworkData is an invalid size");
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ldn/monitor_service.h"
namespace Service::LDN {
IMonitorService::IMonitorService(Core::System& system_)
: ServiceFramework{system_, "IMonitorService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, C<&IMonitorService::GetStateForMonitor>, "GetStateForMonitor"},
{1, nullptr, "GetNetworkInfoForMonitor"},
{2, nullptr, "GetIpv4AddressForMonitor"},
{3, nullptr, "GetDisconnectReasonForMonitor"},
{4, nullptr, "GetSecurityParameterForMonitor"},
{5, nullptr, "GetNetworkConfigForMonitor"},
{100, C<&IMonitorService::InitializeMonitor>, "InitializeMonitor"},
{101, nullptr, "FinalizeMonitor"},
};
// clang-format on
RegisterHandlers(functions);
}
IMonitorService::~IMonitorService() = default;
Result IMonitorService::GetStateForMonitor(Out<State> out_state) {
LOG_INFO(Service_LDN, "called");
*out_state = state;
R_SUCCEED();
}
Result IMonitorService::InitializeMonitor() {
LOG_INFO(Service_LDN, "called");
state = State::Initialized;
R_SUCCEED();
}
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ldn/ldn_types.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::LDN {
class IMonitorService final : public ServiceFramework<IMonitorService> {
public:
explicit IMonitorService(Core::System& system_);
~IMonitorService() override;
private:
Result GetStateForMonitor(Out<State> out_state);
Result InitializeMonitor();
State state{State::None};
};
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ldn/ldn_types.h"
#include "core/hle/service/ldn/sf_monitor_service.h"
namespace Service::LDN {
ISfMonitorService::ISfMonitorService(Core::System& system_)
: ServiceFramework{system_, "ISfMonitorService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, C<&ISfMonitorService::Initialize>, "Initialize"},
{288, C<&ISfMonitorService::GetGroupInfo>, "GetGroupInfo"},
{320, nullptr, "GetLinkLevel"},
};
// clang-format on
RegisterHandlers(functions);
}
ISfMonitorService::~ISfMonitorService() = default;
Result ISfMonitorService::Initialize(Out<u32> out_value) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
*out_value = 0;
R_SUCCEED();
}
Result ISfMonitorService::GetGroupInfo(
OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
*out_group_info = GroupInfo{};
R_SUCCEED();
}
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::LDN {
struct GroupInfo;
class ISfMonitorService final : public ServiceFramework<ISfMonitorService> {
public:
explicit ISfMonitorService(Core::System& system_);
~ISfMonitorService() override;
private:
Result Initialize(Out<u32> out_value);
Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
};
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/ldn/sf_service.h"
namespace Service::LDN {
ISfService::ISfService(Core::System& system_) : ServiceFramework{system_, "ISfService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Initialize"},
{256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
{264, nullptr, "GetNetworkInterfaceLastError"},
{272, nullptr, "GetRole"},
{280, nullptr, "GetAdvertiseData"},
{288, nullptr, "GetGroupInfo"},
{296, nullptr, "GetGroupInfo2"},
{304, nullptr, "GetGroupOwner"},
{312, nullptr, "GetIpConfig"},
{320, nullptr, "GetLinkLevel"},
{512, nullptr, "Scan"},
{768, nullptr, "CreateGroup"},
{776, nullptr, "DestroyGroup"},
{784, nullptr, "SetAdvertiseData"},
{1536, nullptr, "SendToOtherGroup"},
{1544, nullptr, "RecvFromOtherGroup"},
{1552, nullptr, "AddAcceptableGroupId"},
{1560, nullptr, "ClearAcceptableGroupId"},
};
// clang-format on
RegisterHandlers(functions);
}
ISfService::~ISfService() = default;
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::LDN {
class ISfService final : public ServiceFramework<ISfService> {
public:
explicit ISfService(Core::System& system_);
~ISfService() override;
};
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ldn/ldn_types.h"
#include "core/hle/service/ldn/sf_service_monitor.h"
namespace Service::LDN {
ISfServiceMonitor::ISfServiceMonitor(Core::System& system_)
: ServiceFramework{system_, "ISfServiceMonitor"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, C<&ISfServiceMonitor::Initialize>, "Initialize"},
{256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
{264, nullptr, "GetNetworkInterfaceLastError"},
{272, nullptr, "GetRole"},
{280, nullptr, "GetAdvertiseData"},
{281, nullptr, "GetAdvertiseData2"},
{288, C<&ISfServiceMonitor::GetGroupInfo>, "GetGroupInfo"},
{296, nullptr, "GetGroupInfo2"},
{304, nullptr, "GetGroupOwner"},
{312, nullptr, "GetIpConfig"},
{320, nullptr, "GetLinkLevel"},
{328, nullptr, "AttachJoinEvent"},
{336, nullptr, "GetMembers"},
};
// clang-format on
RegisterHandlers(functions);
}
ISfServiceMonitor::~ISfServiceMonitor() = default;
Result ISfServiceMonitor::Initialize(Out<u32> out_value) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
*out_value = 0;
R_SUCCEED();
}
Result ISfServiceMonitor::GetGroupInfo(
OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
*out_group_info = GroupInfo{};
R_SUCCEED();
}
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::LDN {
struct GroupInfo;
class ISfServiceMonitor final : public ServiceFramework<ISfServiceMonitor> {
public:
explicit ISfServiceMonitor(Core::System& system_);
~ISfServiceMonitor() override;
private:
Result Initialize(Out<u32> out_value);
Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
};
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ldn/system_local_communication_service.h"
namespace Service::LDN {
ISystemLocalCommunicationService::ISystemLocalCommunicationService(Core::System& system_)
: ServiceFramework{system_, "ISystemLocalCommunicationService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetState"},
{1, nullptr, "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"},
{104, nullptr, "SetWirelessControllerRestriction"},
{200, nullptr, "OpenAccessPoint"},
{201, nullptr, "CloseAccessPoint"},
{202, nullptr, "CreateNetwork"},
{203, nullptr, "CreateNetworkPrivate"},
{204, nullptr, "DestroyNetwork"},
{205, nullptr, "Reject"},
{206, nullptr, "SetAdvertiseData"},
{207, nullptr, "SetStationAcceptPolicy"},
{208, nullptr, "AddAcceptFilterEntry"},
{209, nullptr, "ClearAcceptFilter"},
{300, nullptr, "OpenStation"},
{301, nullptr, "CloseStation"},
{302, nullptr, "Connect"},
{303, nullptr, "ConnectPrivate"},
{304, nullptr, "Disconnect"},
{400, nullptr, "InitializeSystem"},
{401, nullptr, "FinalizeSystem"},
{402, nullptr, "SetOperationMode"},
{403, C<&ISystemLocalCommunicationService::InitializeSystem2>, "InitializeSystem2"},
};
// clang-format on
RegisterHandlers(functions);
}
ISystemLocalCommunicationService::~ISystemLocalCommunicationService() = default;
Result ISystemLocalCommunicationService::InitializeSystem2() {
LOG_WARNING(Service_LDN, "(STUBBED) called");
R_SUCCEED();
}
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::LDN {
class ISystemLocalCommunicationService final
: public ServiceFramework<ISystemLocalCommunicationService> {
public:
explicit ISystemLocalCommunicationService(Core::System& system_);
~ISystemLocalCommunicationService() override;
private:
Result InitializeSystem2();
};
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <memory>
#include "core/core.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ldn/ldn_results.h"
#include "core/hle/service/ldn/ldn_types.h"
#include "core/hle/service/ldn/user_local_communication_service.h"
#include "core/hle/service/server_manager.h"
#include "core/internal_network/network.h"
#include "core/internal_network/network_interface.h"
#include "network/network.h"
// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
#undef CreateEvent
namespace Service::LDN {
IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_)
: ServiceFramework{system_, "IUserLocalCommunicationService"},
service_context{system, "IUserLocalCommunicationService"},
room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
// clang-format off
static const FunctionInfo functions[] = {
{0, C<&IUserLocalCommunicationService::GetState>, "GetState"},
{1, C<&IUserLocalCommunicationService::GetNetworkInfo>, "GetNetworkInfo"},
{2, C<&IUserLocalCommunicationService::GetIpv4Address>, "GetIpv4Address"},
{3, C<&IUserLocalCommunicationService::GetDisconnectReason>, "GetDisconnectReason"},
{4, C<&IUserLocalCommunicationService::GetSecurityParameter>, "GetSecurityParameter"},
{5, C<&IUserLocalCommunicationService::GetNetworkConfig>, "GetNetworkConfig"},
{100, C<&IUserLocalCommunicationService::AttachStateChangeEvent>, "AttachStateChangeEvent"},
{101, C<&IUserLocalCommunicationService::GetNetworkInfoLatestUpdate>, "GetNetworkInfoLatestUpdate"},
{102, C<&IUserLocalCommunicationService::Scan>, "Scan"},
{103, C<&IUserLocalCommunicationService::ScanPrivate>, "ScanPrivate"},
{104, C<&IUserLocalCommunicationService::SetWirelessControllerRestriction>, "SetWirelessControllerRestriction"},
{200, C<&IUserLocalCommunicationService::OpenAccessPoint>, "OpenAccessPoint"},
{201, C<&IUserLocalCommunicationService::CloseAccessPoint>, "CloseAccessPoint"},
{202, C<&IUserLocalCommunicationService::CreateNetwork>, "CreateNetwork"},
{203, C<&IUserLocalCommunicationService::CreateNetworkPrivate>, "CreateNetworkPrivate"},
{204, C<&IUserLocalCommunicationService::DestroyNetwork>, "DestroyNetwork"},
{205, nullptr, "Reject"},
{206, C<&IUserLocalCommunicationService::SetAdvertiseData>, "SetAdvertiseData"},
{207, C<&IUserLocalCommunicationService::SetStationAcceptPolicy>, "SetStationAcceptPolicy"},
{208, C<&IUserLocalCommunicationService::AddAcceptFilterEntry>, "AddAcceptFilterEntry"},
{209, nullptr, "ClearAcceptFilter"},
{300, C<&IUserLocalCommunicationService::OpenStation>, "OpenStation"},
{301, C<&IUserLocalCommunicationService::CloseStation>, "CloseStation"},
{302, C<&IUserLocalCommunicationService::Connect>, "Connect"},
{303, nullptr, "ConnectPrivate"},
{304, C<&IUserLocalCommunicationService::Disconnect>, "Disconnect"},
{400, C<&IUserLocalCommunicationService::Initialize>, "Initialize"},
{401, C<&IUserLocalCommunicationService::Finalize>, "Finalize"},
{402, C<&IUserLocalCommunicationService::Initialize2>, "Initialize2"},
};
// clang-format on
RegisterHandlers(functions);
state_change_event =
service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
}
IUserLocalCommunicationService::~IUserLocalCommunicationService() {
if (is_initialized) {
if (auto room_member = room_network.GetRoomMember().lock()) {
room_member->Unbind(ldn_packet_received);
}
}
service_context.CloseEvent(state_change_event);
}
Result IUserLocalCommunicationService::GetState(Out<State> out_state) {
*out_state = State::Error;
if (is_initialized) {
*out_state = lan_discovery.GetState();
}
LOG_INFO(Service_LDN, "called, state={}", *out_state);
R_SUCCEED();
}
Result IUserLocalCommunicationService::GetNetworkInfo(
OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info) {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info));
}
Result IUserLocalCommunicationService::GetIpv4Address(Out<Ipv4Address> out_current_address,
Out<Ipv4Address> out_subnet_mask) {
LOG_INFO(Service_LDN, "called");
const auto network_interface = Network::GetSelectedNetworkInterface();
R_UNLESS(network_interface.has_value(), ResultNoIpAddress);
*out_current_address = {Network::TranslateIPv4(network_interface->ip_address)};
*out_subnet_mask = {Network::TranslateIPv4(network_interface->subnet_mask)};
// When we're connected to a room, spoof the hosts IP address
if (auto room_member = room_network.GetRoomMember().lock()) {
if (room_member->IsConnected()) {
*out_current_address = room_member->GetFakeIpAddress();
}
}
std::reverse(std::begin(*out_current_address), std::end(*out_current_address)); // ntohl
std::reverse(std::begin(*out_subnet_mask), std::end(*out_subnet_mask)); // ntohl
R_SUCCEED();
}
Result IUserLocalCommunicationService::GetDisconnectReason(
Out<DisconnectReason> out_disconnect_reason) {
LOG_INFO(Service_LDN, "called");
*out_disconnect_reason = lan_discovery.GetDisconnectReason();
R_SUCCEED();
}
Result IUserLocalCommunicationService::GetSecurityParameter(
Out<SecurityParameter> out_security_parameter) {
LOG_INFO(Service_LDN, "called");
NetworkInfo info{};
R_TRY(lan_discovery.GetNetworkInfo(info));
out_security_parameter->session_id = info.network_id.session_id;
std::memcpy(out_security_parameter->data.data(), info.ldn.security_parameter.data(),
sizeof(SecurityParameter::data));
R_SUCCEED();
}
Result IUserLocalCommunicationService::GetNetworkConfig(Out<NetworkConfig> out_network_config) {
LOG_INFO(Service_LDN, "called");
NetworkInfo info{};
R_TRY(lan_discovery.GetNetworkInfo(info));
out_network_config->intent_id = info.network_id.intent_id;
out_network_config->channel = info.common.channel;
out_network_config->node_count_max = info.ldn.node_count_max;
out_network_config->local_communication_version = info.ldn.nodes[0].local_communication_version;
R_SUCCEED();
}
Result IUserLocalCommunicationService::AttachStateChangeEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_LDN, "called");
*out_event = &state_change_event->GetReadableEvent();
R_SUCCEED();
}
Result IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(
OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update) {
LOG_INFO(Service_LDN, "called");
R_UNLESS(!out_node_latest_update.empty(), ResultBadInput);
R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info, out_node_latest_update));
}
Result IUserLocalCommunicationService::Scan(
Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
channel, scan_filter.flag, scan_filter.network_type);
R_UNLESS(!out_network_info.empty(), ResultBadInput);
R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
}
Result IUserLocalCommunicationService::ScanPrivate(
Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
channel, scan_filter.flag, scan_filter.network_type);
R_UNLESS(out_network_info.empty(), ResultBadInput);
R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
}
Result IUserLocalCommunicationService::SetWirelessControllerRestriction(
WirelessControllerRestriction wireless_restriction) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
R_SUCCEED();
}
Result IUserLocalCommunicationService::OpenAccessPoint() {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.OpenAccessPoint());
}
Result IUserLocalCommunicationService::CloseAccessPoint() {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.CloseAccessPoint());
}
Result IUserLocalCommunicationService::CreateNetwork(const CreateNetworkConfig& create_config) {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
create_config.network_config));
}
Result IUserLocalCommunicationService::CreateNetworkPrivate(
const CreateNetworkConfigPrivate& create_config,
InArray<AddressEntry, BufferAttr_HipcPointer> address_list) {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
create_config.network_config));
}
Result IUserLocalCommunicationService::DestroyNetwork() {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.DestroyNetwork());
}
Result IUserLocalCommunicationService::SetAdvertiseData(
InBuffer<BufferAttr_HipcAutoSelect> buffer_data) {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.SetAdvertiseData(buffer_data));
}
Result IUserLocalCommunicationService::SetStationAcceptPolicy(AcceptPolicy accept_policy) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
R_SUCCEED();
}
Result IUserLocalCommunicationService::AddAcceptFilterEntry(MacAddress mac_address) {
LOG_WARNING(Service_LDN, "(STUBBED) called");
R_SUCCEED();
}
Result IUserLocalCommunicationService::OpenStation() {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.OpenStation());
}
Result IUserLocalCommunicationService::CloseStation() {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.CloseStation());
}
Result IUserLocalCommunicationService::Connect(
const ConnectNetworkData& connect_data,
InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info) {
LOG_INFO(Service_LDN,
"called, passphrase_size={}, security_mode={}, "
"local_communication_version={}",
connect_data.security_config.passphrase_size,
connect_data.security_config.security_mode, connect_data.local_communication_version);
R_RETURN(lan_discovery.Connect(*network_info, connect_data.user_config,
static_cast<u16>(connect_data.local_communication_version)));
}
Result IUserLocalCommunicationService::Disconnect() {
LOG_INFO(Service_LDN, "called");
R_RETURN(lan_discovery.Disconnect());
}
Result IUserLocalCommunicationService::Initialize(ClientProcessId aruid) {
LOG_INFO(Service_LDN, "called, process_id={}", aruid.pid);
const auto network_interface = Network::GetSelectedNetworkInterface();
R_UNLESS(network_interface, ResultAirplaneModeEnabled);
if (auto room_member = room_network.GetRoomMember().lock()) {
ldn_packet_received = room_member->BindOnLdnPacketReceived(
[this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
} else {
LOG_ERROR(Service_LDN, "Couldn't bind callback!");
R_RETURN(ResultAirplaneModeEnabled);
}
lan_discovery.Initialize([&]() { OnEventFired(); });
is_initialized = true;
R_SUCCEED();
}
Result IUserLocalCommunicationService::Finalize() {
LOG_INFO(Service_LDN, "called");
if (auto room_member = room_network.GetRoomMember().lock()) {
room_member->Unbind(ldn_packet_received);
}
is_initialized = false;
R_RETURN(lan_discovery.Finalize());
}
Result IUserLocalCommunicationService::Initialize2(u32 version, ClientProcessId process_id) {
LOG_INFO(Service_LDN, "called, version={}, process_id={}", version, process_id.pid);
R_RETURN(Initialize(process_id));
}
void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacket& packet) {
lan_discovery.ReceivePacket(packet);
}
void IUserLocalCommunicationService::OnEventFired() {
state_change_event->Signal();
}
} // namespace Service::LDN
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/ldn/lan_discovery.h"
#include "core/hle/service/ldn/ldn_types.h"
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Network {
class RoomNetwork;
}
namespace Service::LDN {
class IUserLocalCommunicationService final
: public ServiceFramework<IUserLocalCommunicationService> {
public:
explicit IUserLocalCommunicationService(Core::System& system_);
~IUserLocalCommunicationService() override;
private:
Result GetState(Out<State> out_state);
Result GetNetworkInfo(OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info);
Result GetIpv4Address(Out<Ipv4Address> out_current_address, Out<Ipv4Address> out_subnet_mask);
Result GetDisconnectReason(Out<DisconnectReason> out_disconnect_reason);
Result GetSecurityParameter(Out<SecurityParameter> out_security_parameter);
Result GetNetworkConfig(Out<NetworkConfig> out_network_config);
Result AttachStateChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetNetworkInfoLatestUpdate(
OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update);
Result Scan(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
Result ScanPrivate(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
Result SetWirelessControllerRestriction(WirelessControllerRestriction wireless_restriction);
Result OpenAccessPoint();
Result CloseAccessPoint();
Result CreateNetwork(const CreateNetworkConfig& create_network_Config);
Result CreateNetworkPrivate(const CreateNetworkConfigPrivate& create_network_Config,
InArray<AddressEntry, BufferAttr_HipcPointer> address_list);
Result DestroyNetwork();
Result SetAdvertiseData(InBuffer<BufferAttr_HipcAutoSelect> buffer_data);
Result SetStationAcceptPolicy(AcceptPolicy accept_policy);
Result AddAcceptFilterEntry(MacAddress mac_address);
Result OpenStation();
Result CloseStation();
Result Connect(const ConnectNetworkData& connect_data,
InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info);
Result Disconnect();
Result Initialize(ClientProcessId aruid);
Result Finalize();
Result Initialize2(u32 version, ClientProcessId aruid);
private:
/// Callback to parse and handle a received LDN packet.
void OnLDNPacketReceived(const Network::LDNPacket& packet);
void OnEventFired();
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* state_change_event;
Network::RoomNetwork& room_network;
LANDiscovery lan_discovery;
// Callback identifier for the OnLDNPacketReceived event.
Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
bool is_initialized{};
};
} // namespace Service::LDN
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment