summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/time/time.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/time/time.cpp')
-rw-r--r--src/core/hle/service/time/time.cpp172
1 files changed, 146 insertions, 26 deletions
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 28fd8debc..16564de24 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -15,6 +15,44 @@
namespace Service::Time {
+static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time,
+ CalendarAdditionalInfo& additional_info,
+ [[maybe_unused]] const TimeZoneRule& /*rule*/) {
+ const std::time_t time(posix_time);
+ const std::tm* tm = std::localtime(&time);
+ if (tm == nullptr) {
+ calendar_time = {};
+ additional_info = {};
+ 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;
+}
+
+static u64 CalendarToPosix(const CalendarTime& calendar_time,
+ [[maybe_unused]] const TimeZoneRule& /*rule*/) {
+ std::tm time{};
+ time.tm_year = calendar_time.year - 1900;
+ time.tm_mon = calendar_time.month - 1;
+ time.tm_mday = calendar_time.day;
+
+ time.tm_hour = calendar_time.hour;
+ time.tm_min = calendar_time.minute;
+ time.tm_sec = calendar_time.second;
+
+ std::time_t epoch_time = std::mktime(&time);
+ return static_cast<u64>(epoch_time);
+}
+
class ISystemClock final : public ServiceFramework<ISystemClock> {
public:
ISystemClock() : ServiceFramework("ISystemClock") {
@@ -34,6 +72,7 @@ private:
std::chrono::system_clock::now().time_since_epoch())
.count()};
LOG_DEBUG(Service_Time, "called");
+
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(time_since_epoch);
@@ -41,6 +80,7 @@ private:
void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called");
+
SystemClockContext system_clock_ontext{};
IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
rb.Push(RESULT_SUCCESS);
@@ -60,6 +100,7 @@ public:
private:
void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
+
SteadyClockTimePoint steady_clock_time_point{
CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / 1000};
IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
@@ -80,8 +121,8 @@ public:
{5, nullptr, "GetTimeZoneRuleVersion"},
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
- {201, nullptr, "ToPosixTime"},
- {202, nullptr, "ToPosixTimeWithMyRule"},
+ {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
+ {202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
};
RegisterHandlers(functions);
}
@@ -92,6 +133,7 @@ private:
void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
+
IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(location_name);
@@ -99,6 +141,7 @@ private:
void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_Time, "(STUBBED) called");
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
@@ -116,7 +159,6 @@ private:
void ToCalendarTime(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 posix_time = rp.Pop<u64>();
-
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
TimeZoneRule time_zone_rule{};
@@ -137,7 +179,6 @@ private:
void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 posix_time = rp.Pop<u64>();
-
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
@@ -151,60 +192,139 @@ private:
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 ToPosixTime(Kernel::HLERequestContext& ctx) {
+ // TODO(ogniK): Figure out how to handle multiple times
+ LOG_WARNING(Service_Time, "(STUBBED) called");
+
+ IPC::RequestParser rp{ctx};
+ auto calendar_time = rp.PopRaw<CalendarTime>();
+ auto posix_time = CalendarToPosix(calendar_time, {});
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushRaw<u32>(1); // Amount of times we're returning
+ ctx.WriteBuffer(&posix_time, sizeof(u64));
+ }
+
+ void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_Time, "(STUBBED) called");
+
+ IPC::RequestParser rp{ctx};
+ auto calendar_time = rp.PopRaw<CalendarTime>();
+ auto posix_time = CalendarToPosix(calendar_time, {});
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushRaw<u32>(1); // Amount of times we're returning
+ ctx.WriteBuffer(&posix_time, sizeof(u64));
}
};
void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>();
- LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>();
- LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISteadyClock>();
- LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ITimeZoneService>();
- LOG_DEBUG(Service_Time, "called");
}
void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>();
+}
+
+void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
+
+ IPC::RequestParser rp{ctx};
+ const auto initial_type = rp.PopRaw<u8>();
+
+ const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count()};
+
+ const std::time_t time(time_since_epoch);
+ const std::tm* tm = std::localtime(&time);
+ if (tm == nullptr) {
+ LOG_ERROR(Service_Time, "tm is a nullptr");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultCode(-1)); // TODO(ogniK): Find appropriate error code
+ return;
+ }
+
+ const SteadyClockTimePoint steady_clock_time_point{
+ CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / 1000, {}};
+
+ CalendarTime calendar_time{};
+ 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;
+
+ ClockSnapshot clock_snapshot{};
+ clock_snapshot.system_posix_time = time_since_epoch;
+ clock_snapshot.network_posix_time = time_since_epoch;
+ clock_snapshot.system_calendar_time = calendar_time;
+ clock_snapshot.network_calendar_time = calendar_time;
+
+ CalendarAdditionalInfo additional_info{};
+ PosixToCalendar(time_since_epoch, calendar_time, additional_info, {});
+
+ clock_snapshot.system_calendar_info = additional_info;
+ clock_snapshot.network_calendar_info = additional_info;
+
+ clock_snapshot.steady_clock_timepoint = steady_clock_time_point;
+ clock_snapshot.location_name = LocationName{"UTC"};
+ clock_snapshot.clock_auto_adjustment_enabled = 1;
+ clock_snapshot.type = initial_type;
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot));
+}
+
+void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
+ Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
+ IPC::RequestParser rp{ctx};
+ const auto snapshot_a = rp.PopRaw<ClockSnapshot>();
+ const auto snapshot_b = rp.PopRaw<ClockSnapshot>();
+ const u64 difference =
+ snapshot_b.user_clock_context.offset - snapshot_a.user_clock_context.offset;
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushRaw<u64>(difference);
}
Module::Interface::Interface(std::shared_ptr<Module> time, const char* name)