From 0dcaeec9592434780b0975a76f92ef6f58b5116c Mon Sep 17 00:00:00 2001 From: yellows8 Date: Tue, 20 Feb 2018 22:24:35 -0500 Subject: [PATCH 1/2] In __libnx_gtod() set tv_usec, and moved+updated the timezones comment. --- nx/source/runtime/newlib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nx/source/runtime/newlib.c b/nx/source/runtime/newlib.c index 561ef34e0..43463d4bf 100644 --- a/nx/source/runtime/newlib.c +++ b/nx/source/runtime/newlib.c @@ -28,6 +28,8 @@ static struct _reent* __libnx_get_reent(void) { return tv->reent; } +//TODO: timeGetCurrentTime() returns UTC time. How to handle timezones? + int __libnx_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz) { if (tp != NULL) { u64 now=0; @@ -40,10 +42,10 @@ int __libnx_gtod(struct _reent *ptr, struct timeval *tp, struct timezone *tz) { } tp->tv_sec = now; - tp->tv_usec = 0;//timeGetCurrentTime() only returns seconds. + tp->tv_usec = now*1000000;//timeGetCurrentTime() only returns seconds. } - if (tz != NULL) {//TODO: This needs handled properly, timeGetCurrentTime() returns UTC time. + if (tz != NULL) { tz->tz_minuteswest = 0; tz->tz_dsttime = 0; } From d61154f0e5be9e34faf7889e4f782e954d73fa1b Mon Sep 17 00:00:00 2001 From: yellows8 Date: Wed, 21 Feb 2018 00:26:21 -0500 Subject: [PATCH 2/2] Added timeSetCurrentTime() and attempt to initialize time-serv with 'time:s' first. --- nx/include/switch/services/time.h | 9 +++++ nx/source/services/time.c | 62 +++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/nx/include/switch/services/time.h b/nx/include/switch/services/time.h index eb3ed396a..0ef21a09a 100644 --- a/nx/include/switch/services/time.h +++ b/nx/include/switch/services/time.h @@ -9,6 +9,7 @@ #include "../types.h" #include "../services/sm.h" +/// Time clock type. typedef enum { TimeType_UserSystemClock, TimeType_NetworkSystemClock, @@ -22,3 +23,11 @@ void timeExit(void); Service* timeGetSessionService(void); Result timeGetCurrentTime(TimeType type, u64 *timestamp); + +/** + * @brief Sets the time for the specified clock. + * @param[in] type Clock to use. + * @param[in] timestamp POSIX UTC timestamp. + * @return Result code. + */ +Result timeSetCurrentTime(TimeType type, u64 timestamp); diff --git a/nx/source/services/time.c b/nx/source/services/time.c index 30e502e18..67cc89c02 100644 --- a/nx/source/services/time.c +++ b/nx/source/services/time.c @@ -20,7 +20,10 @@ Result timeInitialize(void) Result rc; - rc = smGetService(&g_timeSrv, "time:u"); + rc = smGetService(&g_timeSrv, "time:s"); + if (R_FAILED(rc)) + rc = smGetService(&g_timeSrv, "time:u"); + if (R_FAILED(rc)) return rc; @@ -92,21 +95,26 @@ static Result _timeGetSession(Service* srv_out, u64 cmd_id) { return rc; } -Result timeGetCurrentTime(TimeType type, u64 *timestamp) { - Service *srv = NULL; - +static Service* _timeGetClockSession(TimeType type) { if (type==TimeType_UserSystemClock) { - srv = &g_timeUserSystemClock; + return &g_timeUserSystemClock; } else if (type==TimeType_NetworkSystemClock) { - srv = &g_timeNetworkSystemClock; + return &g_timeNetworkSystemClock; } else if (type==TimeType_LocalSystemClock) { - srv = &g_timeLocalSystemClock; + return &g_timeLocalSystemClock; } else { - return MAKERESULT(Module_Libnx, LibnxError_BadInput); + return NULL; } +} + +Result timeGetCurrentTime(TimeType type, u64 *timestamp) { + Service *srv = _timeGetClockSession(type); + + if (srv==NULL) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); IpcCommand c; ipcInitialize(&c); @@ -141,3 +149,41 @@ Result timeGetCurrentTime(TimeType type, u64 *timestamp) { return rc; } +Result timeSetCurrentTime(TimeType type, u64 timestamp) { + Service *srv = _timeGetClockSession(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; +} +