/** * @file psc.h * @brief PSC service IPC wrapper. * @author SciresM * @copyright libnx Authors */ #include "types.h" #include "result.h" #include "arm/atomics.h" #include "kernel/ipc.h" #include "kernel/detect.h" #include "kernel/event.h" #include "services/psc.h" #include "services/sm.h" static Service g_pscSrv; static u64 g_refCnt; static Result _pscPmModuleInitialize(PscPmModule *module, u16 module_id, const u16 *dependencies, size_t dependency_count, bool autoclear); static Result _pscPmModuleAcknowledge(PscPmModule *module); static Result _pscPmModuleAcknowledgeEx(PscPmModule *module, PscPmState state); Result pscInitialize(void) { Result rc = 0; atomicIncrement64(&g_refCnt); if (serviceIsActive(&g_pscSrv)) return rc; rc = smGetService(&g_pscSrv, "psc:m"); if (R_SUCCEEDED(rc)) { rc = serviceConvertToDomain(&g_pscSrv); } if (R_FAILED(rc)) pscExit(); return rc; } void pscExit(void) { if (atomicDecrement64(&g_refCnt) == 0) { serviceClose(&g_pscSrv); } } Result pscGetPmModule(PscPmModule *out, u16 module_id, const u16 *dependencies, size_t dependency_count, bool autoclear) { IpcCommand c; ipcInitialize(&c); struct { u64 magic; u64 cmd_id; } *raw; raw = serviceIpcPrepareHeader(&g_pscSrv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 0; Result rc = serviceIpcDispatch(&g_pscSrv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; struct { u64 magic; u64 result; } *resp; serviceIpcParse(&g_pscSrv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc)) { serviceCreateSubservice(&out->srv, &g_pscSrv, &r, 0); rc = _pscPmModuleInitialize(out, module_id, dependencies, dependency_count, autoclear); if (R_FAILED(rc)) { serviceClose(&out->srv); } } } return rc; } Result _pscPmModuleInitialize(PscPmModule *module, u16 module_id, const u16 *dependencies, size_t dependency_count, bool autoclear) { IpcCommand c; ipcInitialize(&c); ipcAddSendBuffer(&c, dependencies, dependency_count * sizeof(u16), BufferType_Normal); struct { u64 magic; u64 cmd_id; u32 module_id; } *raw; raw = serviceIpcPrepareHeader(&module->srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 0; raw->module_id = module_id; Result rc = serviceIpcDispatch(&module->srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; struct { u64 magic; u64 result; } *resp; serviceIpcParse(&module->srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc)) { eventLoadRemote(&module->event, r.Handles[0], autoclear); module->module_id = module_id; } } return rc; } Result pscPmModuleGetRequest(PscPmModule *module, PscPmState *out_state, u32 *out_flags) { IpcCommand c; ipcInitialize(&c); struct { u64 magic; u64 cmd_id; } *raw; raw = serviceIpcPrepareHeader(&module->srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 1; Result rc = serviceIpcDispatch(&module->srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; struct { u64 magic; u64 result; u32 state; u32 flags; } *resp; serviceIpcParse(&module->srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc)) { *out_state = (PscPmState)resp->state; *out_flags = resp->flags; } } return rc; } Result pscPmModuleAcknowledge(PscPmModule *module, PscPmState state) { if (kernelAbove600()) { return _pscPmModuleAcknowledgeEx(module, state); } else { return _pscPmModuleAcknowledge(module); } } Result pscPmModuleFinalize(PscPmModule *module) { IpcCommand c; ipcInitialize(&c); struct { u64 magic; u64 cmd_id; } *raw; raw = serviceIpcPrepareHeader(&module->srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 3; Result rc = serviceIpcDispatch(&module->srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; struct { u64 magic; u64 result; } *resp; serviceIpcParse(&module->srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; } return rc; } static Result _pscPmModuleAcknowledge(PscPmModule *module) { IpcCommand c; ipcInitialize(&c); struct { u64 magic; u64 cmd_id; } *raw; raw = serviceIpcPrepareHeader(&module->srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 2; Result rc = serviceIpcDispatch(&module->srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; struct { u64 magic; u64 result; } *resp; serviceIpcParse(&module->srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; } return rc; } static Result _pscPmModuleAcknowledgeEx(PscPmModule *module, PscPmState state) { IpcCommand c; ipcInitialize(&c); struct { u64 magic; u64 cmd_id; u32 state; } *raw; raw = serviceIpcPrepareHeader(&module->srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 4; raw->state = state; Result rc = serviceIpcDispatch(&module->srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; struct { u64 magic; u64 result; } *resp; serviceIpcParse(&module->srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; } return rc; }