Fix srv:pm handling for pre-7.x system versions (#365)

This commit is contained in:
TuxSH 2017-07-31 15:12:51 +02:00 committed by Dave Murphy
parent e1ddc74c1c
commit 532fbef44f
3 changed files with 64 additions and 32 deletions

View File

@ -4,12 +4,18 @@
*/ */
#pragma once #pragma once
/// Initializes srv:pm. /// Initializes srv:pm and the service API.
Result srvPmInit(void); Result srvPmInit(void);
/// Exits srv:pm. /// Exits srv:pm and the service API.
void srvPmExit(void); 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. * @brief Publishes a notification to a process.
* @param notificationId ID of the notification. * @param notificationId ID of the notification.
@ -25,15 +31,15 @@ Result SRVPM_PublishToAll(u32 notificationId);
/** /**
* @brief Registers a process with SRV. * @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 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. * @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);

View File

@ -6,27 +6,58 @@
#include <3ds/synchronization.h> #include <3ds/synchronization.h>
#include <3ds/services/srvpm.h> #include <3ds/services/srvpm.h>
#include <3ds/ipc.h> #include <3ds/ipc.h>
#include <3ds/os.h>
#define IS_PRE_7X (osGetFirmVersion() >= SYSTEM_VERSION(2, 39, 4))
static Handle srvPmHandle; static Handle srvPmHandle;
static int srvPmRefCount; static int srvPmRefCount;
Result srvPmInit(void) Result srvPmInit(void)
{ {
Result res = 0;
if (!IS_PRE_7X) res = srvInit();
if (R_FAILED(res)) return res;
if (AtomicPostIncrement(&srvPmRefCount)) return 0; 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; return res;
} }
void srvPmExit(void) void srvPmExit(void)
{ {
if (*srvGetSessionHandle() != 0) srvExit();
if (AtomicDecrement(&srvPmRefCount)) return; if (AtomicDecrement(&srvPmRefCount)) return;
svcCloseHandle(srvPmHandle); svcCloseHandle(srvPmHandle);
} }
Result SRVPM_PublishToProcess(u32 notificationId, Handle process) Handle *srvPmGetSessionHandle(void)
{
return &srvPmHandle;
}
static Result srvPmSendCommand(u32* cmdbuf)
{ {
Result rc = 0; 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(); u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x1,1,2); // 0x10042 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[2] = IPC_Desc_SharedHandles(1);
cmdbuf[3] = process; cmdbuf[3] = process;
if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle)))return rc; return srvPmSendCommand(cmdbuf);
return cmdbuf[1];
} }
Result SRVPM_PublishToAll(u32 notificationId) Result SRVPM_PublishToAll(u32 notificationId)
{ {
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer(); u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x2,1,0); // 0x20040 cmdbuf[0] = IPC_MakeHeader(0x2,1,0); // 0x20040
cmdbuf[1] = notificationId; cmdbuf[1] = notificationId;
if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle)))return rc; return srvPmSendCommand(cmdbuf);
return cmdbuf[1];
} }
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(); u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x3,2,2); // 0x30082 cmdbuf[0] = IPC_MakeHeader(0x3,2,2); // 0x30082
cmdbuf[1] = procid; cmdbuf[1] = pid;
cmdbuf[2] = count; cmdbuf[2] = count;
cmdbuf[3] = IPC_Desc_StaticBuffer(count*4,0); cmdbuf[3] = IPC_Desc_StaticBuffer(count*8,0);
cmdbuf[4] = (u32)serviceaccesscontrol; cmdbuf[4] = (u32)serviceAccessControlList;
if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle))) return rc; return srvPmSendCommand(cmdbuf);
return cmdbuf[1];
} }
Result SRVPM_UnregisterProcess(u32 procid) Result SRVPM_UnregisterProcess(u32 pid)
{ {
Result rc = 0;
u32 *cmdbuf = getThreadCommandBuffer(); u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x4,1,0); // 0x40040 cmdbuf[0] = IPC_MakeHeader(0x4,1,0); // 0x40040
cmdbuf[1] = procid; cmdbuf[1] = pid;
if(R_FAILED(rc = svcSendSyncRequest(srvPmHandle))) return rc; return srvPmSendCommand(cmdbuf);
return cmdbuf[1];
} }

View File

@ -11,6 +11,9 @@
#include <3ds/synchronization.h> #include <3ds/synchronization.h>
#include <3ds/env.h> #include <3ds/env.h>
#include <3ds/os.h>
#include <3ds/services/srvpm.h>
static Handle srvHandle; static Handle srvHandle;
static int srvRefCount; static int srvRefCount;
@ -20,6 +23,9 @@ Result srvInit(void)
if (AtomicPostIncrement(&srvRefCount)) return 0; if (AtomicPostIncrement(&srvRefCount)) return 0;
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:"); rc = svcConnectToPort(&srvHandle, "srv:");
if (R_FAILED(rc)) goto end; if (R_FAILED(rc)) goto end;