Service/time: implement posix time to calendar conversion
This commit is contained in:
		| @@ -3,6 +3,7 @@ | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <chrono> | ||||
| #include <ctime> | ||||
| #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<u64>(); | ||||
|  | ||||
|         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<u64>(); | ||||
|         const u64 posix_time = rp.Pop<u64>(); | ||||
|  | ||||
|         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) { | ||||
|   | ||||
| @@ -4,13 +4,13 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <array> | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Service::Time { | ||||
|  | ||||
| // TODO(Rozelette) RE this structure | ||||
| struct LocationName { | ||||
|     INSERT_PADDING_BYTES(0x24); | ||||
|     std::array<u8, 0x24> 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<u8, 8> 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<Interface> { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 mailwl
					mailwl