diff --git a/nx/include/switch/runtime/devices/socket.h b/nx/include/switch/runtime/devices/socket.h index 3f0b3bcf..ad99be4a 100644 --- a/nx/include/switch/runtime/devices/socket.h +++ b/nx/include/switch/runtime/devices/socket.h @@ -46,3 +46,9 @@ int socketSslConnectionSetSocketDescriptor(SslConnection *c, int sockfd); /// Wrapper for \ref sslConnectionGetSocketDescriptor. Returns the output sockfd on success and -1 on error. int socketSslConnectionGetSocketDescriptor(SslConnection *c); +/// Wrapper for \ref nifmRequestRegisterSocketDescriptor. Returns 0 on success and -1 on error. +int socketNifmRequestRegisterSocketDescriptor(NifmRequest* r, int sockfd); + +/// Wrapper for \ref nifmRequestUnregisterSocketDescriptor. Returns 0 on success and -1 on error. +int socketNifmRequestUnregisterSocketDescriptor(NifmRequest* r, int sockfd); + diff --git a/nx/include/switch/services/nifm.h b/nx/include/switch/services/nifm.h index fed33cd7..1f190100 100644 --- a/nx/include/switch/services/nifm.h +++ b/nx/include/switch/services/nifm.h @@ -282,5 +282,32 @@ Result nifmRequestSubmitAndWait(NifmRequest* r); */ Result nifmRequestGetAppletInfo(NifmRequest* r, u32 theme_color, void* buffer, size_t size, u32 *applet_id, u32 *mode, u32 *out_size); +/** + * @brief SetKeptInSleep + * @note Only available on [3.0.0+]. + * @note ::NifmRequestState must be ::NifmRequestState_Unknown1. + * @param r \ref NifmRequest + * @param[in] flag Flag + */ +Result nifmRequestSetKeptInSleep(NifmRequest* r, bool flag); + +/** + * @brief RegisterSocketDescriptor. Only 1 socket can be registered at a time with a NifmRequest. Do not use directly, use \ref socketNifmRequestRegisterSocketDescriptor instead. + * @note Only available on [3.0.0+]. + * @note ::NifmRequestState must be ::NifmRequestState_Available. + * @param r \ref NifmRequest + * @param[in] sockfd Socket fd + */ +Result nifmRequestRegisterSocketDescriptor(NifmRequest* r, int sockfd); + +/** + * @brief UnregisterSocketDescriptor. Do not use directly, use \ref socketNifmRequestUnregisterSocketDescriptor instead. + * @note Only available on [3.0.0+]. + * @note ::NifmRequestState must be ::NifmRequestState_Available. + * @param r \ref NifmRequest + * @param[in] sockfd Socket fd, must match the fd previously registered with \ref nifmRequestRegisterSocketDescriptor. + */ +Result nifmRequestUnregisterSocketDescriptor(NifmRequest* r, int sockfd); + ///@} diff --git a/nx/source/runtime/devices/socket.c b/nx/source/runtime/devices/socket.c index a2f0b4fe..8f8f9e69 100644 --- a/nx/source/runtime/devices/socket.c +++ b/nx/source/runtime/devices/socket.c @@ -16,6 +16,7 @@ #include "result.h" #include "services/bsd.h" #include "services/ssl.h" +#include "services/nifm.h" #include "runtime/devices/socket.h" #include "runtime/hosversion.h" #include "../alloc.h" @@ -198,6 +199,38 @@ int socketSslConnectionGetSocketDescriptor(SslConnection *c) { return fd; } +int socketNifmRequestRegisterSocketDescriptor(NifmRequest* r, int sockfd) { + int fd = _socketGetFd(sockfd); + + if (fd==-1) + return -1; + + Result rc = nifmRequestRegisterSocketDescriptor(r, fd); + if (R_FAILED(rc)) { + g_bsdResult = rc; + errno = EIO; + return -1; + } + + return 0; +} + +int socketNifmRequestUnregisterSocketDescriptor(NifmRequest* r, int sockfd) { + int fd = _socketGetFd(sockfd); + + if (fd==-1) + return -1; + + Result rc = nifmRequestUnregisterSocketDescriptor(r, fd); + if (R_FAILED(rc)) { + g_bsdResult = rc; + errno = EIO; + return -1; + } + + return 0; +} + /***********************************************************************************************************************/ static int _socketGetFd(int fd) { diff --git a/nx/source/services/nifm.c b/nx/source/services/nifm.c index ba5ec484..f40fa39d 100644 --- a/nx/source/services/nifm.c +++ b/nx/source/services/nifm.c @@ -99,6 +99,11 @@ static Result _nifmCmdInBoolNoOut(Service* srv, bool inval, u32 cmd_id) { return _nifmCmdInU8NoOut(srv, inval!=0, cmd_id); } +static Result _nifmCmdInU32NoOut(Service* srv, u32 inval, u64 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval); +} + static Result _nifmCreateGeneralServiceOld(Service* srv_out) { return _nifmCmdGetSession(&g_nifmSrv, srv_out, 4); } @@ -452,3 +457,30 @@ Result nifmRequestGetAppletInfo(NifmRequest* r, u32 theme_color, void* buffer, s return rc; } +Result nifmRequestSetKeptInSleep(NifmRequest* r, bool flag) { + if (!serviceIsActive(&r->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nifmCmdInBoolNoOut(&r->s, flag, 23); +} + +Result nifmRequestRegisterSocketDescriptor(NifmRequest* r, int sockfd) { + if (!serviceIsActive(&r->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nifmCmdInU32NoOut(&r->s, (u32)sockfd, 24); +} + +Result nifmRequestUnregisterSocketDescriptor(NifmRequest* r, int sockfd) { + if (!serviceIsActive(&r->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nifmCmdInU32NoOut(&r->s, (u32)sockfd, 25); +} +