From 532fbef44f4c689063694f01a470c2f6240aec14 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Mon, 31 Jul 2017 15:12:51 +0200 Subject: [PATCH] Fix srv:pm handling for pre-7.x system versions (#365) --- libctru/include/3ds/services/srvpm.h | 20 +++++--- libctru/source/services/srvpm.c | 68 ++++++++++++++++++---------- libctru/source/srv.c | 8 +++- 3 files changed, 64 insertions(+), 32 deletions(-) diff --git a/libctru/include/3ds/services/srvpm.h b/libctru/include/3ds/services/srvpm.h index 5b47b54..b6dacb3 100644 --- a/libctru/include/3ds/services/srvpm.h +++ b/libctru/include/3ds/services/srvpm.h @@ -4,12 +4,18 @@ */ #pragma once -/// Initializes srv:pm. +/// Initializes srv:pm and the service API. Result srvPmInit(void); -/// Exits srv:pm. +/// Exits srv:pm and the service API. void srvPmExit(void); +/** + * @brief Gets the current srv:pm session handle. + * @return The current srv:pm session handle. + */ +Handle *srvPmGetSessionHandle(void); + /** * @brief Publishes a notification to a process. * @param notificationId ID of the notification. @@ -25,15 +31,15 @@ Result SRVPM_PublishToAll(u32 notificationId); /** * @brief Registers a process with SRV. - * @param procid ID of the process. + * @param pid ID of the process. * @param count Number of services within the service access control data. - * @param serviceaccesscontrol Service Access Control list. + * @param serviceAccessControlList Service Access Control list. */ -Result SRVPM_RegisterProcess(u32 procid, u32 count, void* serviceaccesscontrol); +Result SRVPM_RegisterProcess(u32 pid, u32 count, char (*serviceAccessControlList)[8]); /** * @brief Unregisters a process with SRV. - * @param procid ID of the process. + * @param pid ID of the process. */ -Result SRVPM_UnregisterProcess(u32 procid); +Result SRVPM_UnregisterProcess(u32 pid); diff --git a/libctru/source/services/srvpm.c b/libctru/source/services/srvpm.c index e5e8fdc..92c16c2 100644 --- a/libctru/source/services/srvpm.c +++ b/libctru/source/services/srvpm.c @@ -6,27 +6,58 @@ #include <3ds/synchronization.h> #include <3ds/services/srvpm.h> #include <3ds/ipc.h> +#include <3ds/os.h> + +#define IS_PRE_7X (osGetFirmVersion() >= SYSTEM_VERSION(2, 39, 4)) static Handle srvPmHandle; static int srvPmRefCount; Result srvPmInit(void) { + Result res = 0; + + if (!IS_PRE_7X) res = srvInit(); + if (R_FAILED(res)) return res; + if (AtomicPostIncrement(&srvPmRefCount)) return 0; - Result res = srvGetServiceHandle(&srvPmHandle, "srv:pm"); - if (R_FAILED(res)) AtomicDecrement(&srvPmRefCount); + + if (!IS_PRE_7X) + res = srvGetServiceHandleDirect(&srvPmHandle, "srv:pm"); + else + { + res = svcConnectToPort(&srvPmHandle, "srv:pm"); + if (R_SUCCEEDED(res)) res = srvInit(); + } + + if (R_FAILED(res)) srvPmExit(); return res; } void srvPmExit(void) { + if (*srvGetSessionHandle() != 0) srvExit(); if (AtomicDecrement(&srvPmRefCount)) return; svcCloseHandle(srvPmHandle); } -Result SRVPM_PublishToProcess(u32 notificationId, Handle process) +Handle *srvPmGetSessionHandle(void) +{ + return &srvPmHandle; +} + +static Result srvPmSendCommand(u32* cmdbuf) { Result rc = 0; + if (IS_PRE_7X) cmdbuf[0] |= 0x04000000; + rc = svcSendSyncRequest(srvPmHandle); + if (R_SUCCEEDED(rc)) rc = cmdbuf[1]; + + return rc; +} + +Result SRVPM_PublishToProcess(u32 notificationId, Handle process) +{ u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x1,1,2); // 0x10042 @@ -34,50 +65,39 @@ Result SRVPM_PublishToProcess(u32 notificationId, Handle process) cmdbuf[2] = IPC_Desc_SharedHandles(1); cmdbuf[3] = process; - if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle)))return rc; - - return cmdbuf[1]; + return srvPmSendCommand(cmdbuf); } Result SRVPM_PublishToAll(u32 notificationId) { - Result rc = 0; u32* cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x2,1,0); // 0x20040 cmdbuf[1] = notificationId; - if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle)))return rc; - - return cmdbuf[1]; + return srvPmSendCommand(cmdbuf); } -Result SRVPM_RegisterProcess(u32 procid, u32 count, void* serviceaccesscontrol) +Result SRVPM_RegisterProcess(u32 pid, u32 count, char (*serviceAccessControlList)[8]) { - Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x3,2,2); // 0x30082 - cmdbuf[1] = procid; + cmdbuf[1] = pid; cmdbuf[2] = count; - cmdbuf[3] = IPC_Desc_StaticBuffer(count*4,0); - cmdbuf[4] = (u32)serviceaccesscontrol; + cmdbuf[3] = IPC_Desc_StaticBuffer(count*8,0); + cmdbuf[4] = (u32)serviceAccessControlList; - if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle))) return rc; - - return cmdbuf[1]; + return srvPmSendCommand(cmdbuf); } -Result SRVPM_UnregisterProcess(u32 procid) +Result SRVPM_UnregisterProcess(u32 pid) { - Result rc = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x4,1,0); // 0x40040 - cmdbuf[1] = procid; + cmdbuf[1] = pid; - if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle))) return rc; - - return cmdbuf[1]; + return srvPmSendCommand(cmdbuf); } diff --git a/libctru/source/srv.c b/libctru/source/srv.c index 5e9a2a2..bc0bc35 100644 --- a/libctru/source/srv.c +++ b/libctru/source/srv.c @@ -11,6 +11,9 @@ #include <3ds/synchronization.h> #include <3ds/env.h> +#include <3ds/os.h> +#include <3ds/services/srvpm.h> + static Handle srvHandle; static int srvRefCount; @@ -20,7 +23,10 @@ Result srvInit(void) if (AtomicPostIncrement(&srvRefCount)) return 0; - rc = svcConnectToPort(&srvHandle, "srv:"); + if(osGetFirmVersion() < SYSTEM_VERSION(2, 39, 4) && *srvPmGetSessionHandle() != 0) + rc = svcDuplicateHandle(&srvHandle, *srvPmGetSessionHandle()); // Prior to system version 7.0 srv:pm was a superset of srv: + else + rc = svcConnectToPort(&srvHandle, "srv:"); if (R_FAILED(rc)) goto end; rc = srvRegisterClient();