diff --git a/nx/include/switch.h b/nx/include/switch.h index fe0acdab..29c18e68 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -19,6 +19,7 @@ extern "C" { #include #include #include +#include #ifdef __cplusplus } diff --git a/nx/include/switch/services/sm.h b/nx/include/switch/services/sm.h index 93324dcd..de38324f 100644 --- a/nx/include/switch/services/sm.h +++ b/nx/include/switch/services/sm.h @@ -1,5 +1,6 @@ bool smHasInitialized(); Result smInitialize(); +void smExit(void); Result smGetService(Handle* handle_out, const char* name); Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions); Result smUnregisterService(const char* name); diff --git a/nx/include/switch/services/vi.h b/nx/include/switch/services/vi.h new file mode 100644 index 00000000..0cdd2057 --- /dev/null +++ b/nx/include/switch/services/vi.h @@ -0,0 +1,16 @@ +typedef enum +{ + VISERVTYPE_Default = -1, + VISERVTYPE_Application = 0, + VISERVTYPE_System = 1, + VISERVTYPE_Manager = 2, +} viServiceType; + +Result viInitialize(viServiceType servicetype); +void viExit(void); +Handle viGetSessionService(void); +Handle viGetSession_IApplicationDisplayService(void); +Handle viGetSession_IHOSBinderDriverRelay(void); +Handle viGetSession_ISystemDisplayService(void); +Handle viGetSession_IManagerDisplayService(void); +Handle viGetSession_IHOSBinderDriverIndirect(void); diff --git a/nx/include/switch/svc.h b/nx/include/switch/svc.h index 17eeaa2e..6023419d 100644 --- a/nx/include/switch/svc.h +++ b/nx/include/switch/svc.h @@ -52,6 +52,7 @@ Result svcConnectToNamedPort(Handle* session, const char* name); Result svcSendSyncRequest(Handle session); Result svcBreak(u32 breakReason, u64 inval1, u64 inval2); Result svcGetInfo(u64* out, u64 id0, Handle handle, u64 id1); +Result svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, u64 unk1);//unk* are normally 0? Result svcAcceptSession(Handle *session_handle, Handle port_handle); Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout); Result svcQueryPhysicalAddress(u64 out[3], u64 virtaddr); diff --git a/nx/source/kernel/svc.s b/nx/source/kernel/svc.s index a58fda8a..53940f32 100644 --- a/nx/source/kernel/svc.s +++ b/nx/source/kernel/svc.s @@ -84,6 +84,16 @@ SVC_BEGIN svcGetInfo ret SVC_END +SVC_BEGIN svcCreateSession + stp x0, x1, [sp, #-16]! + svc 0x40 + ldr x3, [sp], #8 + str w1, [x3] + ldr x3, [sp], #8 + str w2, [x3] + ret +SVC_END + SVC_BEGIN svcAcceptSession str x0, [sp, #-16]! svc 0x41 diff --git a/nx/source/services/sm.c b/nx/source/services/sm.c index 2e165a58..26390167 100644 --- a/nx/source/services/sm.c +++ b/nx/source/services/sm.c @@ -47,6 +47,15 @@ Result smInitialize() { return rc; } +void smExit(void) +{ + if(smHasInitialized()) + { + svcCloseHandle(g_smHandle); + g_smHandle = -1; + } +} + static u64 _EncodeName(const char* name) { u64 name_encoded = 0; diff --git a/nx/source/services/vi.c b/nx/source/services/vi.c new file mode 100644 index 00000000..947ede1e --- /dev/null +++ b/nx/source/services/vi.c @@ -0,0 +1,165 @@ +#include +#include + +static Handle g_viServiceSession = 0; +static u32 g_viServiceType = -1; +static Handle g_viIApplicationDisplayService = 0; +static Handle g_viIHOSBinderDriverRelay = 0; +static Handle g_viISystemDisplayService = 0; +static Handle g_viIManagerDisplayService = 0; +static Handle g_viIHOSBinderDriverIndirect = 0; + +static Result _viGetSession(Handle sessionhandle, Handle* handle_out, void* inraw, size_t rawsize); +static Result _viGetSessionNoParams(Handle sessionhandle, Handle* handle_out, u64 cmd_id); + +Result viInitialize(viServiceType servicetype) { + if(g_viServiceType!=-1)return -1; + + Result rc = 0; + + if (servicetype==VISERVTYPE_Default || servicetype==VISERVTYPE_Manager) { + rc = smGetService(&g_viServiceSession, "vi:m"); + g_viServiceType = 2; + } + + if ((servicetype==VISERVTYPE_Default && R_FAILED(rc)) || servicetype==VISERVTYPE_System) { + rc = smGetService(&g_viServiceSession, "vi:s"); + g_viServiceType = 1; + } + + if ((servicetype==VISERVTYPE_Default && R_FAILED(rc)) || servicetype==VISERVTYPE_Application) + { + rc = smGetService(&g_viServiceSession, "vi:u"); + g_viServiceType = 0; + } + + if (R_SUCCEEDED(rc)) { + struct { + u64 magic; + u64 cmd_id; + u64 inval0; + } raw; + + raw.magic = SFCI_MAGIC; + raw.cmd_id = g_viServiceType; + raw.inval0 = 0; + + rc = _viGetSession(g_viServiceSession, &g_viIApplicationDisplayService, &raw, sizeof(raw)); + } + + if (R_SUCCEEDED(rc))rc = _viGetSessionNoParams(g_viIApplicationDisplayService, &g_viIHOSBinderDriverRelay, 100); + if (g_viServiceType>=VISERVTYPE_System && R_SUCCEEDED(rc))rc = _viGetSessionNoParams(g_viIApplicationDisplayService, &g_viISystemDisplayService, 101); + if (g_viServiceType>=VISERVTYPE_Manager && R_SUCCEEDED(rc))rc = _viGetSessionNoParams(g_viIApplicationDisplayService, &g_viIManagerDisplayService, 102); + if (g_viServiceType>=VISERVTYPE_System && R_SUCCEEDED(rc))rc = _viGetSessionNoParams(g_viIApplicationDisplayService, &g_viIHOSBinderDriverIndirect, 103); + + if (R_FAILED(rc))g_viServiceType = -1; + + return rc; +} + +void viExit(void) +{ + if(g_viServiceType==-1)return; + + g_viServiceType = -1; + + if(g_viServiceSession) + { + svcCloseHandle(g_viServiceSession); + g_viServiceSession = 0; + } + + if(g_viIApplicationDisplayService) + { + svcCloseHandle(g_viIApplicationDisplayService); + g_viIApplicationDisplayService = 0; + } + + if(g_viISystemDisplayService) + { + svcCloseHandle(g_viISystemDisplayService); + g_viISystemDisplayService = 0; + } + + if(g_viIManagerDisplayService) + { + svcCloseHandle(g_viIManagerDisplayService); + g_viIManagerDisplayService = 0; + } + + if(g_viIHOSBinderDriverIndirect) + { + svcCloseHandle(g_viIHOSBinderDriverIndirect); + g_viIHOSBinderDriverIndirect = 0; + } +} + +Handle viGetSessionService(void) +{ + return g_viServiceSession; +} + +Handle viGetSession_IApplicationDisplayService(void) +{ + return g_viIApplicationDisplayService; +} + +Handle viGetSession_IHOSBinderDriverRelay(void) +{ + return g_viIHOSBinderDriverRelay; +} + +Handle viGetSession_ISystemDisplayService(void) +{ + return g_viISystemDisplayService; +} + +Handle viGetSession_IManagerDisplayService(void) +{ + return g_viIManagerDisplayService; +} + +Handle viGetSession_IHOSBinderDriverIndirect(void) +{ + return g_viIHOSBinderDriverIndirect; +} + +static Result _viGetSession(Handle sessionhandle, Handle* handle_out, void* inraw, size_t rawsize) { + IpcCommand c; + ipcInitialize(&c); + + memcpy(ipcPrepareHeader(&c, rawsize), inraw, rawsize); + + Result rc = ipcDispatch(sessionhandle); + + if (R_SUCCEEDED(rc)) { + IpcCommandResponse r; + ipcParseResponse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *handle_out = r.Handles[0]; + } + } + + return rc; +} + +static Result _viGetSessionNoParams(Handle sessionhandle, Handle* handle_out, u64 cmd_id) { + struct { + u64 magic; + u64 cmd_id; + } raw; + + raw.magic = SFCI_MAGIC; + raw.cmd_id = cmd_id; + + return _viGetSession(sessionhandle, handle_out, &raw, sizeof(raw)); +} + diff --git a/nx/source/system/appExit.c b/nx/source/system/appExit.c index 8ecf701a..3b4d1db2 100644 --- a/nx/source/system/appExit.c +++ b/nx/source/system/appExit.c @@ -1,5 +1,7 @@ #include +#include void __attribute__((weak)) __appExit(void) { // Initialize services + smExit(); } diff --git a/nx/source/system/appInit.c b/nx/source/system/appInit.c index 2d1d1bcb..d018eeb5 100644 --- a/nx/source/system/appInit.c +++ b/nx/source/system/appInit.c @@ -1,5 +1,7 @@ #include +#include void __attribute__((weak)) __appInit(void) { // Initialize services + smInitialize(); }