time.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <chrono>
  5. #include <ctime>
  6. #include "common/logging/log.h"
  7. #include "core/core_timing.h"
  8. #include "core/hle/ipc_helpers.h"
  9. #include "core/hle/kernel/client_port.h"
  10. #include "core/hle/kernel/client_session.h"
  11. #include "core/hle/service/time/interface.h"
  12. #include "core/hle/service/time/time.h"
  13. namespace Service::Time {
  14. class ISystemClock final : public ServiceFramework<ISystemClock> {
  15. public:
  16. ISystemClock() : ServiceFramework("ISystemClock") {
  17. static const FunctionInfo functions[] = {
  18. {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
  19. {1, nullptr, "SetCurrentTime"},
  20. {2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
  21. {3, nullptr, "SetSystemClockContext"},
  22. };
  23. RegisterHandlers(functions);
  24. }
  25. private:
  26. void GetCurrentTime(Kernel::HLERequestContext& ctx) {
  27. const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>(
  28. std::chrono::system_clock::now().time_since_epoch())
  29. .count()};
  30. LOG_DEBUG(Service_Time, "called");
  31. IPC::ResponseBuilder rb{ctx, 4};
  32. rb.Push(RESULT_SUCCESS);
  33. rb.Push<u64>(time_since_epoch);
  34. }
  35. void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
  36. LOG_WARNING(Service_Time, "(STUBBED) called");
  37. SystemClockContext system_clock_ontext{};
  38. IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
  39. rb.Push(RESULT_SUCCESS);
  40. rb.PushRaw(system_clock_ontext);
  41. }
  42. };
  43. class ISteadyClock final : public ServiceFramework<ISteadyClock> {
  44. public:
  45. ISteadyClock() : ServiceFramework("ISteadyClock") {
  46. static const FunctionInfo functions[] = {
  47. {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
  48. };
  49. RegisterHandlers(functions);
  50. }
  51. private:
  52. void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
  53. LOG_DEBUG(Service_Time, "called");
  54. SteadyClockTimePoint steady_clock_time_point{
  55. CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / 1000};
  56. IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
  57. rb.Push(RESULT_SUCCESS);
  58. rb.PushRaw(steady_clock_time_point);
  59. }
  60. };
  61. class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
  62. public:
  63. ITimeZoneService() : ServiceFramework("ITimeZoneService") {
  64. static const FunctionInfo functions[] = {
  65. {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
  66. {1, nullptr, "SetDeviceLocationName"},
  67. {2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
  68. {3, nullptr, "LoadLocationNameList"},
  69. {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
  70. {5, nullptr, "GetTimeZoneRuleVersion"},
  71. {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
  72. {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
  73. {200, nullptr, "ToPosixTime"},
  74. {201, nullptr, "ToPosixTimeWithMyRule"},
  75. };
  76. RegisterHandlers(functions);
  77. }
  78. private:
  79. LocationName location_name{"UTC"};
  80. TimeZoneRule my_time_zone_rule{};
  81. void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
  82. LOG_DEBUG(Service_Time, "called");
  83. IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2};
  84. rb.Push(RESULT_SUCCESS);
  85. rb.PushRaw(location_name);
  86. }
  87. void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) {
  88. LOG_WARNING(Service_Time, "(STUBBED) called");
  89. IPC::ResponseBuilder rb{ctx, 3};
  90. rb.Push(RESULT_SUCCESS);
  91. rb.Push<u32>(0);
  92. }
  93. void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
  94. LOG_WARNING(Service_Time, "(STUBBED) called");
  95. ctx.WriteBuffer(&my_time_zone_rule, sizeof(TimeZoneRule));
  96. IPC::ResponseBuilder rb{ctx, 2};
  97. rb.Push(RESULT_SUCCESS);
  98. }
  99. void ToCalendarTime(Kernel::HLERequestContext& ctx) {
  100. IPC::RequestParser rp{ctx};
  101. const u64 posix_time = rp.Pop<u64>();
  102. LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
  103. TimeZoneRule time_zone_rule{};
  104. auto buffer = ctx.ReadBuffer();
  105. std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
  106. CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
  107. CalendarAdditionalInfo additional_info{};
  108. PosixToCalendar(posix_time, calendar_time, additional_info, time_zone_rule);
  109. IPC::ResponseBuilder rb{ctx, 10};
  110. rb.Push(RESULT_SUCCESS);
  111. rb.PushRaw(calendar_time);
  112. rb.PushRaw(additional_info);
  113. }
  114. void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
  115. IPC::RequestParser rp{ctx};
  116. const u64 posix_time = rp.Pop<u64>();
  117. LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
  118. CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
  119. CalendarAdditionalInfo additional_info{};
  120. PosixToCalendar(posix_time, calendar_time, additional_info, my_time_zone_rule);
  121. IPC::ResponseBuilder rb{ctx, 10};
  122. rb.Push(RESULT_SUCCESS);
  123. rb.PushRaw(calendar_time);
  124. rb.PushRaw(additional_info);
  125. }
  126. void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time,
  127. CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) {
  128. std::time_t t(posix_time);
  129. std::tm* tm = std::localtime(&t);
  130. if (!tm) {
  131. return;
  132. }
  133. calendar_time.year = tm->tm_year + 1900;
  134. calendar_time.month = tm->tm_mon + 1;
  135. calendar_time.day = tm->tm_mday;
  136. calendar_time.hour = tm->tm_hour;
  137. calendar_time.minute = tm->tm_min;
  138. calendar_time.second = tm->tm_sec;
  139. additional_info.day_of_week = tm->tm_wday;
  140. additional_info.day_of_year = tm->tm_yday;
  141. std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC"));
  142. additional_info.utc_offset = 0;
  143. }
  144. };
  145. void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) {
  146. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  147. rb.Push(RESULT_SUCCESS);
  148. rb.PushIpcInterface<ISystemClock>();
  149. LOG_DEBUG(Service_Time, "called");
  150. }
  151. void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
  152. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  153. rb.Push(RESULT_SUCCESS);
  154. rb.PushIpcInterface<ISystemClock>();
  155. LOG_DEBUG(Service_Time, "called");
  156. }
  157. void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
  158. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  159. rb.Push(RESULT_SUCCESS);
  160. rb.PushIpcInterface<ISteadyClock>();
  161. LOG_DEBUG(Service_Time, "called");
  162. }
  163. void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
  164. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  165. rb.Push(RESULT_SUCCESS);
  166. rb.PushIpcInterface<ITimeZoneService>();
  167. LOG_DEBUG(Service_Time, "called");
  168. }
  169. void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
  170. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  171. rb.Push(RESULT_SUCCESS);
  172. rb.PushIpcInterface<ISystemClock>();
  173. LOG_DEBUG(Service_Time, "called");
  174. }
  175. Module::Interface::Interface(std::shared_ptr<Module> time, const char* name)
  176. : ServiceFramework(name), time(std::move(time)) {}
  177. void InstallInterfaces(SM::ServiceManager& service_manager) {
  178. auto time = std::make_shared<Module>();
  179. std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager);
  180. std::make_shared<Time>(time, "time:s")->InstallAsService(service_manager);
  181. std::make_shared<Time>(time, "time:u")->InstallAsService(service_manager);
  182. }
  183. } // namespace Service::Time