Implemented apm.

This commit is contained in:
yellows8 2017-12-29 16:15:17 -05:00
parent fa318656b3
commit 1dda414f31
4 changed files with 165 additions and 0 deletions

View File

@ -26,6 +26,7 @@ extern "C" {
#include <switch/services/sm.h>
#include <switch/services/fs.h>
#include <switch/services/acc.h>
#include <switch/services/apm.h>
#include <switch/services/applet.h>
#include <switch/services/binder.h>
#include <switch/services/bsd.h>

View File

@ -0,0 +1,7 @@
/// These are used internally by applet.
Result apmInitialize(void);
void apmExit(void);
Result apmSetPerformanceConfiguration(u32 PerformanceMode, u32 PerformanceConfiguration);
Result apmGetPerformanceConfiguration(u32 PerformanceMode, u32 *PerformanceConfiguration);

144
nx/source/services/apm.c Normal file
View File

@ -0,0 +1,144 @@
#include <string.h>
#include <switch.h>
static Handle g_apmServiceSession = INVALID_HANDLE;
static Handle g_apmISession = INVALID_HANDLE;
static Result _apmGetSession(Handle sessionhandle, Handle* handle_out, u64 cmd_id);
Result apmInitialize(void) {
if (g_apmServiceSession != INVALID_HANDLE) return 0;
Result rc = 0;
rc = smGetService(&g_apmServiceSession, "apm:p");
if (R_FAILED(rc)) rc = smGetService(&g_apmServiceSession, "apm");
if (R_SUCCEEDED(rc)) rc = _apmGetSession(g_apmServiceSession, &g_apmISession, 0);//OpenSession. Official sw doesn't open this until using commands which need it, when it wasn't already opened.
if (R_FAILED(rc)) apmExit();
return rc;
}
void apmExit(void)
{
if (g_apmServiceSession == INVALID_HANDLE) return;
if (g_apmServiceSession != INVALID_HANDLE) {
svcCloseHandle(g_apmServiceSession);
g_apmServiceSession = INVALID_HANDLE;
}
if (g_apmISession != INVALID_HANDLE) {
svcCloseHandle(g_apmISession);
g_apmISession = INVALID_HANDLE;
}
}
static Result _apmGetSession(Handle sessionhandle, Handle* handle_out, u64 cmd_id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
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;
}
Result apmSetPerformanceConfiguration(u32 PerformanceMode, u32 PerformanceConfiguration) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 PerformanceMode;
u32 PerformanceConfiguration;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->PerformanceMode = PerformanceMode;
raw->PerformanceConfiguration = PerformanceConfiguration;
Result rc = ipcDispatch(g_apmISession);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result apmGetPerformanceConfiguration(u32 PerformanceMode, u32 *PerformanceConfiguration) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 PerformanceMode;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
raw->PerformanceMode = PerformanceMode;
Result rc = ipcDispatch(g_apmISession);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u32 PerformanceConfiguration;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && PerformanceConfiguration) *PerformanceConfiguration = resp->PerformanceConfiguration;
}
return rc;
}

View File

@ -4,6 +4,7 @@
__attribute__((weak)) u32 __nx_applet_type = APPLET_TYPE_Default;
__attribute__((weak)) bool __nx_applet_auto_notifyrunning = true;
__attribute__((weak)) u8 __nx_applet_AppletAttribute[0x80];
__attribute__((weak)) u32 __nx_applet_PerformanceConfiguration[2] = {/*0x92220008*//*0x20004*//*0x92220007*/0, 0};
static Handle g_appletServiceSession = INVALID_HANDLE;
static Handle g_appletProxySession = INVALID_HANDLE;
@ -57,6 +58,7 @@ Result appletInitialize(void) {
Result rc = 0;
Handle prochandle = CUR_PROCESS_HANDLE;
s32 tmpindex=0;
u32 i;
u32 msg=0;
if (__nx_applet_type==APPLET_TYPE_None) return 0;
@ -153,6 +155,15 @@ Result appletInitialize(void) {
if (R_SUCCEEDED(rc)) rc = _appletSetOperationModeChangedNotification(1);
if (R_SUCCEEDED(rc)) rc = _appletSetPerformanceModeChangedNotification(1);
if (R_SUCCEEDED(rc)) rc = apmInitialize();
if (R_SUCCEEDED(rc)) {//Official apps aren't known to use apmSetPerformanceConfiguration with mode=1.
for (i=0; i<2; i++) {//This is broken with the regular "apm" service.
if (__nx_applet_PerformanceConfiguration[i]) rc = apmSetPerformanceConfiguration(i, __nx_applet_PerformanceConfiguration[i]);
if (R_FAILED(rc)) break;
}
}
if (R_FAILED(rc)) appletExit();
return rc;
@ -162,6 +173,8 @@ void appletExit(void)
{
if (g_appletServiceSession == INVALID_HANDLE) return;
apmExit();
if (g_appletMessageEventHandle != INVALID_HANDLE) {
svcCloseHandle(g_appletMessageEventHandle);
g_appletMessageEventHandle = INVALID_HANDLE;