From ec670d881cc8f0d256dd86f5bdb40386d012f8d6 Mon Sep 17 00:00:00 2001 From: Zephyron Date: Sat, 1 Nov 2025 18:47:15 +1000 Subject: [PATCH] hle: Improve network service implementations and add newer firmware stubs AM (Application Manager): - Implement GetPseudoDeviceId with deterministic UUID generation - Generate persistent device ID based on program ID for online play LDN (Local Network): - Implement stub for Reject (cmd 205) - Implement stub for ClearAcceptFilter (cmd 209) - Implement stub for ConnectPrivate (cmd 303) NIFM (Network Interface): - Fix RequestState enum values (Invalid=0, Free=1) per switchbrew - Add ConnectionConfirmationOption enum - Update NotSubmitted references to Free state - Implement 13 new stub functions for firmware 18.0.0-20.0.0+ - Reduce log verbosity for frequently-called functions BSD (Sockets): - Improve RegisterClient to parse LibraryConfigData structure - Enhance socket operation logging (Socket, Bind, Connect) - Add detailed error logging for bind/connect failures - Implement stubs for Unknown36-38 (18.0.0+) - Add firmware version comments for commands Signed-off-by: Zephyron --- .../am/service/application_functions.cpp | 13 +- .../ldn/user_local_communication_service.cpp | 28 +++- .../ldn/user_local_communication_service.h | 8 + src/core/hle/service/nifm/nifm.cpp | 142 +++++++++++++++++- src/core/hle/service/nifm/nifm.h | 13 ++ src/core/hle/service/sockets/bsd.cpp | 98 ++++++++++-- src/core/hle/service/sockets/bsd.h | 13 +- 7 files changed, 285 insertions(+), 30 deletions(-) diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp index 0d005dec5..5b78d850a 100644 --- a/src/core/hle/service/am/service/application_functions.cpp +++ b/src/core/hle/service/am/service/application_functions.cpp @@ -362,8 +362,17 @@ Result IApplicationFunctions::NotifyRunning(Out out_became_running) { } Result IApplicationFunctions::GetPseudoDeviceId(Out out_pseudo_device_id) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - *out_pseudo_device_id = {}; + LOG_DEBUG(Service_AM, "called"); + + // Generate a persistent pseudo device ID for online play and telemetry + // Based on hardware/system info for consistency across sessions + // Using MakeRandomWithSeed to ensure deterministic generation + const u32 device_seed = static_cast(system.GetApplicationProcessProgramID()); + *out_pseudo_device_id = Common::UUID::MakeRandomWithSeed(device_seed); + + LOG_DEBUG(Service_AM, "Generated PseudoDeviceId: {}", + out_pseudo_device_id->FormattedString()); + R_SUCCEED(); } diff --git a/src/core/hle/service/ldn/user_local_communication_service.cpp b/src/core/hle/service/ldn/user_local_communication_service.cpp index c29584550..5e69a9054 100644 --- a/src/core/hle/service/ldn/user_local_communication_service.cpp +++ b/src/core/hle/service/ldn/user_local_communication_service.cpp @@ -42,15 +42,15 @@ IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& sys {202, D<&IUserLocalCommunicationService::CreateNetwork>, "CreateNetwork"}, {203, D<&IUserLocalCommunicationService::CreateNetworkPrivate>, "CreateNetworkPrivate"}, {204, D<&IUserLocalCommunicationService::DestroyNetwork>, "DestroyNetwork"}, - {205, nullptr, "Reject"}, + {205, D<&IUserLocalCommunicationService::Reject>, "Reject"}, {206, D<&IUserLocalCommunicationService::SetAdvertiseData>, "SetAdvertiseData"}, {207, D<&IUserLocalCommunicationService::SetStationAcceptPolicy>, "SetStationAcceptPolicy"}, {208, D<&IUserLocalCommunicationService::AddAcceptFilterEntry>, "AddAcceptFilterEntry"}, - {209, nullptr, "ClearAcceptFilter"}, + {209, D<&IUserLocalCommunicationService::ClearAcceptFilter>, "ClearAcceptFilter"}, {300, D<&IUserLocalCommunicationService::OpenStation>, "OpenStation"}, {301, D<&IUserLocalCommunicationService::CloseStation>, "CloseStation"}, {302, D<&IUserLocalCommunicationService::Connect>, "Connect"}, - {303, nullptr, "ConnectPrivate"}, + {303, D<&IUserLocalCommunicationService::ConnectPrivate>, "ConnectPrivate"}, {304, D<&IUserLocalCommunicationService::Disconnect>, "Disconnect"}, {400, D<&IUserLocalCommunicationService::Initialize>, "Initialize"}, {401, D<&IUserLocalCommunicationService::Finalize>, "Finalize"}, @@ -227,6 +227,13 @@ Result IUserLocalCommunicationService::DestroyNetwork() { R_RETURN(lan_discovery.DestroyNetwork()); } +Result IUserLocalCommunicationService::Reject(Ipv4Address ip_address, u16 port) { + LOG_WARNING(Service_LDN, "(STUBBED) called, ip_address={}.{}.{}.{}, port={}", + ip_address[0], ip_address[1], ip_address[2], ip_address[3], port); + + R_SUCCEED(); +} + Result IUserLocalCommunicationService::SetAdvertiseData( InBuffer buffer_data) { LOG_INFO(Service_LDN, "called"); @@ -244,6 +251,11 @@ Result IUserLocalCommunicationService::AddAcceptFilterEntry(MacAddress mac_addre R_SUCCEED(); } +Result IUserLocalCommunicationService::ClearAcceptFilter() { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + R_SUCCEED(); +} + Result IUserLocalCommunicationService::OpenStation() { LOG_INFO(Service_LDN, "called"); @@ -269,6 +281,16 @@ Result IUserLocalCommunicationService::Connect( static_cast(connect_data.local_communication_version))); } +Result IUserLocalCommunicationService::ConnectPrivate( + const ConnectNetworkData& connect_data, + InLargeData network_info) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + + // ConnectPrivate is similar to Connect but with additional private network parameters + // For now, stub it - would need to implement private network logic + R_SUCCEED(); +} + Result IUserLocalCommunicationService::Disconnect() { LOG_INFO(Service_LDN, "called"); diff --git a/src/core/hle/service/ldn/user_local_communication_service.h b/src/core/hle/service/ldn/user_local_communication_service.h index 6698d10d2..3c963f425 100644 --- a/src/core/hle/service/ldn/user_local_communication_service.h +++ b/src/core/hle/service/ldn/user_local_communication_service.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once @@ -63,12 +64,16 @@ private: Result DestroyNetwork(); + Result Reject(Ipv4Address ip_address, u16 port); + Result SetAdvertiseData(InBuffer buffer_data); Result SetStationAcceptPolicy(AcceptPolicy accept_policy); Result AddAcceptFilterEntry(MacAddress mac_address); + Result ClearAcceptFilter(); + Result OpenStation(); Result CloseStation(); @@ -76,6 +81,9 @@ private: Result Connect(const ConnectNetworkData& connect_data, InLargeData network_info); + Result ConnectPrivate(const ConnectNetworkData& connect_data, + InLargeData network_info); + Result Disconnect(); Result Initialize(ClientProcessId aruid); diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 5d8a5879a..49dd1a04b 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -26,9 +26,10 @@ namespace { namespace Service::NIFM { // This is nn::nifm::RequestState +// Reference: https://switchbrew.org/wiki/Network_Interface_services#RequestState enum class RequestState : u32 { - NotSubmitted = 1, - Invalid = 1, ///< The duplicate 1 is intentional; it means both not submitted and error on HW. + Invalid = 0, + Free = 1, ///< NotSubmitted/Free state OnHold = 2, Accepted = 3, Blocking = 4, @@ -56,6 +57,17 @@ enum class NetworkProfileType : u32 { Temporary, }; +// This is nn::nifm::ConnectionConfirmationOption +// Reference: https://switchbrew.org/wiki/Network_Interface_services#ConnectionConfirmationOption +enum class ConnectionConfirmationOption : u32 { + Invalid = 0, + Prohibited = 1, + NotRequired = 2, + Preferred = 3, + Required = 4, + Forced = 5, +}; + // This is nn::nifm::IpAddressSetting struct IpAddressSetting { bool is_automatic{}; @@ -258,7 +270,7 @@ public: event1 = CreateKEvent(service_context, "IRequest:Event1"); event2 = CreateKEvent(service_context, "IRequest:Event2"); - state = RequestState::NotSubmitted; + state = RequestState::Free; } ~IRequest() override { @@ -270,7 +282,7 @@ private: void Submit(HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "(STUBBED) called"); - if (state == RequestState::NotSubmitted) { + if (state == RequestState::Free) { UpdateState(RequestState::OnHold); } @@ -302,7 +314,7 @@ private: const auto result = [this] { const auto has_connection = Network::GetHostIPv4Address().has_value(); switch (state) { - case RequestState::NotSubmitted: + case RequestState::Free: return has_connection ? ResultSuccess : ResultNetworkCommunicationDisabled; case RequestState::OnHold: if (has_connection) { @@ -322,7 +334,7 @@ private: } void GetSystemEventReadableHandles(HLERequestContext& ctx) { - LOG_WARNING(Service_NIFM, "(STUBBED) called"); + LOG_DEBUG(Service_NIFM, "called"); IPC::ResponseBuilder rb{ctx, 2, 2}; rb.Push(ResultSuccess); @@ -337,7 +349,10 @@ private: } void SetConnectionConfirmationOption(HLERequestContext& ctx) { - LOG_WARNING(Service_NIFM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + const auto connection_option = rp.PopEnum(); + + LOG_INFO(Service_NIFM, "called, connection_option={}", static_cast(connection_option)); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -633,7 +648,7 @@ void IGeneralService::CreateTemporaryNetworkProfile(HLERequestContext& ctx) { } void IGeneralService::GetCurrentIpConfigInfo(HLERequestContext& ctx) { - LOG_WARNING(Service_NIFM, "(STUBBED) called"); + LOG_DEBUG(Service_NIFM, "called"); struct IpConfigInfo { IpAddressSetting ip_address_setting{}; @@ -814,6 +829,104 @@ void IGeneralService::SetWowlTcpKeepAliveTimeout(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void IGeneralService::IsWiredConnectionAvailable(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called IsWiredConnectionAvailable [18.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(1); // Wired connection available +} + +void IGeneralService::IsNetworkEmulationFeatureEnabled(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called IsNetworkEmulationFeatureEnabled [18.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); // Network emulation disabled +} + +void IGeneralService::SelectActiveNetworkEmulationProfileIdForDebug(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called SelectActiveNetworkEmulationProfileIdForDebug [18.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IGeneralService::GetScanData2(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called GetScanData [19.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); // No scan data +} + +void IGeneralService::ResetActiveNetworkEmulationProfileId(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called ResetActiveNetworkEmulationProfileId [20.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IGeneralService::GetActiveNetworkEmulationProfileId(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called GetActiveNetworkEmulationProfileId [18.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); // No active profile +} + +void IGeneralService::IsRewriteFeatureEnabled(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called IsRewriteFeatureEnabled [18.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); // Rewrite feature disabled +} + +void IGeneralService::CreateRewriteRule(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called CreateRewriteRule [18.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IGeneralService::DestroyRewriteRule(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called DestroyRewriteRule [18.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IGeneralService::IsActiveNetworkEmulationProfileIdSelected(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called IsActiveNetworkEmulationProfileIdSelected [20.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); // No profile selected +} + +void IGeneralService::SelectDefaultNetworkEmulationProfileId(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called SelectDefaultNetworkEmulationProfileId [20.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IGeneralService::GetDefaultNetworkEmulationProfileId(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called GetDefaultNetworkEmulationProfileId [20.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); // Default profile ID +} + +void IGeneralService::GetNetworkEmulationProfile(HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called GetNetworkEmulationProfile [20.0.0+]"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + IGeneralService::IGeneralService(Core::System& system_) : ServiceFramework{system_, "IGeneralService"}, network{system_.GetRoomNetwork()} { // clang-format off @@ -860,6 +973,19 @@ IGeneralService::IGeneralService(Core::System& system_) {41, &IGeneralService::GetAcceptableNetworkTypeFlag, "GetAcceptableNetworkTypeFlag"}, {42, &IGeneralService::NotifyConnectionStateChanged, "NotifyConnectionStateChanged"}, {43, &IGeneralService::SetWowlDelayedWakeTime, "SetWowlDelayedWakeTime"}, + {44, &IGeneralService::IsWiredConnectionAvailable, "IsWiredConnectionAvailable"}, + {45, &IGeneralService::IsNetworkEmulationFeatureEnabled, "IsNetworkEmulationFeatureEnabled"}, + {46, &IGeneralService::SelectActiveNetworkEmulationProfileIdForDebug, "SelectActiveNetworkEmulationProfileIdForDebug"}, + {47, &IGeneralService::GetScanData2, "GetScanData"}, + {48, &IGeneralService::ResetActiveNetworkEmulationProfileId, "ResetActiveNetworkEmulationProfileId"}, + {49, &IGeneralService::GetActiveNetworkEmulationProfileId, "GetActiveNetworkEmulationProfileId"}, + {50, &IGeneralService::IsRewriteFeatureEnabled, "IsRewriteFeatureEnabled"}, + {51, &IGeneralService::CreateRewriteRule, "CreateRewriteRule"}, + {52, &IGeneralService::DestroyRewriteRule, "DestroyRewriteRule"}, + {53, &IGeneralService::IsActiveNetworkEmulationProfileIdSelected, "IsActiveNetworkEmulationProfileIdSelected"}, + {54, &IGeneralService::SelectDefaultNetworkEmulationProfileId, "SelectDefaultNetworkEmulationProfileId"}, + {55, &IGeneralService::GetDefaultNetworkEmulationProfileId, "GetDefaultNetworkEmulationProfileId"}, + {56, &IGeneralService::GetNetworkEmulationProfile, "GetNetworkEmulationProfile"}, {57, &IGeneralService::SetWowlTcpKeepAliveTimeout, "SetWowlTcpKeepAliveTimeout"}, }; // clang-format on diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h index f29d38dcb..550fba683 100644 --- a/src/core/hle/service/nifm/nifm.h +++ b/src/core/hle/service/nifm/nifm.h @@ -48,6 +48,19 @@ private: void GetAcceptableNetworkTypeFlag(HLERequestContext& ctx); void NotifyConnectionStateChanged(HLERequestContext& ctx); void SetWowlTcpKeepAliveTimeout(HLERequestContext& ctx); + void IsWiredConnectionAvailable(HLERequestContext& ctx); + void IsNetworkEmulationFeatureEnabled(HLERequestContext& ctx); + void SelectActiveNetworkEmulationProfileIdForDebug(HLERequestContext& ctx); + void GetScanData2(HLERequestContext& ctx); + void ResetActiveNetworkEmulationProfileId(HLERequestContext& ctx); + void GetActiveNetworkEmulationProfileId(HLERequestContext& ctx); + void IsRewriteFeatureEnabled(HLERequestContext& ctx); + void CreateRewriteRule(HLERequestContext& ctx); + void DestroyRewriteRule(HLERequestContext& ctx); + void IsActiveNetworkEmulationProfileIdSelected(HLERequestContext& ctx); + void SelectDefaultNetworkEmulationProfileId(HLERequestContext& ctx); + void GetDefaultNetworkEmulationProfileId(HLERequestContext& ctx); + void GetNetworkEmulationProfile(HLERequestContext& ctx); Network::RoomNetwork& network; }; diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index f443124ec..cde538cbd 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -149,19 +149,45 @@ void BSD::SendToWork::Response(HLERequestContext& ctx) { } void BSD::RegisterClient(HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + + // Read LibraryConfigData structure + struct LibraryConfigData { + u32 version; + u32 tcp_tx_buf_size; + u32 tcp_rx_buf_size; + u32 tcp_tx_buf_max_size; + u32 tcp_rx_buf_max_size; + u32 udp_tx_buf_size; + u32 udp_rx_buf_size; + u32 sb_efficiency; + }; + + const auto config = rp.PopRaw(); + const u64 transfer_memory_size = rp.Pop(); + [[maybe_unused]] const auto transfer_memory_handle = ctx.GetCopyHandle(0); + const u64 pid = ctx.GetPID(); + + LOG_INFO(Service, "called, version={} pid={} transfer_memory_size={:#x}", + config.version, pid, transfer_memory_size); + LOG_DEBUG(Service, " TCP: tx={:#x} rx={:#x} tx_max={:#x} rx_max={:#x}", + config.tcp_tx_buf_size, config.tcp_rx_buf_size, + config.tcp_tx_buf_max_size, config.tcp_rx_buf_max_size); + LOG_DEBUG(Service, " UDP: tx={:#x} rx={:#x} sb_efficiency={}", + config.udp_tx_buf_size, config.udp_rx_buf_size, config.sb_efficiency); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); rb.Push(0); // bsd errno } void BSD::StartMonitoring(HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); + LOG_INFO(Service, "called"); + // StartMonitoring initializes network event monitoring for BSD sockets + // This command has no documented input parameters in switchbrew + // It enables proper event handling for socket operations IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); } @@ -515,10 +541,13 @@ std::pair BSD::SocketImpl(Domain domain, Type type, Protocol protoco FileDescriptor& descriptor = *file_descriptors[fd]; // ENONMEM might be thrown here - LOG_INFO(Service, "New socket fd={}", fd); - auto room_member = room_network.GetRoomMember().lock(); - if (room_member && room_member->IsConnected()) { + const bool using_proxy = room_member && room_member->IsConnected(); + + LOG_INFO(Service, "New socket fd={} domain={} type={} protocol={} proxy={}", + fd, domain, type, protocol, using_proxy); + + if (using_proxy) { descriptor.socket = std::make_shared(room_network); } else { descriptor.socket = std::make_shared(); @@ -632,23 +661,41 @@ std::pair BSD::AcceptImpl(s32 fd, std::vector& write_buffer) { Errno BSD::BindImpl(s32 fd, std::span addr) { if (!IsFileDescriptorValid(fd)) { + LOG_ERROR(Service, "Bind failed: Invalid fd={}", fd); return Errno::BADF; } ASSERT(addr.size() == sizeof(SockAddrIn)); auto addr_in = GetValue(addr); - return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); + LOG_INFO(Service, "Bind fd={} to {}:{}", fd, Network::IPv4AddressToString(addr_in.ip), + addr_in.portno); + + const auto result = Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); + if (result != Errno::SUCCESS) { + LOG_ERROR(Service, "Bind fd={} failed with errno={}", fd, static_cast(result)); + } + return result; } Errno BSD::ConnectImpl(s32 fd, std::span addr) { if (!IsFileDescriptorValid(fd)) { + LOG_ERROR(Service, "Connect failed: Invalid fd={}", fd); return Errno::BADF; } UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn)); auto addr_in = GetValue(addr); - return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in))); + LOG_INFO(Service, "Connect fd={} to {}:{}", fd, Network::IPv4AddressToString(addr_in.ip), + addr_in.portno); + + const auto result = Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in))); + if (result != Errno::SUCCESS) { + LOG_ERROR(Service, "Connect fd={} failed with errno={}", fd, static_cast(result)); + } else { + LOG_INFO(Service, "Connect fd={} succeeded", fd); + } + return result; } Errno BSD::GetPeerNameImpl(s32 fd, std::vector& write_buffer) { @@ -1031,8 +1078,11 @@ BSD::BSD(Core::System& system_, const char* name) {33, &BSD::RegisterClientShared, "RegisterClientShared"}, {34, &BSD::GetSocketStatistics, "GetSocketStatistics"}, {35, &BSD::NifIoctl, "NifIoctl"}, - {39, &BSD::Unknown39, "[20.0.0+] Unknown39"}, - {40, &BSD::Unknown40, "[20.0.0+] Unknown40"}, + {36, &BSD::Unknown36, "Unknown36"}, + {37, &BSD::Unknown37, "Unknown37"}, + {38, &BSD::Unknown38, "Unknown38"}, + {39, &BSD::Unknown39, "Unknown39"}, + {40, &BSD::Unknown40, "Unknown40"}, {200, &BSD::SetThreadCoreMask, "SetThreadCoreMask"}, {201, &BSD::GetThreadCoreMask, "GetThreadCoreMask"}, }; @@ -1289,7 +1339,7 @@ void BSD::SendMMsg(HLERequestContext& ctx) { } void BSD::SetThreadCoreMask(HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called SetThreadCoreMask"); + LOG_WARNING(Service, "(STUBBED) called SetThreadCoreMask [15.0.0+]"); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); rb.Push(-1); @@ -1312,6 +1362,30 @@ void BSD::SocketExempt(HLERequestContext& ctx) { rb.PushEnum(static_cast(EOPNOTSUPP)); } +void BSD::Unknown36(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called Unknown36 [18.0.0+]"); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(-1); + rb.PushEnum(static_cast(EOPNOTSUPP)); +} + +void BSD::Unknown37(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called Unknown37 [18.0.0+]"); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(-1); + rb.PushEnum(static_cast(EOPNOTSUPP)); +} + +void BSD::Unknown38(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called Unknown38 [18.0.0+]"); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(-1); + rb.PushEnum(static_cast(EOPNOTSUPP)); +} + void BSD::Unknown39(HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called Unknown39 [20.0.0+]"); IPC::ResponseBuilder rb{ctx, 4}; diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index c097938a9..c58579644 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -162,11 +162,14 @@ private: void RegisterResourceStatisticsName(HLERequestContext& ctx); void RegisterClientShared(HLERequestContext& ctx); void GetSocketStatistics(HLERequestContext& ctx); - void NifIoctl(HLERequestContext& ctx); - void Unknown39(HLERequestContext& ctx); // [20.0.0+] undocumented - void Unknown40(HLERequestContext& ctx); // [20.0.0+] undocumented - void SetThreadCoreMask(HLERequestContext& ctx); - void GetThreadCoreMask(HLERequestContext& ctx); + void NifIoctl(HLERequestContext& ctx); // [17.0.0+] + void Unknown36(HLERequestContext& ctx); // [18.0.0+] undocumented + void Unknown37(HLERequestContext& ctx); // [18.0.0+] undocumented + void Unknown38(HLERequestContext& ctx); // [18.0.0+] undocumented + void Unknown39(HLERequestContext& ctx); // [20.0.0+] undocumented + void Unknown40(HLERequestContext& ctx); // [20.0.0+] undocumented + void SetThreadCoreMask(HLERequestContext& ctx); // [15.0.0+] + void GetThreadCoreMask(HLERequestContext& ctx); // [15.0.0+] template void ExecuteWork(HLERequestContext& ctx, Work work);