diff --git a/nx/include/switch.h b/nx/include/switch.h index afdbaaa6..15429807 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -78,6 +78,7 @@ extern "C" { #include "switch/services/ns.h" #include "switch/services/ldr.h" #include "switch/services/ro.h" +#include "switch/services/ts.h" #include "switch/services/pm.h" #include "switch/services/set.h" #include "switch/services/lr.h" diff --git a/nx/include/switch/services/ts.h b/nx/include/switch/services/ts.h new file mode 100644 index 00000000..ecfa2cdd --- /dev/null +++ b/nx/include/switch/services/ts.h @@ -0,0 +1,47 @@ +/** + * @file friend.h + * @brief Temperature measurement (ts) service IPC wrapper. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../services/sm.h" + +/// Location +typedef enum { + TsLocation_Internal = 0, ///< Internal + TsLocation_External = 1, ///< External +} TsLocation; + +/// Initialize ts. +Result tsInitialize(void); + +/// Exit ts. +void tsExit(void); + +/// Gets the Service for ts. +Service* tsGetServiceSession(void); + +/** + * @brief Gets the min/max temperature for the specified \ref TsLocation. + * @param[in] location \ref TsLocation + * @param[out] min_temperature Output minimum temperature in Celsius. + * @param[out] max_temperature Output maximum temperature in Celsius. + */ +Result tsGetTemperatureRange(TsLocation location, s32 *min_temperature, s32 *max_temperature); + +/** + * @brief Gets the temperature for the specified \ref TsLocation. + * @param[in] location \ref TsLocation + * @param[out] temperature Output temperature in Celsius. + */ +Result tsGetTemperature(TsLocation location, s32 *temperature); + +/** + * @brief Gets the temperature for the specified \ref TsLocation, in MilliC. + * @param[in] location \ref TsLocation + * @param[out] temperature Output temperature in MilliC. + */ +Result tsGetTemperatureMilliC(TsLocation location, s32 *temperature); + diff --git a/nx/source/services/ts.c b/nx/source/services/ts.c new file mode 100644 index 00000000..53512ab9 --- /dev/null +++ b/nx/source/services/ts.c @@ -0,0 +1,118 @@ +#include +#include "types.h" +#include "result.h" +#include "arm/atomics.h" +#include "kernel/ipc.h" +#include "runtime/hosversion.h" +#include "services/sm.h" +#include "services/ts.h" + +static Service g_tsSrv; +static u64 g_tsRefCnt; + +Result tsInitialize(void) { + Result rc=0; + + atomicIncrement64(&g_tsRefCnt); + + if (serviceIsActive(&g_tsSrv)) + return 0; + + rc = smGetService(&g_tsSrv, "ts"); + + return rc; +} + +void tsExit(void) { + if (atomicDecrement64(&g_tsRefCnt) == 0) + serviceClose(&g_tsSrv); +} + +Service* tsGetServiceSession(void) { + return &g_tsSrv; +} + +static Result _tsCmdInU8Out32(u8 inval, u32 *out, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 inval; + } *raw; + + raw = serviceIpcPrepareHeader(&g_tsSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->inval = inval; + + Result rc = serviceIpcDispatch(&g_tsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 out; + } *resp; + + serviceIpcParse(&g_tsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out) *out = resp->out; + } + + return rc; +} + +Result tsGetTemperatureRange(TsLocation location, s32 *min_temperature, s32 *max_temperature) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u8 location; + } *raw; + + raw = serviceIpcPrepareHeader(&g_tsSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + raw->location = location; + + Result rc = serviceIpcDispatch(&g_tsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + s32 min_temperature; + s32 max_temperature; + } *resp; + + serviceIpcParse(&g_tsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && min_temperature) *min_temperature = resp->min_temperature; + if (R_SUCCEEDED(rc) && max_temperature) *max_temperature = resp->max_temperature; + } + + return rc; +} + +Result tsGetTemperature(TsLocation location, s32 *temperature) { + return _tsCmdInU8Out32(location, (u32*)temperature, 1); +} + +Result tsGetTemperatureMilliC(TsLocation location, s32 *temperature) { + return _tsCmdInU8Out32(location, (u32*)temperature, 3); +} +