| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- // Copyright 2018 yuzu emulator team
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #include "common/settings.h"
- #include "core/core.h"
- #include "core/hle/ipc_helpers.h"
- #include "core/hle/kernel/k_event.h"
- #include "core/hle/kernel/k_readable_event.h"
- #include "core/hle/kernel/kernel.h"
- #include "core/hle/service/nifm/nifm.h"
- #include "core/hle/service/service.h"
- #include "core/network/network.h"
- namespace Service::NIFM {
- enum class RequestState : u32 {
- NotSubmitted = 1,
- Error = 1, ///< The duplicate 1 is intentional; it means both not submitted and error on HW.
- Pending = 2,
- Connected = 3,
- };
- struct IpAddressSetting {
- bool is_automatic{};
- Network::IPv4Address current_address{};
- Network::IPv4Address subnet_mask{};
- Network::IPv4Address gateway{};
- };
- static_assert(sizeof(IpAddressSetting) == 0xD, "IpAddressSetting has incorrect size.");
- struct DnsSetting {
- bool is_automatic{};
- Network::IPv4Address primary_dns{};
- Network::IPv4Address secondary_dns{};
- };
- static_assert(sizeof(DnsSetting) == 0x9, "DnsSetting has incorrect size.");
- struct ProxySetting {
- bool enabled{};
- INSERT_PADDING_BYTES(1);
- u16 port{};
- std::array<char, 0x64> proxy_server{};
- bool automatic_auth_enabled{};
- std::array<char, 0x20> user{};
- std::array<char, 0x20> password{};
- INSERT_PADDING_BYTES(1);
- };
- static_assert(sizeof(ProxySetting) == 0xAA, "ProxySetting has incorrect size.");
- struct IpSettingData {
- IpAddressSetting ip_address_setting{};
- DnsSetting dns_setting{};
- ProxySetting proxy_setting{};
- u16 mtu{};
- };
- static_assert(sizeof(IpSettingData) == 0xC2, "IpSettingData has incorrect size.");
- struct SfWirelessSettingData {
- u8 ssid_length{};
- std::array<char, 0x20> ssid{};
- u8 unknown_1{};
- u8 unknown_2{};
- u8 unknown_3{};
- std::array<char, 0x41> passphrase{};
- };
- static_assert(sizeof(SfWirelessSettingData) == 0x65, "SfWirelessSettingData has incorrect size.");
- struct NifmWirelessSettingData {
- u8 ssid_length{};
- std::array<char, 0x21> ssid{};
- u8 unknown_1{};
- INSERT_PADDING_BYTES(1);
- u32 unknown_2{};
- u32 unknown_3{};
- std::array<char, 0x41> passphrase{};
- INSERT_PADDING_BYTES(3);
- };
- static_assert(sizeof(NifmWirelessSettingData) == 0x70,
- "NifmWirelessSettingData has incorrect size.");
- #pragma pack(push, 1)
- struct SfNetworkProfileData {
- IpSettingData ip_setting_data{};
- u128 uuid{};
- std::array<char, 0x40> network_name{};
- u8 unknown_1{};
- u8 unknown_2{};
- u8 unknown_3{};
- u8 unknown_4{};
- SfWirelessSettingData wireless_setting_data{};
- INSERT_PADDING_BYTES(1);
- };
- static_assert(sizeof(SfNetworkProfileData) == 0x17C, "SfNetworkProfileData has incorrect size.");
- struct NifmNetworkProfileData {
- u128 uuid{};
- std::array<char, 0x40> network_name{};
- u32 unknown_1{};
- u32 unknown_2{};
- u8 unknown_3{};
- u8 unknown_4{};
- INSERT_PADDING_BYTES(2);
- NifmWirelessSettingData wireless_setting_data{};
- IpSettingData ip_setting_data{};
- };
- static_assert(sizeof(NifmNetworkProfileData) == 0x18E,
- "NifmNetworkProfileData has incorrect size.");
- #pragma pack(pop)
- class IScanRequest final : public ServiceFramework<IScanRequest> {
- public:
- explicit IScanRequest(Core::System& system_) : ServiceFramework{system_, "IScanRequest"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "Submit"},
- {1, nullptr, "IsProcessing"},
- {2, nullptr, "GetResult"},
- {3, nullptr, "GetSystemEventReadableHandle"},
- {4, nullptr, "SetChannels"},
- };
- // clang-format on
- RegisterHandlers(functions);
- }
- };
- class IRequest final : public ServiceFramework<IRequest> {
- public:
- explicit IRequest(Core::System& system_) : ServiceFramework{system_, "IRequest"} {
- static const FunctionInfo functions[] = {
- {0, &IRequest::GetRequestState, "GetRequestState"},
- {1, &IRequest::GetResult, "GetResult"},
- {2, &IRequest::GetSystemEventReadableHandles, "GetSystemEventReadableHandles"},
- {3, &IRequest::Cancel, "Cancel"},
- {4, &IRequest::Submit, "Submit"},
- {5, nullptr, "SetRequirement"},
- {6, nullptr, "SetRequirementPreset"},
- {8, nullptr, "SetPriority"},
- {9, nullptr, "SetNetworkProfileId"},
- {10, nullptr, "SetRejectable"},
- {11, &IRequest::SetConnectionConfirmationOption, "SetConnectionConfirmationOption"},
- {12, nullptr, "SetPersistent"},
- {13, nullptr, "SetInstant"},
- {14, nullptr, "SetSustainable"},
- {15, nullptr, "SetRawPriority"},
- {16, nullptr, "SetGreedy"},
- {17, nullptr, "SetSharable"},
- {18, nullptr, "SetRequirementByRevision"},
- {19, nullptr, "GetRequirement"},
- {20, nullptr, "GetRevision"},
- {21, &IRequest::GetAppletInfo, "GetAppletInfo"},
- {22, nullptr, "GetAdditionalInfo"},
- {23, nullptr, "SetKeptInSleep"},
- {24, nullptr, "RegisterSocketDescriptor"},
- {25, nullptr, "UnregisterSocketDescriptor"},
- };
- RegisterHandlers(functions);
- auto& kernel = system.Kernel();
- event1 = Kernel::KEvent::Create(kernel, "IRequest:Event1");
- event1->Initialize();
- event2 = Kernel::KEvent::Create(kernel, "IRequest:Event2");
- event2->Initialize();
- }
- private:
- void Submit(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
- }
- void GetRequestState(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- if (Settings::values.bcat_backend == "none") {
- rb.PushEnum(RequestState::NotSubmitted);
- } else {
- rb.PushEnum(RequestState::Connected);
- }
- }
- void GetResult(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
- }
- void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2, 2};
- rb.Push(RESULT_SUCCESS);
- rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent());
- }
- void Cancel(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
- }
- void SetConnectionConfirmationOption(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
- }
- void GetAppletInfo(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- std::vector<u8> out_buffer(ctx.GetWriteBufferSize());
- ctx.WriteBuffer(out_buffer);
- IPC::ResponseBuilder rb{ctx, 5};
- rb.Push(RESULT_SUCCESS);
- rb.Push<u32>(0);
- rb.Push<u32>(0);
- rb.Push<u32>(0);
- }
- std::shared_ptr<Kernel::KEvent> event1, event2;
- };
- class INetworkProfile final : public ServiceFramework<INetworkProfile> {
- public:
- explicit INetworkProfile(Core::System& system_) : ServiceFramework{system_, "INetworkProfile"} {
- static const FunctionInfo functions[] = {
- {0, nullptr, "Update"},
- {1, nullptr, "PersistOld"},
- {2, nullptr, "Persist"},
- };
- RegisterHandlers(functions);
- }
- };
- class IGeneralService final : public ServiceFramework<IGeneralService> {
- public:
- explicit IGeneralService(Core::System& system_);
- private:
- void GetClientId(Kernel::HLERequestContext& ctx) {
- static constexpr u32 client_id = 1;
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(RESULT_SUCCESS);
- rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid
- }
- void CreateScanRequest(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_NIFM, "called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<IScanRequest>(system);
- }
- void CreateRequest(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_NIFM, "called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<IRequest>(system);
- }
- void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- const SfNetworkProfileData network_profile_data{
- .ip_setting_data{
- .ip_address_setting{
- .is_automatic{true},
- .current_address{192, 168, 1, 100},
- .subnet_mask{255, 255, 255, 0},
- .gateway{192, 168, 1, 1},
- },
- .dns_setting{
- .is_automatic{true},
- .primary_dns{1, 1, 1, 1},
- .secondary_dns{1, 0, 0, 1},
- },
- .proxy_setting{
- .enabled{false},
- .port{},
- .proxy_server{},
- .automatic_auth_enabled{},
- .user{},
- .password{},
- },
- .mtu{1500},
- },
- .uuid{0xdeadbeef, 0xdeadbeef},
- .network_name{"yuzu Network"},
- .wireless_setting_data{
- .ssid_length{12},
- .ssid{"yuzu Network"},
- .passphrase{"yuzupassword"},
- },
- };
- ctx.WriteBuffer(network_profile_data);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
- }
- void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
- }
- void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- const auto [ipv4, error] = Network::GetHostIPv4Address();
- UNIMPLEMENTED_IF(error != Network::Errno::SUCCESS);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- rb.PushRaw(ipv4);
- }
- void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_NIFM, "called");
- ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c,
- "SfNetworkProfileData is not the correct size");
- u128 uuid{};
- auto buffer = ctx.ReadBuffer();
- std::memcpy(&uuid, buffer.data() + 8, sizeof(u128));
- IPC::ResponseBuilder rb{ctx, 6, 0, 1};
- rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<INetworkProfile>(system);
- rb.PushRaw<u128>(uuid);
- }
- void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- struct IpConfigInfo {
- IpAddressSetting ip_address_setting;
- DnsSetting dns_setting;
- };
- static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting),
- "IpConfigInfo has incorrect size.");
- const IpConfigInfo ip_config_info{
- .ip_address_setting{
- .is_automatic{true},
- .current_address{192, 168, 1, 100},
- .subnet_mask{255, 255, 255, 0},
- .gateway{192, 168, 1, 1},
- },
- .dns_setting{
- .is_automatic{true},
- .primary_dns{1, 1, 1, 1},
- .secondary_dns{1, 0, 0, 1},
- },
- };
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(IpConfigInfo) / sizeof(u32)};
- rb.Push(RESULT_SUCCESS);
- rb.PushRaw<IpConfigInfo>(ip_config_info);
- }
- void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- rb.Push<u8>(0);
- }
- void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- if (Settings::values.bcat_backend == "none") {
- rb.Push<u8>(0);
- } else {
- rb.Push<u8>(1);
- }
- }
- void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_NIFM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- if (Settings::values.bcat_backend == "none") {
- rb.Push<u8>(0);
- } else {
- rb.Push<u8>(1);
- }
- }
- };
- IGeneralService::IGeneralService(Core::System& system_)
- : ServiceFramework{system_, "IGeneralService"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1, &IGeneralService::GetClientId, "GetClientId"},
- {2, &IGeneralService::CreateScanRequest, "CreateScanRequest"},
- {4, &IGeneralService::CreateRequest, "CreateRequest"},
- {5, &IGeneralService::GetCurrentNetworkProfile, "GetCurrentNetworkProfile"},
- {6, nullptr, "EnumerateNetworkInterfaces"},
- {7, nullptr, "EnumerateNetworkProfiles"},
- {8, nullptr, "GetNetworkProfile"},
- {9, nullptr, "SetNetworkProfile"},
- {10, &IGeneralService::RemoveNetworkProfile, "RemoveNetworkProfile"},
- {11, nullptr, "GetScanDataOld"},
- {12, &IGeneralService::GetCurrentIpAddress, "GetCurrentIpAddress"},
- {13, nullptr, "GetCurrentAccessPointOld"},
- {14, &IGeneralService::CreateTemporaryNetworkProfile, "CreateTemporaryNetworkProfile"},
- {15, &IGeneralService::GetCurrentIpConfigInfo, "GetCurrentIpConfigInfo"},
- {16, nullptr, "SetWirelessCommunicationEnabled"},
- {17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
- {18, nullptr, "GetInternetConnectionStatus"},
- {19, nullptr, "SetEthernetCommunicationEnabled"},
- {20, &IGeneralService::IsEthernetCommunicationEnabled, "IsEthernetCommunicationEnabled"},
- {21, &IGeneralService::IsAnyInternetRequestAccepted, "IsAnyInternetRequestAccepted"},
- {22, nullptr, "IsAnyForegroundRequestAccepted"},
- {23, nullptr, "PutToSleep"},
- {24, nullptr, "WakeUp"},
- {25, nullptr, "GetSsidListVersion"},
- {26, nullptr, "SetExclusiveClient"},
- {27, nullptr, "GetDefaultIpSetting"},
- {28, nullptr, "SetDefaultIpSetting"},
- {29, nullptr, "SetWirelessCommunicationEnabledForTest"},
- {30, nullptr, "SetEthernetCommunicationEnabledForTest"},
- {31, nullptr, "GetTelemetorySystemEventReadableHandle"},
- {32, nullptr, "GetTelemetryInfo"},
- {33, nullptr, "ConfirmSystemAvailability"},
- {34, nullptr, "SetBackgroundRequestEnabled"},
- {35, nullptr, "GetScanData"},
- {36, nullptr, "GetCurrentAccessPoint"},
- {37, nullptr, "Shutdown"},
- {38, nullptr, "GetAllowedChannels"},
- {39, nullptr, "NotifyApplicationSuspended"},
- {40, nullptr, "SetAcceptableNetworkTypeFlag"},
- {41, nullptr, "GetAcceptableNetworkTypeFlag"},
- {42, nullptr, "NotifyConnectionStateChanged"},
- {43, nullptr, "SetWowlDelayedWakeTime"},
- };
- // clang-format on
- RegisterHandlers(functions);
- }
- class NetworkInterface final : public ServiceFramework<NetworkInterface> {
- public:
- explicit NetworkInterface(const char* name, Core::System& system_)
- : ServiceFramework{system_, name} {
- static const FunctionInfo functions[] = {
- {4, &NetworkInterface::CreateGeneralServiceOld, "CreateGeneralServiceOld"},
- {5, &NetworkInterface::CreateGeneralService, "CreateGeneralService"},
- };
- RegisterHandlers(functions);
- }
- private:
- void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_NIFM, "called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<IGeneralService>(system);
- }
- void CreateGeneralService(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_NIFM, "called");
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<IGeneralService>(system);
- }
- };
- void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
- std::make_shared<NetworkInterface>("nifm:a", system)->InstallAsService(service_manager);
- std::make_shared<NetworkInterface>("nifm:s", system)->InstallAsService(service_manager);
- std::make_shared<NetworkInterface>("nifm:u", system)->InstallAsService(service_manager);
- }
- } // namespace Service::NIFM
|