From 11568c2ea36b712498fd0cedd03748331946030a Mon Sep 17 00:00:00 2001 From: mailwl Date: Thu, 31 May 2018 15:33:30 +0300 Subject: [PATCH] Service/time: implement posix time to calendar conversion --- src/core/hle/service/time/time.cpp | 58 +++++++++++++++++++++++++++--- src/core/hle/service/time/time.h | 28 +++++++++------ 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 2eb37fb42..654012189 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "common/logging/log.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" @@ -77,7 +78,7 @@ public: {3, nullptr, "LoadLocationNameList"}, {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, {5, nullptr, "GetTimeZoneRuleVersion"}, - {100, nullptr, "ToCalendarTime"}, + {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, {200, nullptr, "ToPosixTime"}, {201, nullptr, "ToPosixTimeWithMyRule"}, @@ -86,9 +87,11 @@ public: } private: + LocationName location_name{"UTC"}; + TimeZoneRule my_time_zone_rule{}; + void GetDeviceLocationName(Kernel::HLERequestContext& ctx) { - NGLOG_WARNING(Service_Time, "(STUBBED) called"); - LocationName location_name{}; + NGLOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2}; rb.Push(RESULT_SUCCESS); rb.PushRaw(location_name); @@ -103,23 +106,70 @@ private: void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { NGLOG_WARNING(Service_Time, "(STUBBED) called"); + + ctx.WriteBuffer(&my_time_zone_rule, sizeof(TimeZoneRule)); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + void ToCalendarTime(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 posix_time = rp.Pop(); + + NGLOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time); + + TimeZoneRule time_zone_rule{}; + auto buffer = ctx.ReadBuffer(); + std::memcpy(&time_zone_rule, buffer.data(), buffer.size()); + + CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; + CalendarAdditionalInfo additional_info{}; + + PosixToCalendar(posix_time, calendar_time, additional_info, time_zone_rule); + + IPC::ResponseBuilder rb{ctx, 10}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(calendar_time); + rb.PushRaw(additional_info); + } + void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - u64 posix_time = rp.Pop(); + const u64 posix_time = rp.Pop(); NGLOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time); CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; CalendarAdditionalInfo additional_info{}; + + PosixToCalendar(posix_time, calendar_time, additional_info, my_time_zone_rule); + IPC::ResponseBuilder rb{ctx, 10}; rb.Push(RESULT_SUCCESS); rb.PushRaw(calendar_time); rb.PushRaw(additional_info); } + + void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, + CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { + std::time_t t(posix_time); + std::tm* tm = std::localtime(&t); + if (!tm) { + return; + } + calendar_time.year = tm->tm_year + 1900; + calendar_time.month = tm->tm_mon + 1; + calendar_time.day = tm->tm_mday; + calendar_time.hour = tm->tm_hour; + calendar_time.minute = tm->tm_min; + calendar_time.second = tm->tm_sec; + + additional_info.day_of_week = tm->tm_wday; + additional_info.day_of_year = tm->tm_yday; + std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC")); + additional_info.utc_offset = 0; + } }; void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 12fe1995a..49af38589 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -4,13 +4,13 @@ #pragma once +#include #include "core/hle/service/service.h" namespace Service::Time { -// TODO(Rozelette) RE this structure struct LocationName { - INSERT_PADDING_BYTES(0x24); + std::array name; }; static_assert(sizeof(LocationName) == 0x24, "LocationName is incorrect size"); @@ -25,26 +25,34 @@ struct CalendarTime { }; static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size"); -// TODO(Rozelette) RE this structure struct CalendarAdditionalInfo { - INSERT_PADDING_BYTES(0x18); + u32_le day_of_week; + u32_le day_of_year; + std::array name; + INSERT_PADDING_BYTES(1); + s32_le utc_offset; }; static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo structure has incorrect size"); -// TODO(bunnei) RE this structure -struct SystemClockContext { - INSERT_PADDING_BYTES(0x20); +// TODO(mailwl) RE this structure +struct TimeZoneRule { + INSERT_PADDING_BYTES(0x4000); }; -static_assert(sizeof(SystemClockContext) == 0x20, - "SystemClockContext structure has incorrect size"); struct SteadyClockTimePoint { - u64 value; + u64_le value; INSERT_PADDING_WORDS(4); }; static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size"); +struct SystemClockContext { + u64_le offset; + SteadyClockTimePoint time_point; +}; +static_assert(sizeof(SystemClockContext) == 0x20, + "SystemClockContext structure has incorrect size"); + class Module final { public: class Interface : public ServiceFramework {