#include <3ds.h> #include #include "srvsys.h" static Handle srvHandle; static int srvRefCount; static RecursiveLock initLock; static int initLockinit = 0; Result srvSysInit() { Result rc = 0; if (!initLockinit) { RecursiveLock_Init(&initLock); } RecursiveLock_Lock(&initLock); if (srvRefCount > 0) { RecursiveLock_Unlock(&initLock); return MAKERESULT(RL_INFO, RS_NOP, 25, RD_ALREADY_INITIALIZED); } while (1) { rc = svcConnectToPort(&srvHandle, "srv:"); if (R_LEVEL(rc) != RL_PERMANENT || R_SUMMARY(rc) != RS_NOTFOUND || R_DESCRIPTION(rc) != RD_NOT_FOUND) break; svcSleepThread(500000); } if (R_SUCCEEDED(rc)) { rc = srvSysRegisterClient(); srvRefCount++; } RecursiveLock_Unlock(&initLock); return rc; } Result srvSysRegisterClient(void) { Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x1, 0, 2); // 0x10002 cmdbuf[1] = IPC_Desc_CurProcessHandle(); if (R_FAILED(rc = svcSendSyncRequest(srvHandle))) return rc; return cmdbuf[1]; } Result srvSysExit() { Result rc; RecursiveLock_Lock(&initLock); if (srvRefCount > 1) { srvRefCount--; RecursiveLock_Unlock(&initLock); return MAKERESULT(RL_INFO, RS_NOP, 25, RD_BUSY); } if (srvHandle != 0) svcCloseHandle(srvHandle); else svcBreak(USERBREAK_ASSERT); rc = (Result)srvHandle; // yeah, I think this is a benign bug srvHandle = 0; srvRefCount--; RecursiveLock_Unlock(&initLock); return rc; } Result srvSysGetServiceHandle(Handle *out, const char *name) { Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x5, 4, 0); // 0x50100 strncpy((char *)&cmdbuf[1], name, 8); cmdbuf[3] = strlen(name); cmdbuf[4] = 0x0; if (R_FAILED(rc = svcSendSyncRequest(srvHandle))) return rc; if (out) *out = cmdbuf[3]; return cmdbuf[1]; } Result srvSysEnableNotification(Handle *semaphoreOut) { Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x2, 0, 0); if (R_FAILED(rc = svcSendSyncRequest(srvHandle))) return rc; if (semaphoreOut) *semaphoreOut = cmdbuf[3]; return cmdbuf[1]; } Result srvSysReceiveNotification(u32 *notificationIdOut) { Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0xB, 0, 0); // 0xB0000 if (R_FAILED(rc = svcSendSyncRequest(srvHandle))) return rc; if (notificationIdOut) *notificationIdOut = cmdbuf[2]; return cmdbuf[1]; } Result srvSysRegisterService(Handle *out, const char *name, int maxSessions) { Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x3, 4, 0); // 0x30100 strncpy((char *)&cmdbuf[1], name, 8); cmdbuf[3] = strlen(name); cmdbuf[4] = maxSessions; if (R_FAILED(rc = svcSendSyncRequest(srvHandle))) return rc; if (out) *out = cmdbuf[3]; return cmdbuf[1]; } Result srvSysUnregisterService(const char *name) { Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x4, 3, 0); // 0x400C0 strncpy((char *)&cmdbuf[1], name, 8); cmdbuf[3] = strlen(name); if (R_FAILED(rc = svcSendSyncRequest(srvHandle))) return rc; return cmdbuf[1]; }