diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/time/time_zone_service.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp new file mode 100644 index 000000000..1566e778e --- /dev/null +++ b/src/core/hle/service/time/time_zone_service.cpp @@ -0,0 +1,148 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/time/time_zone_content_manager.h" +#include "core/hle/service/time/time_zone_service.h" +#include "core/hle/service/time/time_zone_types.h" + +namespace Service::Time { + +ITimeZoneService ::ITimeZoneService(TimeZone::TimeZoneContentManager& time_zone_content_manager) + : ServiceFramework("ITimeZoneService"), time_zone_content_manager{time_zone_content_manager} { + static const FunctionInfo functions[] = { + {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"}, + {1, nullptr, "SetDeviceLocationName"}, + {2, nullptr, "GetTotalLocationNameCount"}, + {3, nullptr, "LoadLocationNameList"}, + {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, + {5, nullptr, "GetTimeZoneRuleVersion"}, + {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, + {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, + {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"}, + {202, nullptr, "ToPosixTimeWithMyRule"}, + }; + RegisterHandlers(functions); +} + +void ITimeZoneService::GetDeviceLocationName(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Time, "called"); + + TimeZone::LocationName location_name{}; + if (const ResultCode result{ + time_zone_content_manager.GetTimeZoneManager().GetDeviceLocationName(location_name)}; + result != RESULT_SUCCESS) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + IPC::ResponseBuilder rb{ctx, (sizeof(location_name) / 4) + 2}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(location_name); +} + +void ITimeZoneService::LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()}; + + std::string location_name; + for (const auto& byte : raw_location_name) { + // Strip extra bytes + if (byte == '\0') { + break; + } + location_name.push_back(byte); + } + + LOG_DEBUG(Service_Time, "called, location_name={}", location_name); + + TimeZone::TimeZoneRule time_zone_rule{}; + if (const ResultCode result{ + time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)}; + result != RESULT_SUCCESS) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + std::vector<u8> time_zone_rule_outbuffer(sizeof(TimeZone::TimeZoneRule)); + std::memcpy(time_zone_rule_outbuffer.data(), &time_zone_rule, sizeof(TimeZone::TimeZoneRule)); + ctx.WriteBuffer(time_zone_rule_outbuffer); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void ITimeZoneService::ToCalendarTime(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto posix_time{rp.Pop<s64>()}; + + LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time); + + TimeZone::TimeZoneRule time_zone_rule{}; + const auto buffer{ctx.ReadBuffer()}; + std::memcpy(&time_zone_rule, buffer.data(), buffer.size()); + + TimeZone::CalendarInfo calendar_info{}; + if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToCalendarTime( + time_zone_rule, posix_time, calendar_info)}; + result != RESULT_SUCCESS) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(calendar_info); +} + +void ITimeZoneService::ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto posix_time{rp.Pop<s64>()}; + + LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time); + + TimeZone::CalendarInfo calendar_info{}; + if (const ResultCode result{ + time_zone_content_manager.GetTimeZoneManager().ToCalendarTimeWithMyRules( + posix_time, calendar_info)}; + result != RESULT_SUCCESS) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(calendar_info); +} + +void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Time, "called"); + + IPC::RequestParser rp{ctx}; + const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()}; + TimeZone::TimeZoneRule time_zone_rule{}; + std::memcpy(&time_zone_rule, ctx.ReadBuffer().data(), sizeof(TimeZone::TimeZoneRule)); + + s64 posix_time{}; + if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToPosixTime( + time_zone_rule, calendar_time, posix_time)}; + result != RESULT_SUCCESS) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + + // TODO(bunnei): Handle multiple times + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u32>(1); // Number of times we're returning + ctx.WriteBuffer(&posix_time, sizeof(s64)); +} + +} // namespace Service::Time |