From 2aefb4ae84e2aba0dccf5ba87e244fabf3e8fb41 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Thu, 9 Jul 2020 14:31:04 +0100 Subject: [PATCH] Implement network interface services nifm:u is used by applications to enable a connection to the network. --- app/CMakeLists.txt | 3 ++ .../main/cpp/skyline/services/base_service.h | 4 ++ .../skyline/services/nifm/IGeneralService.cpp | 15 +++++++ .../skyline/services/nifm/IGeneralService.h | 22 ++++++++++ .../cpp/skyline/services/nifm/IRequest.cpp | 33 +++++++++++++++ .../main/cpp/skyline/services/nifm/IRequest.h | 42 +++++++++++++++++++ .../skyline/services/nifm/IStaticService.cpp | 16 +++++++ .../skyline/services/nifm/IStaticService.h | 22 ++++++++++ .../main/cpp/skyline/services/serviceman.cpp | 4 ++ 9 files changed, 161 insertions(+) create mode 100644 app/src/main/cpp/skyline/services/nifm/IGeneralService.cpp create mode 100644 app/src/main/cpp/skyline/services/nifm/IGeneralService.h create mode 100644 app/src/main/cpp/skyline/services/nifm/IRequest.cpp create mode 100644 app/src/main/cpp/skyline/services/nifm/IRequest.h create mode 100644 app/src/main/cpp/skyline/services/nifm/IStaticService.cpp create mode 100644 app/src/main/cpp/skyline/services/nifm/IStaticService.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 431295e8..d8026c83 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -119,6 +119,9 @@ add_library(skyline SHARED ${source_DIR}/skyline/services/friends/IFriendService.cpp ${source_DIR}/skyline/services/nfp/IUserManager.cpp ${source_DIR}/skyline/services/nfp/IUser.cpp + ${source_DIR}/skyline/services/nifm/IStaticService.cpp + ${source_DIR}/skyline/services/nifm/IGeneralService.cpp + ${source_DIR}/skyline/services/nifm/IRequest.cpp ${source_DIR}/skyline/vfs/partition_filesystem.cpp ${source_DIR}/skyline/vfs/rom_filesystem.cpp ${source_DIR}/skyline/vfs/os_backing.cpp diff --git a/app/src/main/cpp/skyline/services/base_service.h b/app/src/main/cpp/skyline/services/base_service.h index cc3b5ce7..a9de1b6c 100644 --- a/app/src/main/cpp/skyline/services/base_service.h +++ b/app/src/main/cpp/skyline/services/base_service.h @@ -75,6 +75,9 @@ namespace skyline::service { friends_IFriendService, nfp_IUserManager, nfp_IUser, + nifm_IStaticService, + nifm_IGeneralService, + nifm_IRequest, }; /** @@ -111,6 +114,7 @@ namespace skyline::service { {"acc:u0", Service::account_IAccountServiceForApplication}, {"friend:u", Service::friends_IServiceCreator}, {"nfp:user", Service::nfp_IUserManager}, + {"nifm:u", Service::nifm_IStaticService}, }; class ServiceManager; diff --git a/app/src/main/cpp/skyline/services/nifm/IGeneralService.cpp b/app/src/main/cpp/skyline/services/nifm/IGeneralService.cpp new file mode 100644 index 00000000..4d625508 --- /dev/null +++ b/app/src/main/cpp/skyline/services/nifm/IGeneralService.cpp @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include "IRequest.h" +#include "IGeneralService.h" + +namespace skyline::service::nifm { + IGeneralService::IGeneralService(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::nifm_IGeneralService, "nifm:IGeneralService", { + {0x4, SFUNC(IGeneralService::CreateRequest)} + }) {} + + void IGeneralService::CreateRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + manager.RegisterService(SRVREG(IRequest), session, response); + } +} diff --git a/app/src/main/cpp/skyline/services/nifm/IGeneralService.h b/app/src/main/cpp/skyline/services/nifm/IGeneralService.h new file mode 100644 index 00000000..ad37fbe3 --- /dev/null +++ b/app/src/main/cpp/skyline/services/nifm/IGeneralService.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include + +namespace skyline::service::nifm { + /** + * @brief IGeneralService is used by applications to control the network connection (https://switchbrew.org/wiki/Network_Interface_services#IGeneralService) + */ + class IGeneralService : public BaseService { + public: + IGeneralService(const DeviceState &state, ServiceManager &manager); + + /** + * @brief This creates an IRequest instance that can be used to bring up the network (https://switchbrew.org/wiki/Network_Interface_services#CreateRequest) + */ + void CreateRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + }; +} diff --git a/app/src/main/cpp/skyline/services/nifm/IRequest.cpp b/app/src/main/cpp/skyline/services/nifm/IRequest.cpp new file mode 100644 index 00000000..cac94efb --- /dev/null +++ b/app/src/main/cpp/skyline/services/nifm/IRequest.cpp @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include +#include "IRequest.h" + +namespace skyline::service::nifm { + IRequest::IRequest(const DeviceState &state, ServiceManager &manager) : event0(std::make_shared(state)), event1(std::make_shared(state)), BaseService(state, manager, Service::nifm_IRequest, "nifm:IRequest", { + {0x0, SFUNC(IRequest::GetRequestState)}, + {0x1, SFUNC(IRequest::GetResult)}, + {0x2, SFUNC(IRequest::GetSystemEventReadableHandles)}, + {0x4, SFUNC(IRequest::Submit)}, + }) {} + + void IRequest::GetRequestState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + constexpr u32 Unsubmitted = 1; //!< The request has not been submitted + response.Push(Unsubmitted); + } + + void IRequest::GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {} + + void IRequest::GetSystemEventReadableHandles(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + auto handle = state.process->InsertItem(event0); + state.logger->Debug("Request Event 0 Handle: 0x{:X}", handle); + response.copyHandles.push_back(handle); + + handle = state.process->InsertItem(event1); + state.logger->Debug("Request Event 1 Handle: 0x{:X}", handle); + response.copyHandles.push_back(handle); + } + + void IRequest::Submit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {} +} diff --git a/app/src/main/cpp/skyline/services/nifm/IRequest.h b/app/src/main/cpp/skyline/services/nifm/IRequest.h new file mode 100644 index 00000000..9f5ab07f --- /dev/null +++ b/app/src/main/cpp/skyline/services/nifm/IRequest.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include +#include + +namespace skyline::service::nifm { + /** + * @brief IRequest is used by applications to bring up a network (https://switchbrew.org/wiki/Network_Interface_services#IRequest) + */ + class IRequest : public BaseService { + private: + std::shared_ptr event0; //!< The KEvent that is signalled on request state changes + std::shared_ptr event1; //!< The KEvent that is signalled on request changes + + public: + IRequest(const DeviceState &state, ServiceManager &manager); + + /** + * @brief This returns the current state of the request (https://switchbrew.org/wiki/Network_Interface_services#GetRequestState) + */ + void GetRequestState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + + /** + * @brief This returns the error code if a network bring up request fails (https://switchbrew.org/wiki/Network_Interface_services#GetResult) + */ + void GetResult(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + + /** + * @brief This returns two KEvent handles that signal request on request updates (https://switchbrew.org/wiki/Network_Interface_services#GetSystemEventReadableHandles) + */ + void GetSystemEventReadableHandles(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + + /** + * @brief This submits a request to bring up a network (https://switchbrew.org/wiki/Network_Interface_services#Submit) + */ + void Submit(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + }; +} diff --git a/app/src/main/cpp/skyline/services/nifm/IStaticService.cpp b/app/src/main/cpp/skyline/services/nifm/IStaticService.cpp new file mode 100644 index 00000000..123a0eaf --- /dev/null +++ b/app/src/main/cpp/skyline/services/nifm/IStaticService.cpp @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include "IGeneralService.h" +#include "IStaticService.h" + +namespace skyline::service::nifm { + IStaticService::IStaticService(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::nifm_IStaticService, "nifm:IStaticService", { + {0x4, SFUNC(IStaticService::CreateGeneralService)}, + {0x5, SFUNC(IStaticService::CreateGeneralService)} + }) {} + + void IStaticService::CreateGeneralService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + manager.RegisterService(SRVREG(IGeneralService), session, response); + } +} diff --git a/app/src/main/cpp/skyline/services/nifm/IStaticService.h b/app/src/main/cpp/skyline/services/nifm/IStaticService.h new file mode 100644 index 00000000..038c255e --- /dev/null +++ b/app/src/main/cpp/skyline/services/nifm/IStaticService.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include + +namespace skyline::service::nifm { + /** + * @brief IStaticService or nifm:u is used by applications to open an IGeneralService instance for controlling the network connection (https://switchbrew.org/wiki/Network_Interface_services#IGeneralService) + */ + class IStaticService : public BaseService { + public: + IStaticService(const DeviceState &state, ServiceManager &manager); + + /** + * @brief This opens an IGeneralService that can be used by applications to control the network connection (https://switchbrew.org/wiki/Network_Interface_services#CreateGeneralServiceOld) + */ + void CreateGeneralService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + }; +} diff --git a/app/src/main/cpp/skyline/services/serviceman.cpp b/app/src/main/cpp/skyline/services/serviceman.cpp index f2e354c5..303f15ec 100644 --- a/app/src/main/cpp/skyline/services/serviceman.cpp +++ b/app/src/main/cpp/skyline/services/serviceman.cpp @@ -23,6 +23,7 @@ #include "account/IAccountServiceForApplication.h" #include "friends/IServiceCreator.h" #include "nfp/IUserManager.h" +#include "nifm/IStaticService.h" #include "serviceman.h" namespace skyline::service { @@ -98,6 +99,9 @@ namespace skyline::service { case Service::nfp_IUserManager: serviceObj = std::make_shared(state, *this); break; + case Service::nifm_IStaticService: + serviceObj = std::make_shared(state, *this); + break; default: throw exception("CreateService called on missing object, type: {}", serviceType); }