From 040b33c4573fefca24062a5112aba26111941074 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 6 Oct 2019 22:06:22 -0400 Subject: [PATCH] time: Updated for new-ipc. Renamed _timeGetClockSession to timeGetServiceSession_SystemClock, and added it to the .h. Added timeGetServiceSession_TimeZoneService. Fixed the order of cmds. Fixed param types for timeGetTotalLocationNameCount, timeLoadLocationNameList, timeToPosixTime, and timeToPosixTimeWithMyRule. The location_name_size param for timeLoadLocationNameList was replaced with location_name_max, which is max entries instead of buffer byte-size. Internal improvements and improved docs. --- nx/include/switch/services/time.h | 36 +- nx/source/services/time.c | 525 ++++++------------------------ 2 files changed, 130 insertions(+), 431 deletions(-) diff --git a/nx/include/switch/services/time.h b/nx/include/switch/services/time.h index a76ebd25..6e97c828 100644 --- a/nx/include/switch/services/time.h +++ b/nx/include/switch/services/time.h @@ -7,7 +7,7 @@ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" /// Time clock type. typedef enum { @@ -28,11 +28,11 @@ typedef struct { } TimeCalendarTime; typedef struct { - u32 wday; ///< 0-based day-of-week. - u32 yday; ///< 0-based day-of-year. - char timezoneName[8]; ///< Timezone name string. - u32 DST; ///< 0 = no DST, 1 = DST. - s32 offset; ///< Seconds relative to UTC for this timezone. + u32 wday; ///< 0-based day-of-week. + u32 yday; ///< 0-based day-of-year. + char timezoneName[8]; ///< Timezone name string. + u32 DST; ///< 0 = no DST, 1 = DST. + s32 offset; ///< Seconds relative to UTC for this timezone. } TimeCalendarAdditionalInfo; typedef struct { @@ -43,11 +43,27 @@ typedef struct { char name[0x24]; } TimeLocationName; +/// Initialize time. Used automatically during app startup. Result timeInitialize(void); + +/// Exit time. Used automatically during app startup. void timeExit(void); +/// Gets the Service object for the actual time service session. Service* timeGetServiceSession(void); +/// Gets the Service object for ISystemClock with the specified \ref TimeType. This will return NULL when the type is invalid. +Service* timeGetServiceSession_SystemClock(TimeType type); + +/// Gets the Service object for ITimeZoneService. +Service* timeGetServiceSession_TimeZoneService(void); + +/** + * @brief Gets the time for the specified clock. + * @param[in] type Clock to use. + * @param[out] timestamp POSIX UTC timestamp. + * @return Result code. + */ Result timeGetCurrentTime(TimeType type, u64 *timestamp); /** @@ -60,13 +76,13 @@ Result timeSetCurrentTime(TimeType type, u64 timestamp); Result timeGetDeviceLocationName(TimeLocationName *name); Result timeSetDeviceLocationName(const TimeLocationName *name); -Result timeGetTotalLocationNameCount(u32 *total_location_name_count); -Result timeLoadLocationNameList(u32 index, TimeLocationName *location_name_array, size_t location_name_size, u32 *location_name_count); +Result timeGetTotalLocationNameCount(s32 *total_location_name_count); +Result timeLoadLocationNameList(s32 index, TimeLocationName *location_name_array, s32 location_name_max, s32 *location_name_count); Result timeLoadTimeZoneRule(const TimeLocationName *name, TimeZoneRule *rule); -Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_count, u32 *timestamp_count); -Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_count, u32 *timestamp_count); Result timeToCalendarTime(const TimeZoneRule *rule, u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info); Result timeToCalendarTimeWithMyRule(u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info); +Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count); +Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count); diff --git a/nx/source/services/time.c b/nx/source/services/time.c index 5e4b8531..b1acdc31 100644 --- a/nx/source/services/time.c +++ b/nx/source/services/time.c @@ -1,28 +1,19 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "services/time.h" -#include "services/sm.h" static Service g_timeSrv; static Service g_timeUserSystemClock; static Service g_timeNetworkSystemClock; static Service g_timeTimeZoneService; static Service g_timeLocalSystemClock; -static u64 g_refCnt; -static Result _timeGetSession(Service* srv_out, u64 cmd_id); +static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id); -Result timeInitialize(void) -{ - atomicIncrement64(&g_refCnt); +NX_GENERATE_SERVICE_GUARD(time); - if (serviceIsActive(&g_timeSrv)) - return 0; - - Result rc; +Result _timeInitialize(void) { + Result rc=0; rc = smGetService(&g_timeSrv, "time:s"); if (R_FAILED(rc)) @@ -31,75 +22,33 @@ Result timeInitialize(void) if (R_FAILED(rc)) return rc; - rc = _timeGetSession(&g_timeUserSystemClock, 0); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeUserSystemClock, 0); if (R_SUCCEEDED(rc)) - rc = _timeGetSession(&g_timeNetworkSystemClock, 1); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeNetworkSystemClock, 1); if (R_SUCCEEDED(rc)) - rc = _timeGetSession(&g_timeTimeZoneService, 3); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeTimeZoneService, 3); if (R_SUCCEEDED(rc)) - rc = _timeGetSession(&g_timeLocalSystemClock, 4); - - if (R_FAILED(rc)) - timeExit(); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeLocalSystemClock, 4); return rc; } -void timeExit(void) -{ - if (atomicDecrement64(&g_refCnt) == 0) - { - serviceClose(&g_timeLocalSystemClock); - serviceClose(&g_timeTimeZoneService); - serviceClose(&g_timeNetworkSystemClock); - serviceClose(&g_timeUserSystemClock); - serviceClose(&g_timeSrv); - } +void _timeCleanup(void) { + serviceClose(&g_timeLocalSystemClock); + serviceClose(&g_timeTimeZoneService); + serviceClose(&g_timeNetworkSystemClock); + serviceClose(&g_timeUserSystemClock); + serviceClose(&g_timeSrv); } Service* timeGetServiceSession(void) { return &g_timeSrv; } -static Result _timeGetSession(Service* srv_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 = serviceIpcDispatch(&g_timeSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(srv_out, r.Handles[0]); - } - } - - return rc; -} - -static Service* _timeGetClockSession(TimeType type) { +Service* timeGetServiceSession_SystemClock(TimeType type) { if (type==TimeType_UserSystemClock) { return &g_timeUserSystemClock; } @@ -114,409 +63,143 @@ static Service* _timeGetClockSession(TimeType type) { } } +Service* timeGetServiceSession_TimeZoneService(void) { + return &g_timeTimeZoneService; +} + +static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) { + return serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} + +static Result _timeCmdInU64NoOut(Service* srv, u64 inval, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval); +} + +static Result _timeCmdNoInOutU64(Service* srv, u64 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _appletCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + Result timeGetCurrentTime(TimeType type, u64 *timestamp) { - Service *srv = _timeGetClockSession(type); + Service *srv = timeGetServiceSession_SystemClock(type); if (srv==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 timestamp; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && timestamp) *timestamp = resp->timestamp; - } - - return rc; + return _timeCmdNoInOutU64(srv, timestamp, 0); } Result timeSetCurrentTime(TimeType type, u64 timestamp) { - Service *srv = _timeGetClockSession(type); + Service *srv = timeGetServiceSession_SystemClock(type); if (srv==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 timestamp; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->timestamp = timestamp; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _timeCmdInU64NoOut(srv, timestamp, 1); } Result timeGetDeviceLocationName(TimeLocationName *name) { - IpcCommand c; - ipcInitialize(&c); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - TimeLocationName name; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && name) memcpy(name, &resp->name, sizeof(TimeLocationName)); - } - - return rc; + return serviceDispatchOut(&g_timeTimeZoneService, 0, *name); } Result timeSetDeviceLocationName(const TimeLocationName *name) { - IpcCommand c; - ipcInitialize(&c); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - TimeLocationName name; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - memcpy(&raw->name, name, sizeof(TimeLocationName)); - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_timeTimeZoneService, 1, *name); } -Result timeGetTotalLocationNameCount(u32 *total_location_name_count) { - IpcCommand c; - ipcInitialize(&c); +Result timeGetTotalLocationNameCount(s32 *total_location_name_count) { + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 total_location_name_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total_location_name_count) *total_location_name_count = resp->total_location_name_count; - } - - return rc; + return _appletCmdNoInOutU32(&g_timeTimeZoneService, (u32*)total_location_name_count, 2); } -Result timeLoadLocationNameList(u32 index, TimeLocationName *location_name_array, size_t location_name_size, u32 *location_name_count) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, location_name_array, location_name_size, BufferType_Normal); +Result timeLoadLocationNameList(s32 index, TimeLocationName *location_name_array, s32 location_name_max, s32 *location_name_count) { + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - u32 index; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->index = index; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 location_name_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && location_name_count) *location_name_count = resp->location_name_count; - } - - return rc; + return serviceDispatchInOut(&g_timeTimeZoneService, 3, index, *location_name_count, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { location_name_array, sizeof(TimeLocationName)*location_name_max } }, + ); } Result timeLoadTimeZoneRule(const TimeLocationName *name, TimeZoneRule *rule) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, rule, sizeof(TimeZoneRule), BufferType_Normal); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - TimeLocationName name; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - memcpy(&raw->name, name, sizeof(TimeLocationName)); - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_timeTimeZoneService, 4, *name, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { rule, sizeof(TimeZoneRule) } }, + ); } Result timeToCalendarTime(const TimeZoneRule *rule, u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, rule, sizeof(TimeZoneRule), BufferType_Normal); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); struct { - u64 magic; - u64 cmd_id; - u64 timestamp; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 100; - raw->timestamp = timestamp; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - TimeCalendarTime caltime; - TimeCalendarAdditionalInfo info; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && caltime) memcpy(caltime, &resp->caltime, sizeof(TimeCalendarTime)); - if (R_SUCCEEDED(rc) && info) memcpy(info, &resp->info, sizeof(TimeCalendarAdditionalInfo)); - } + TimeCalendarTime caltime; + TimeCalendarAdditionalInfo info; + } out; + Result rc = serviceDispatchInOut(&g_timeTimeZoneService, 100, timestamp, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { rule, sizeof(TimeZoneRule) } }, + ); + if (R_SUCCEEDED(rc) && caltime) *caltime = out.caltime; + if (R_SUCCEEDED(rc) && info) *info = out.info; return rc; } Result timeToCalendarTimeWithMyRule(u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 timestamp; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 101; - raw->timestamp = timestamp; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - TimeCalendarTime caltime; - TimeCalendarAdditionalInfo info; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && caltime) memcpy(caltime, &resp->caltime, sizeof(TimeCalendarTime)); - if (R_SUCCEEDED(rc) && info) memcpy(info, &resp->info, sizeof(TimeCalendarAdditionalInfo)); - } - - return rc; -} - -Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_count, u32 *timestamp_count) { if (!serviceIsActive(&g_timeTimeZoneService)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, rule, sizeof(TimeZoneRule), BufferType_Normal); - ipcAddRecvStatic(&c, timestamp_list, sizeof(u64)*timestamp_list_count, 0); - struct { - u64 magic; - u64 cmd_id; TimeCalendarTime caltime; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 201; - raw->caltime = *caltime; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 timestamp_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && timestamp_count) *timestamp_count = resp->timestamp_count; - } + TimeCalendarAdditionalInfo info; + } out; + Result rc = serviceDispatchInOut(&g_timeTimeZoneService, 101, timestamp, out); + if (R_SUCCEEDED(rc) && caltime) *caltime = out.caltime; + if (R_SUCCEEDED(rc) && info) *info = out.info; return rc; } -Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_count, u32 *timestamp_count) { +Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count) { if (!serviceIsActive(&g_timeTimeZoneService)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvStatic(&c, timestamp_list, sizeof(u64)*timestamp_list_count, 0); - - struct { - u64 magic; - u64 cmd_id; - TimeCalendarTime caltime; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 202; - raw->caltime = *caltime; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 timestamp_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && timestamp_count) *timestamp_count = resp->timestamp_count; - } - - return rc; + return serviceDispatchInOut(&g_timeTimeZoneService, 201, *caltime, *timestamp_count, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + }, + .buffers = { + { rule, sizeof(TimeZoneRule) }, + { timestamp_list, sizeof(u64)*timestamp_list_count }, + }, + ); +} + +Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count) { + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchInOut(&g_timeTimeZoneService, 202, *caltime, *timestamp_count, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { timestamp_list, sizeof(u64)*timestamp_list_count } }, + ); }