From 52be537b487e15e1523bcd6506af330c6abc6d0a Mon Sep 17 00:00:00 2001 From: Joel Date: Fri, 12 Jan 2018 06:34:56 -0600 Subject: [PATCH] Add more ndm:u functions. (#386) --- libctru/include/3ds/services/ndm.h | 127 +++++++++++++++- libctru/source/services/ndm.c | 225 +++++++++++++++++++++++++++-- libctru/source/services/uds.c | 6 +- 3 files changed, 338 insertions(+), 20 deletions(-) diff --git a/libctru/include/3ds/services/ndm.h b/libctru/include/3ds/services/ndm.h index 5490659..1039114 100644 --- a/libctru/include/3ds/services/ndm.h +++ b/libctru/include/3ds/services/ndm.h @@ -4,13 +4,54 @@ */ #pragma once +/// Exclusive states. typedef enum { EXCLUSIVE_STATE_NONE = 0, EXCLUSIVE_STATE_INFRASTRUCTURE = 1, EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS = 2, EXCLUSIVE_STATE_STREETPASS = 3, EXCLUSIVE_STATE_STREETPASS_DATA = 4, -} NDM_ExclusiveState; +} ndmExclusiveState; + +/// Current states. +typedef enum { + STATE_INITIAL = 0, + STATE_SUSPENDED = 1, + STATE_INFRASTRUCTURE_CONNECTING = 2, + STATE_INFRASTRUCTURE_CONNECTED = 3, + STATE_INFRASTRUCTURE_WORKING = 4, + STATE_INFRASTRUCTURE_SUSPENDING = 5, + STATE_INFRASTRUCTURE_FORCE_SUSPENDING = 6, + STATE_INFRASTRUCTURE_DISCONNECTING = 7, + STATE_INFRASTRUCTURE_FORCE_DISCONNECTING = 8, + STATE_CEC_WORKING = 9, + STATE_CEC_FORCE_SUSPENDING = 10, + STATE_CEC_SUSPENDING = 11, +} ndmState; + +// Daemons. +typedef enum { + DAEMON_CEC = 0, + DAEMON_BOSS = 1, + DAEMON_NIM = 2, + DAEMON_FRIENDS = 3, +} ndmDaemon; + +/// Used to specify multiple daemons. +typedef enum { + DAEMON_MASK_CEC = BIT(DAEMON_CEC), + DAEMON_MASK_BOSS = BIT(DAEMON_BOSS), + DAEMON_MASK_NIM = BIT(DAEMON_NIM), + DAEMON_MASK_FRIENDS = BIT(DAEMON_FRIENDS), +} ndmDaemonMask; + +// Daemon status. +typedef enum { + DAEMON_STATUS_BUSY = 0, + DAEMON_STATUS_IDLE = 1, + DAEMON_STATUS_SUSPENDING = 2, + DAEMON_STATUS_SUSPENDED = 3, +} ndmDaemonStatus; /// Initializes ndmu. Result ndmuInit(void); @@ -18,7 +59,87 @@ Result ndmuInit(void); /// Exits ndmu. void ndmuExit(void); -Result ndmuEnterExclusiveState(NDM_ExclusiveState state); +/** + * @brief Sets the network daemon to an exclusive state. + * @param state State specified in the ndmExclusiveState enumerator. + */ +Result NDMU_EnterExclusiveState(ndmExclusiveState state); -Result ndmuLeaveExclusiveState(void); +/// Cancels an exclusive state for the network daemon. +Result NDMU_LeaveExclusiveState(void); + +/** + * @brief Returns the exclusive state for the network daemon. + * @param state Pointer to write the exclsuive state to. + */ +Result NDMU_GetExclusiveState(ndmExclusiveState *state); + +/// Locks the exclusive state. +Result NDMU_LockState(void); + +/// Unlocks the exclusive state. +Result NDMU_UnlockState(void); + +/** + * @brief Suspends network daemon. + * @param mask The specified daemon. + */ +Result NDMU_SuspendDaemons(ndmDaemonMask mask); + +/** + * @brief Resumes network daemon. + * @param mask The specified daemon. + */ +Result NDMU_ResumeDaemons(ndmDaemonMask mask); + +/** + * @brief Suspends scheduling for all network daemons. + * @param flag 0 = Wait for completion, 1 = Perform in background. + */ +Result NDMU_SuspendScheduler(u32 flag); + +/// Resumes daemon scheduling. +Result NDMU_ResumeScheduler(void); + +/** + * @brief Returns the current state for the network daemon. + * @param state Pointer to write the current state to. + */ +Result NDMU_GetCurrentState(ndmState *state); + +/** + * @brief Returns the daemon state. + * @param state Pointer to write the daemons state to. + */ +Result NDMU_QueryStatus(ndmDaemonStatus *status); + +/** + * @brief Sets the scan interval. + * @param interval Value to set the scan interval to. + */ +Result NDMU_SetScanInterval(u32 interval); + +/** + * @brief Returns the scan interval. + * @param interval Pointer to write the interval value to. + */ +Result NDMU_GetScanInterval(u32 *interval); + +/** + * @brief Returns the retry interval. + * @param interval Pointer to write the interval value to. + */ +Result NDMU_GetRetryInterval(u32 *interval); + +/// Reverts network daemon to defaults. +Result NDMU_ResetDaemons(void); + +/** + * @brief Gets the current default daemon bit mask. + * @param interval Pointer to write the default daemon mask value to. The default value is (DAEMONMASK_CEC | DAEMONMASK_FRIENDS) + */ +Result NDMU_GetDefaultDaemons(ndmDaemonMask *mask); + +/// Clears half awake mac filter. +Result NDMU_ClearMacFilter(void); diff --git a/libctru/source/services/ndm.c b/libctru/source/services/ndm.c index dcc84b5..9330935 100644 --- a/libctru/source/services/ndm.c +++ b/libctru/source/services/ndm.c @@ -10,30 +10,30 @@ #include <3ds/services/ndm.h> #include <3ds/ipc.h> -Handle __ndmu_servhandle; -static int __ndmu_refcount; +Handle ndmuHandle; +static int ndmuRefCount; Result ndmuInit(void) { Result ret=0; - if (AtomicPostIncrement(&__ndmu_refcount)) return 0; + if (AtomicPostIncrement(&ndmuRefCount)) return 0; - ret = srvGetServiceHandle(&__ndmu_servhandle, "ndm:u"); - if (R_FAILED(ret)) AtomicDecrement(&__ndmu_refcount); + ret = srvGetServiceHandle(&ndmuHandle, "ndm:u"); + if (R_FAILED(ret)) AtomicDecrement(&ndmuRefCount); return ret; } void ndmuExit(void) { - if (AtomicDecrement(&__ndmu_refcount)) return; + if (AtomicDecrement(&ndmuRefCount)) return; - svcCloseHandle(__ndmu_servhandle); - __ndmu_servhandle = 0; + svcCloseHandle(ndmuHandle); + ndmuHandle = 0; } -Result ndmuEnterExclusiveState(NDM_ExclusiveState state) +Result NDMU_EnterExclusiveState(ndmExclusiveState state) { u32* cmdbuf=getThreadCommandBuffer(); @@ -42,12 +42,12 @@ Result ndmuEnterExclusiveState(NDM_ExclusiveState state) cmdbuf[2]=IPC_Desc_CurProcessHandle(); Result ret=0; - if(R_FAILED(ret=svcSendSyncRequest(__ndmu_servhandle)))return ret; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; - return cmdbuf[1]; + return (Result)cmdbuf[1]; } -Result ndmuLeaveExclusiveState(void) +Result NDMU_LeaveExclusiveState(void) { u32* cmdbuf=getThreadCommandBuffer(); @@ -55,8 +55,205 @@ Result ndmuLeaveExclusiveState(void) cmdbuf[1]=IPC_Desc_CurProcessHandle(); Result ret=0; - if(R_FAILED(ret=svcSendSyncRequest(__ndmu_servhandle)))return ret; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; - return cmdbuf[1]; + return (Result)cmdbuf[1]; } +Result NDMU_GetExclusiveState(ndmExclusiveState *state) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x3,0,0); // 0x30000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + *state = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result NDMU_LockState(void) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x4,0,2); // 0x40002 + cmdbuf[1]=IPC_Desc_CurProcessHandle(); + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_UnlockState(void) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x5,0,2); // 0x50002 + cmdbuf[1]=IPC_Desc_CurProcessHandle(); + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_SuspendDaemons(ndmDaemonMask mask) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x6,1,0); // 0x60040 + cmdbuf[1]=mask; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_ResumeDaemons(ndmDaemonMask mask) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x7,1,0); // 0x70040 + cmdbuf[1]=mask; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_SuspendScheduler(u32 flag) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x8,1,0); // 0x80040 + cmdbuf[1]=flag; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_ResumeScheduler(void) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x9,0,0); // 0x90000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_GetCurrentState(ndmState *state) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0xA,0,0); // 0xA0000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + *state = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result NDMU_QueryStatus(ndmDaemonStatus *status) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0xD,1,0); // 0xD0000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + *status = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result NDMU_SetScanInterval(u32 interval) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x10,1,0); // 0x10040 + cmdbuf[1]=interval; + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_GetScanInterval(u32 *interval) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x11,0,0); // 0x110000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + *interval = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result NDMU_GetRetryInterval(u32 *interval) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x13,0,0); // 0x130000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + *interval = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result NDMU_ResetDaemons(void) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x15,0,0); // 0x150000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} + +Result NDMU_GetDefaultDaemons(ndmDaemonMask *mask) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x16,0,0); // 0x160000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + *mask = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result NDMU_ClearMacFilter(void) +{ + u32* cmdbuf=getThreadCommandBuffer(); + + cmdbuf[0]=IPC_MakeHeader(0x17,0,0); // 0x170000 + + Result ret=0; + if(R_FAILED(ret=svcSendSyncRequest(ndmuHandle)))return ret; + + return (Result)cmdbuf[1]; +} diff --git a/libctru/source/services/uds.c b/libctru/source/services/uds.c index 2611337..7f292d9 100644 --- a/libctru/source/services/uds.c +++ b/libctru/source/services/uds.c @@ -55,7 +55,7 @@ Result udsInit(size_t sharedmem_size, const char *username) if(R_SUCCEEDED(ret)) { ndm_state = 1; - ret = ndmuEnterExclusiveState(EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS); + ret = NDMU_EnterExclusiveState(EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS); if(R_SUCCEEDED(ret)) { ndm_state = 2; @@ -80,7 +80,7 @@ Result udsInit(size_t sharedmem_size, const char *username) { if(ndm_state) { - if(ndm_state==2)ndmuLeaveExclusiveState(); + if(ndm_state==2)NDMU_LeaveExclusiveState(); ndmuExit(); } @@ -111,7 +111,7 @@ void udsExit(void) svcCloseHandle(__uds_connectionstatus_event); __uds_connectionstatus_event = 0; - ndmuLeaveExclusiveState(); + NDMU_LeaveExclusiveState(); ndmuExit(); }