From 093471609d415640eeb4814a723d9ff8e6ba788a Mon Sep 17 00:00:00 2001 From: exelix Date: Fri, 15 Mar 2019 22:11:40 +0100 Subject: [PATCH] Change nifm initialization mode and add SetWirelessCommunicationEnabled (#247) * Init nifm in the proper context, add SetWirelessCommunicationEnabled * add nifmSetServiceType to set which nifm service to init --- nx/include/switch/services/nifm.h | 20 +++++++++- nx/source/services/nifm.c | 62 +++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/nx/include/switch/services/nifm.h b/nx/include/switch/services/nifm.h index 5248f542..fb7dfbeb 100644 --- a/nx/include/switch/services/nifm.h +++ b/nx/include/switch/services/nifm.h @@ -1,7 +1,7 @@ /** * @file nifm.h * @brief Network interface service IPC wrapper. - * @author shadowninja108, shibboleet + * @author shadowninja108, shibboleet, exelix * @copyright libnx Authors */ @@ -9,6 +9,19 @@ #include "../kernel/ipc.h" #include "../services/sm.h" +typedef enum { + NifmServiceType_NotInitialized = 0, ///< Initializes nifm:u. + NifmServiceType_User = 1, ///< Initializes nifm:u. + NifmServiceType_System = 2, ///< Initializes nifm:s. + NifmServiceType_Admin = 3, ///< Initializes nifm:a. +} NifmServiceType; + +/** + * @brief Sets the \ref NifmServiceType for initialization. Call this function before \ref nifmInitialize. + * @note By default nifm:u will be used. + */ +void nifmSetServiceType(NifmServiceType serviceType); + Result nifmInitialize(void); void nifmExit(void); @@ -16,6 +29,11 @@ Result nifmGetCurrentIpAddress(u32* out); Result nifmIsWirelessCommunicationEnabled(bool* out); +/** + * @note Works only if called from nifm:a or nifm:s. + */ +Result nifmSetWirelessCommunicationEnabled(bool enable); + Result nifmIsEthernetCommunicationEnabled(bool* out); Result nifmIsAnyForegroundRequestAccepted(bool* out); Result nifmPutToSleep(void); diff --git a/nx/source/services/nifm.c b/nx/source/services/nifm.c index 68dd0fd1..9ae96c4d 100644 --- a/nx/source/services/nifm.c +++ b/nx/source/services/nifm.c @@ -9,6 +9,8 @@ #include "arm/atomics.h" #include "runtime/hosversion.h" +static NifmServiceType g_nifmServiceType = NifmServiceType_NotInitialized; + static Service g_nifmSrv; static Service g_nifmIGS; static u64 g_refCnt; @@ -16,15 +18,31 @@ static u64 g_refCnt; static Result _nifmCreateGeneralService(Service* out, u64 in); static Result _nifmCreateGeneralServiceOld(Service* out); +void nifmSetServiceType(NifmServiceType serviceType) { + g_nifmServiceType = serviceType; +} + Result nifmInitialize(void) { atomicIncrement64(&g_refCnt); if (serviceIsActive(&g_nifmSrv)) return 0; - Result rc; - rc = smGetService(&g_nifmSrv, "nifm:u"); - + Result rc = 0; + switch (g_nifmServiceType) { + case NifmServiceType_NotInitialized: + case NifmServiceType_User: + g_nifmServiceType = NifmServiceType_User; + rc = smGetService(&g_nifmSrv, "nifm:u"); + break; + case NifmServiceType_System: + rc = smGetService(&g_nifmSrv, "nifm:s"); + break; + case NifmServiceType_Admin: + rc = smGetService(&g_nifmSrv, "nifm:a"); + break; + } + if (R_SUCCEEDED(rc)) rc = serviceConvertToDomain(&g_nifmSrv); if (R_SUCCEEDED(rc)) { @@ -44,6 +62,7 @@ void nifmExit(void) { if (atomicDecrement64(&g_refCnt) == 0) { serviceClose(&g_nifmIGS); serviceClose(&g_nifmSrv); + g_nifmServiceType = NifmServiceType_NotInitialized; } } @@ -119,6 +138,43 @@ Result nifmIsWirelessCommunicationEnabled(bool* out) { return rc; } +Result nifmSetWirelessCommunicationEnabled(bool enable) { + if (g_nifmServiceType < NifmServiceType_System) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 value; + } *raw; + + raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 16; + raw->value = enable!= 0; + + Result rc = serviceIpcDispatch(&g_nifmIGS); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + Result nifmIsEthernetCommunicationEnabled(bool* out) { IpcCommand c; ipcInitialize(&c);