mirror of
https://git.citron-emu.org/citron/emulator
synced 2026-01-25 12:13:27 +00:00
service/ldn: Implement SetProtocol and SetWirelessAudioPolicy commands
Adds support for LDN service commands introduced in firmware 20.0.0+: - Command 105: SetWirelessAudioPolicy (stubbed) - Command 106: SetProtocol This enables ACNH Update 3.0 and other games using newer SDK versions to properly initialize LDN for local multiplayer functionality. Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -128,6 +129,21 @@ enum class WirelessControllerRestriction : u32 {
|
||||
Default,
|
||||
};
|
||||
|
||||
enum class WirelessAudioRestriction : u32 {
|
||||
Disabled,
|
||||
Enabled,
|
||||
};
|
||||
|
||||
// Protocol enum for SetProtocol command (18.0.0+)
|
||||
// On NX, permission bitmask is 0xA (allows Protocol 1 and 3 only)
|
||||
enum class Protocol : u32 {
|
||||
Default = 0,
|
||||
NX = 1,
|
||||
// S2 = 2, // Switch 2 only
|
||||
NXAndOunce = 3,
|
||||
// S2_Alt = 4, // Switch 2 only
|
||||
};
|
||||
|
||||
struct ConnectOption {
|
||||
union {
|
||||
u32 raw;
|
||||
|
||||
@@ -22,6 +22,8 @@ ISystemLocalCommunicationService::ISystemLocalCommunicationService(Core::System&
|
||||
{102, D<&ISystemLocalCommunicationService::Scan>, "Scan"},
|
||||
{103, D<&ISystemLocalCommunicationService::ScanPrivate>, "ScanPrivate"},
|
||||
{104, D<&ISystemLocalCommunicationService::SetWirelessControllerRestriction>, "SetWirelessControllerRestriction"},
|
||||
{105, D<&ISystemLocalCommunicationService::SetWirelessAudioPolicy>, "SetWirelessAudioPolicy"},
|
||||
{106, D<&ISystemLocalCommunicationService::SetProtocol>, "SetProtocol"},
|
||||
{200, D<&ISystemLocalCommunicationService::OpenAccessPoint>, "OpenAccessPoint"},
|
||||
{201, D<&ISystemLocalCommunicationService::CloseAccessPoint>, "CloseAccessPoint"},
|
||||
{202, D<&ISystemLocalCommunicationService::CreateNetwork>, "CreateNetwork"},
|
||||
@@ -116,7 +118,38 @@ Result ISystemLocalCommunicationService::ScanPrivate(Out<s16> network_count, Wif
|
||||
}
|
||||
|
||||
Result ISystemLocalCommunicationService::SetWirelessControllerRestriction(WirelessControllerRestriction wireless_restriction) {
|
||||
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||
LOG_WARNING(Service_LDN, "(STUBBED) called, wireless_restriction={}",
|
||||
static_cast<u32>(wireless_restriction));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemLocalCommunicationService::SetWirelessAudioPolicy(WirelessAudioRestriction wireless_audio_restriction) {
|
||||
LOG_WARNING(Service_LDN, "(STUBBED) called, wireless_audio_restriction={}",
|
||||
static_cast<u32>(wireless_audio_restriction));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemLocalCommunicationService::SetProtocol(Protocol protocol) {
|
||||
LOG_INFO(Service_LDN, "called, protocol={}", static_cast<u32>(protocol));
|
||||
|
||||
// On NX, the protocol permission bitmask is 0xA (allows 1 and 3)
|
||||
// The SDK passes value 1 for Protocol 0/1, and 3 is passed directly if specified
|
||||
// Input must be non-zero, and BIT(input) must be set in permission bitmask
|
||||
const u32 protocol_value = static_cast<u32>(protocol);
|
||||
|
||||
// For NX compatibility, we accept protocols 1 (NX) and 3 (NXAndOunce)
|
||||
// Protocol 0 (Default) is typically converted to 1 by the SDK before calling
|
||||
if (protocol_value == 0) {
|
||||
// Default is treated as NX
|
||||
current_protocol = Protocol::NX;
|
||||
} else if (protocol_value == 1 || protocol_value == 3) {
|
||||
current_protocol = protocol;
|
||||
} else {
|
||||
// Invalid protocol for NX - but we'll accept it as a stub
|
||||
LOG_WARNING(Service_LDN, "Invalid protocol value {} for NX, accepting anyway", protocol_value);
|
||||
current_protocol = protocol;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ private:
|
||||
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 SetWirelessAudioPolicy(WirelessAudioRestriction wireless_audio_restriction);
|
||||
Result SetProtocol(Protocol protocol);
|
||||
Result OpenAccessPoint();
|
||||
Result CloseAccessPoint();
|
||||
Result CreateNetwork(const CreateNetworkConfig& create_config);
|
||||
@@ -61,6 +63,8 @@ private:
|
||||
Result FinalizeSystem();
|
||||
Result SetOperationMode(u32 mode);
|
||||
Result InitializeSystem2();
|
||||
|
||||
Protocol current_protocol{Protocol::NX};
|
||||
};
|
||||
|
||||
} // namespace Service::LDN
|
||||
|
||||
@@ -37,6 +37,8 @@ IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& sys
|
||||
{102, D<&IUserLocalCommunicationService::Scan>, "Scan"},
|
||||
{103, D<&IUserLocalCommunicationService::ScanPrivate>, "ScanPrivate"},
|
||||
{104, D<&IUserLocalCommunicationService::SetWirelessControllerRestriction>, "SetWirelessControllerRestriction"},
|
||||
{105, D<&IUserLocalCommunicationService::SetWirelessAudioPolicy>, "SetWirelessAudioPolicy"},
|
||||
{106, D<&IUserLocalCommunicationService::SetProtocol>, "SetProtocol"},
|
||||
{200, D<&IUserLocalCommunicationService::OpenAccessPoint>, "OpenAccessPoint"},
|
||||
{201, D<&IUserLocalCommunicationService::CloseAccessPoint>, "CloseAccessPoint"},
|
||||
{202, D<&IUserLocalCommunicationService::CreateNetwork>, "CreateNetwork"},
|
||||
@@ -189,7 +191,39 @@ Result IUserLocalCommunicationService::ScanPrivate(
|
||||
|
||||
Result IUserLocalCommunicationService::SetWirelessControllerRestriction(
|
||||
WirelessControllerRestriction wireless_restriction) {
|
||||
LOG_WARNING(Service_LDN, "(STUBBED) called");
|
||||
LOG_WARNING(Service_LDN, "(STUBBED) called, wireless_restriction={}",
|
||||
static_cast<u32>(wireless_restriction));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IUserLocalCommunicationService::SetWirelessAudioPolicy(
|
||||
WirelessAudioRestriction wireless_audio_restriction) {
|
||||
LOG_WARNING(Service_LDN, "(STUBBED) called, wireless_audio_restriction={}",
|
||||
static_cast<u32>(wireless_audio_restriction));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IUserLocalCommunicationService::SetProtocol(Protocol protocol) {
|
||||
LOG_INFO(Service_LDN, "called, protocol={}", static_cast<u32>(protocol));
|
||||
|
||||
// On NX, the protocol permission bitmask is 0xA (allows 1 and 3)
|
||||
// The SDK passes value 1 for Protocol 0/1, and 3 is passed directly if specified
|
||||
// Input must be non-zero, and BIT(input) must be set in permission bitmask
|
||||
const u32 protocol_value = static_cast<u32>(protocol);
|
||||
|
||||
// For NX compatibility, we accept protocols 1 (NX) and 3 (NXAndOunce)
|
||||
// Protocol 0 (Default) is typically converted to 1 by the SDK before calling
|
||||
if (protocol_value == 0) {
|
||||
// Default is treated as NX
|
||||
current_protocol = Protocol::NX;
|
||||
} else if (protocol_value == 1 || protocol_value == 3) {
|
||||
current_protocol = protocol;
|
||||
} else {
|
||||
// Invalid protocol for NX - but we'll accept it as a stub
|
||||
LOG_WARNING(Service_LDN, "Invalid protocol value {} for NX, accepting anyway", protocol_value);
|
||||
current_protocol = protocol;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ private:
|
||||
|
||||
Result SetWirelessControllerRestriction(WirelessControllerRestriction wireless_restriction);
|
||||
|
||||
Result SetWirelessAudioPolicy(WirelessAudioRestriction wireless_audio_restriction);
|
||||
|
||||
Result SetProtocol(Protocol protocol);
|
||||
|
||||
Result OpenAccessPoint();
|
||||
|
||||
Result CloseAccessPoint();
|
||||
@@ -106,6 +110,7 @@ private:
|
||||
Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
|
||||
|
||||
bool is_initialized{};
|
||||
Protocol current_protocol{Protocol::NX};
|
||||
};
|
||||
|
||||
} // namespace Service::LDN
|
||||
|
||||
Reference in New Issue
Block a user