summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Kelebek12024-01-26 15:29:04 +0000
committerGravatar Kelebek12024-01-27 03:30:09 +0000
commitda410506a401abc853ee23e56ca1e25eb47cd6e6 (patch)
tree6a42e537b6bfbdb460e7f542e4731fc5cad40dd8
parentMerge pull request #12808 from t895/uri-moment (diff)
downloadyuzu-da410506a401abc853ee23e56ca1e25eb47cd6e6.tar.gz
yuzu-da410506a401abc853ee23e56ca1e25eb47cd6e6.tar.xz
yuzu-da410506a401abc853ee23e56ca1e25eb47cd6e6.zip
Move time services to new IPC.
Add some fixes/improvements to usage with the new IPC
-rw-r--r--externals/tz/tz/tz.cpp4
-rw-r--r--externals/tz/tz/tz.h4
-rw-r--r--src/audio_core/CMakeLists.txt4
-rw-r--r--src/common/CMakeLists.txt4
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/core.cpp14
-rw-r--r--src/core/hle/service/caps/caps_manager.cpp12
-rw-r--r--src/core/hle/service/cmif_serialization.h123
-rw-r--r--src/core/hle/service/cmif_types.h197
-rw-r--r--src/core/hle/service/glue/time/alarm_worker.cpp3
-rw-r--r--src/core/hle/service/glue/time/alarm_worker.h4
-rw-r--r--src/core/hle/service/glue/time/file_timestamp_worker.cpp4
-rw-r--r--src/core/hle/service/glue/time/manager.cpp40
-rw-r--r--src/core/hle/service/glue/time/static.cpp394
-rw-r--r--src/core/hle/service/glue/time/static.h76
-rw-r--r--src/core/hle/service/glue/time/time_zone.cpp347
-rw-r--r--src/core/hle/service/glue/time/time_zone.h67
-rw-r--r--src/core/hle/service/glue/time/time_zone_binary.cpp11
-rw-r--r--src/core/hle/service/glue/time/time_zone_binary.h2
-rw-r--r--src/core/hle/service/glue/time/worker.cpp42
-rw-r--r--src/core/hle/service/glue/time/worker.h8
-rw-r--r--src/core/hle/service/nfc/common/device.cpp8
-rw-r--r--src/core/hle/service/nfc/common/device_manager.cpp8
-rw-r--r--src/core/hle/service/psc/time/common.h135
-rw-r--r--src/core/hle/service/psc/time/power_state_service.cpp28
-rw-r--r--src/core/hle/service/psc/time/power_state_service.h7
-rw-r--r--src/core/hle/service/psc/time/service_manager.cpp438
-rw-r--r--src/core/hle/service/psc/time/service_manager.h60
-rw-r--r--src/core/hle/service/psc/time/static.cpp493
-rw-r--r--src/core/hle/service/psc/time/static.h65
-rw-r--r--src/core/hle/service/psc/time/steady_clock.cpp133
-rw-r--r--src/core/hle/service/psc/time/steady_clock.h21
-rw-r--r--src/core/hle/service/psc/time/system_clock.cpp92
-rw-r--r--src/core/hle/service/psc/time/system_clock.h13
-rw-r--r--src/core/hle/service/psc/time/time_zone.cpp18
-rw-r--r--src/core/hle/service/psc/time/time_zone.h15
-rw-r--r--src/core/hle/service/psc/time/time_zone_service.cpp322
-rw-r--r--src/core/hle/service/psc/time/time_zone_service.h57
-rw-r--r--src/dedicated_room/CMakeLists.txt4
-rw-r--r--src/video_core/CMakeLists.txt4
-rw-r--r--src/yuzu/CMakeLists.txt4
-rw-r--r--src/yuzu_cmd/CMakeLists.txt4
42 files changed, 1229 insertions, 2064 deletions
diff --git a/externals/tz/tz/tz.cpp b/externals/tz/tz/tz.cpp
index 0c8b68217..04fa6cc8a 100644
--- a/externals/tz/tz/tz.cpp
+++ b/externals/tz/tz/tz.cpp
@@ -1625,11 +1625,11 @@ s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary) {
1625 return 0; 1625 return 0;
1626} 1626}
1627 1627
1628bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep) { 1628bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep) {
1629 return localsub(sp, timep, 0, tmp) == nullptr; 1629 return localsub(sp, timep, 0, tmp) == nullptr;
1630} 1630}
1631 1631
1632u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp) { 1632u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp) {
1633 return time1(out_time, tmp, localsub, sp, 0); 1633 return time1(out_time, tmp, localsub, sp, 0);
1634} 1634}
1635 1635
diff --git a/externals/tz/tz/tz.h b/externals/tz/tz/tz.h
index 38605cfb1..dae4459bc 100644
--- a/externals/tz/tz/tz.h
+++ b/externals/tz/tz/tz.h
@@ -75,7 +75,7 @@ static_assert(sizeof(CalendarTimeInternal) == 0x3C, "CalendarTimeInternal has th
75 75
76s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary); 76s32 ParseTimeZoneBinary(Rule& out_rule, std::span<const u8> binary);
77 77
78bool localtime_rz(CalendarTimeInternal* tmp, Rule* sp, time_t* timep); 78bool localtime_rz(CalendarTimeInternal* tmp, Rule const* sp, time_t* timep);
79u32 mktime_tzname(time_t* out_time, Rule* sp, CalendarTimeInternal* tmp); 79u32 mktime_tzname(time_t* out_time, Rule const* sp, CalendarTimeInternal* tmp);
80 80
81} // namespace Tz 81} // namespace Tz
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index e982d03be..4e4ed1789 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -210,8 +210,6 @@ add_library(audio_core STATIC
210 sink/sink_stream.h 210 sink/sink_stream.h
211) 211)
212 212
213create_target_directory_groups(audio_core)
214
215if (MSVC) 213if (MSVC)
216 target_compile_options(audio_core PRIVATE 214 target_compile_options(audio_core PRIVATE
217 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data 215 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
@@ -267,3 +265,5 @@ endif()
267if (YUZU_USE_PRECOMPILED_HEADERS) 265if (YUZU_USE_PRECOMPILED_HEADERS)
268 target_precompile_headers(audio_core PRIVATE precompiled_headers.h) 266 target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
269endif() 267endif()
268
269create_target_directory_groups(audio_core)
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 8c57d47c6..e30fea268 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -244,8 +244,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
244 ) 244 )
245endif() 245endif()
246 246
247create_target_directory_groups(common)
248
249target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads) 247target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
250target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) 248target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
251 249
@@ -257,3 +255,5 @@ endif()
257if (YUZU_USE_PRECOMPILED_HEADERS) 255if (YUZU_USE_PRECOMPILED_HEADERS)
258 target_precompile_headers(common PRIVATE precompiled_headers.h) 256 target_precompile_headers(common PRIVATE precompiled_headers.h)
259endif() 257endif()
258
259create_target_directory_groups(common)
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 347bbf2d0..ea6b2c285 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -915,8 +915,6 @@ else()
915 ) 915 )
916endif() 916endif()
917 917
918create_target_directory_groups(core)
919
920target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz) 918target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz)
921target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) 919target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API)
922if (MINGW) 920if (MINGW)
@@ -994,3 +992,5 @@ endif()
994if (YUZU_ENABLE_LTO) 992if (YUZU_ENABLE_LTO)
995 set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) 993 set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
996endif() 994endif()
995
996create_target_directory_groups(core)
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 1b412ac98..11bf8d2f6 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -200,22 +200,22 @@ struct System::Impl {
200 system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true); 200 system.ServiceManager().GetService<Service::PSC::Time::StaticService>("time:s", true);
201 201
202 std::shared_ptr<Service::PSC::Time::SystemClock> user_clock; 202 std::shared_ptr<Service::PSC::Time::SystemClock> user_clock;
203 static_service_a->GetStandardUserSystemClock(user_clock); 203 static_service_a->GetStandardUserSystemClock(&user_clock);
204 204
205 std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; 205 std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
206 static_service_a->GetStandardLocalSystemClock(local_clock); 206 static_service_a->GetStandardLocalSystemClock(&local_clock);
207 207
208 std::shared_ptr<Service::PSC::Time::SystemClock> network_clock; 208 std::shared_ptr<Service::PSC::Time::SystemClock> network_clock;
209 static_service_s->GetStandardNetworkSystemClock(network_clock); 209 static_service_s->GetStandardNetworkSystemClock(&network_clock);
210 210
211 std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service; 211 std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service;
212 static_service_a->GetTimeZoneService(timezone_service); 212 static_service_a->GetTimeZoneService(&timezone_service);
213 213
214 Service::PSC::Time::LocationName name{}; 214 Service::PSC::Time::LocationName name{};
215 auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); 215 auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
216 std::memcpy(name.name.data(), new_name.data(), std::min(name.name.size(), new_name.size())); 216 std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size()));
217 217
218 timezone_service->SetDeviceLocation(name); 218 timezone_service->SetDeviceLocationName(name);
219 219
220 u64 time_offset = 0; 220 u64 time_offset = 0;
221 if (Settings::values.custom_rtc_enabled) { 221 if (Settings::values.custom_rtc_enabled) {
@@ -233,7 +233,7 @@ struct System::Impl {
233 233
234 local_clock->SetCurrentTime(new_time); 234 local_clock->SetCurrentTime(new_time);
235 235
236 network_clock->GetSystemClockContext(context); 236 network_clock->GetSystemClockContext(&context);
237 settings_service->SetNetworkSystemClockContext(context); 237 settings_service->SetNetworkSystemClockContext(context);
238 network_clock->SetCurrentTime(new_time); 238 network_clock->SetCurrentTime(new_time);
239 } 239 }
diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp
index e3b8ecf3e..3a22b135f 100644
--- a/src/core/hle/service/caps/caps_manager.cpp
+++ b/src/core/hle/service/caps/caps_manager.cpp
@@ -246,10 +246,10 @@ Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
246 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); 246 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
247 247
248 std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; 248 std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
249 static_service->GetStandardUserSystemClock(user_clock); 249 static_service->GetStandardUserSystemClock(&user_clock);
250 250
251 s64 posix_time{}; 251 s64 posix_time{};
252 auto result = user_clock->GetCurrentTime(posix_time); 252 auto result = user_clock->GetCurrentTime(&posix_time);
253 253
254 if (result.IsError()) { 254 if (result.IsError()) {
255 return result; 255 return result;
@@ -268,10 +268,10 @@ Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
268 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); 268 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
269 269
270 std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{}; 270 std::shared_ptr<Service::PSC::Time::SystemClock> user_clock{};
271 static_service->GetStandardUserSystemClock(user_clock); 271 static_service->GetStandardUserSystemClock(&user_clock);
272 272
273 s64 posix_time{}; 273 s64 posix_time{};
274 auto result = user_clock->GetCurrentTime(posix_time); 274 auto result = user_clock->GetCurrentTime(&posix_time);
275 275
276 if (result.IsError()) { 276 if (result.IsError()) {
277 return result; 277 return result;
@@ -470,11 +470,11 @@ AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {
470 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); 470 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
471 471
472 std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; 472 std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{};
473 static_service->GetTimeZoneService(timezone_service); 473 static_service->GetTimeZoneService(&timezone_service);
474 474
475 Service::PSC::Time::CalendarTime calendar_time{}; 475 Service::PSC::Time::CalendarTime calendar_time{};
476 Service::PSC::Time::CalendarAdditionalInfo additional_info{}; 476 Service::PSC::Time::CalendarAdditionalInfo additional_info{};
477 timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time); 477 timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time);
478 478
479 return { 479 return {
480 .year = calendar_time.year, 480 .year = calendar_time.year,
diff --git a/src/core/hle/service/cmif_serialization.h b/src/core/hle/service/cmif_serialization.h
index 9eb10e816..9ee26400d 100644
--- a/src/core/hle/service/cmif_serialization.h
+++ b/src/core/hle/service/cmif_serialization.h
@@ -12,6 +12,109 @@
12namespace Service { 12namespace Service {
13 13
14// clang-format off 14// clang-format off
15template <typename T>
16struct UnwrapArg {
17 using Type = std::remove_cvref_t<T>;
18};
19
20template <typename T, int A>
21struct UnwrapArg<InLargeData<T, A>> {
22 using Type = std::remove_cv_t<typename InLargeData<T, A>::Type>;
23};
24
25template <typename T>
26struct UnwrapArg<Out<T>> {
27 using Type = AutoOut<typename Out<T>::Type>;
28};
29
30template <typename T>
31struct UnwrapArg<OutCopyHandle<T>> {
32 using Type = AutoOut<typename OutCopyHandle<T>::Type>;
33};
34
35template <typename T>
36struct UnwrapArg<OutMoveHandle<T>> {
37 using Type = AutoOut<typename OutMoveHandle<T>::Type>;
38};
39
40template <typename T, int A>
41struct UnwrapArg<OutLargeData<T, A>> {
42 using Type = AutoOut<typename OutLargeData<T, A>::Type>;
43};
44
45enum class ArgumentType {
46 InProcessId,
47 InData,
48 InInterface,
49 InCopyHandle,
50 OutData,
51 OutInterface,
52 OutCopyHandle,
53 OutMoveHandle,
54 InBuffer,
55 InLargeData,
56 OutBuffer,
57 OutLargeData,
58};
59
60template <typename T>
61struct ArgumentTraits;
62
63template <>
64struct ArgumentTraits<ClientProcessId> {
65 static constexpr ArgumentType Type = ArgumentType::InProcessId;
66};
67
68template <typename T>
69struct ArgumentTraits<SharedPointer<T>> {
70 static constexpr ArgumentType Type = ArgumentType::InInterface;
71};
72
73template <typename T>
74struct ArgumentTraits<InCopyHandle<T>> {
75 static constexpr ArgumentType Type = ArgumentType::InCopyHandle;
76};
77
78template <typename T>
79struct ArgumentTraits<Out<SharedPointer<T>>> {
80 static constexpr ArgumentType Type = ArgumentType::OutInterface;
81};
82
83template <typename T>
84struct ArgumentTraits<Out<T>> {
85 static constexpr ArgumentType Type = ArgumentType::OutData;
86};
87
88template <typename T>
89struct ArgumentTraits<OutCopyHandle<T>> {
90 static constexpr ArgumentType Type = ArgumentType::OutCopyHandle;
91};
92
93template <typename T>
94struct ArgumentTraits<OutMoveHandle<T>> {
95 static constexpr ArgumentType Type = ArgumentType::OutMoveHandle;
96};
97
98template <typename T, int A>
99struct ArgumentTraits<Buffer<T, A>> {
100 static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer;
101};
102
103template <typename T, int A>
104struct ArgumentTraits<InLargeData<T, A>> {
105 static constexpr ArgumentType Type = ArgumentType::InLargeData;
106};
107
108template <typename T, int A>
109struct ArgumentTraits<OutLargeData<T, A>> {
110 static constexpr ArgumentType Type = ArgumentType::OutLargeData;
111};
112
113template <typename T>
114struct ArgumentTraits {
115 static constexpr ArgumentType Type = ArgumentType::InData;
116};
117
15struct RequestLayout { 118struct RequestLayout {
16 u32 copy_handle_count; 119 u32 copy_handle_count;
17 u32 move_handle_count; 120 u32 move_handle_count;
@@ -122,6 +225,8 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
122 225
123 static_assert(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment"); 226 static_assert(PrevAlign <= ArgAlign, "Input argument is not ordered by alignment");
124 static_assert(!RawDataFinished, "All input interface arguments must appear after raw data"); 227 static_assert(!RawDataFinished, "All input interface arguments must appear after raw data");
228 static_assert(!std::is_pointer_v<ArgType>, "Input raw data must not be a pointer");
229 static_assert(std::is_trivially_copyable_v<ArgType>, "Input raw data must be trivially copyable");
125 230
126 constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); 231 constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
127 constexpr size_t ArgEnd = ArgOffset + ArgSize; 232 constexpr size_t ArgEnd = ArgOffset + ArgSize;
@@ -198,7 +303,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
198 constexpr size_t BufferSize = sizeof(ArgType); 303 constexpr size_t BufferSize = sizeof(ArgType);
199 304
200 // Clear the existing data. 305 // Clear the existing data.
201 std::memset(&std::get<ArgIndex>(args), 0, BufferSize); 306 std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
202 307
203 return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 308 return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex, OutBufferIndex + 1, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
204 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) { 309 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutBuffer) {
@@ -237,27 +342,29 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
237 342
238 static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment"); 343 static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
239 static_assert(!RawDataFinished, "All output interface arguments must appear after raw data"); 344 static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
345 static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
346 static_assert(std::is_trivially_copyable_v<decltype(std::get<ArgIndex>(args).raw)>, "Output raw data must be trivially copyable");
240 347
241 constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign); 348 constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
242 constexpr size_t ArgEnd = ArgOffset + ArgSize; 349 constexpr size_t ArgEnd = ArgOffset + ArgSize;
243 350
244 std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args), ArgSize); 351 std::memcpy(raw_data + ArgOffset, &std::get<ArgIndex>(args).raw, ArgSize);
245 352
246 return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 353 return WriteOutArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, OutBufferIndex, false, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
247 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) { 354 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutInterface) {
248 if (is_domain) { 355 if (is_domain) {
249 ctx.AddDomainObject(std::get<ArgIndex>(args)); 356 ctx.AddDomainObject(std::get<ArgIndex>(args).raw);
250 } else { 357 } else {
251 ctx.AddMoveInterface(std::get<ArgIndex>(args)); 358 ctx.AddMoveInterface(std::get<ArgIndex>(args).raw);
252 } 359 }
253 360
254 return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 361 return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
255 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) { 362 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) {
256 ctx.AddCopyObject(std::get<ArgIndex>(args)); 363 ctx.AddCopyObject(std::get<ArgIndex>(args).raw);
257 364
258 return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 365 return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
259 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) { 366 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) {
260 ctx.AddMoveObject(std::get<ArgIndex>(args)); 367 ctx.AddMoveObject(std::get<ArgIndex>(args).raw);
261 368
262 return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); 369 return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
263 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { 370 } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
@@ -302,10 +409,10 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
302 } 409 }
303 const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false; 410 const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false;
304 411
305 using MethodArguments = std::tuple<std::remove_reference_t<A>...>; 412 using MethodArguments = std::tuple<std::remove_cvref_t<A>...>;
306 413
307 OutTemporaryBuffers buffers{}; 414 OutTemporaryBuffers buffers{};
308 auto call_arguments = std::tuple<typename RemoveOut<A>::Type...>(); 415 auto call_arguments = std::tuple<typename UnwrapArg<A>::Type...>();
309 416
310 // Read inputs. 417 // Read inputs.
311 const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2; 418 const size_t offset_plus_command_id = ctx.GetDataPayloadOffset() + 2;
diff --git a/src/core/hle/service/cmif_types.h b/src/core/hle/service/cmif_types.h
index 2610c49f3..dc06169f4 100644
--- a/src/core/hle/service/cmif_types.h
+++ b/src/core/hle/service/cmif_types.h
@@ -13,21 +13,30 @@ namespace Service {
13 13
14// clang-format off 14// clang-format off
15template <typename T> 15template <typename T>
16struct AutoOut {
17 T raw;
18};
19
20template <typename T>
16class Out { 21class Out {
17public: 22public:
18 using Type = T; 23 using Type = T;
19 24
20 /* implicit */ Out(Type& t) : raw(&t) {} 25 /* implicit */ Out(AutoOut<Type>& t) : raw(&t.raw) {}
21 ~Out() = default; 26 /* implicit */ Out(Type* t) : raw(t) {}
22 27
23 Type* Get() const { 28 Type* Get() const {
24 return raw; 29 return raw;
25 } 30 }
26 31
27 Type& operator*() { 32 Type& operator*() const {
28 return *raw; 33 return *raw;
29 } 34 }
30 35
36 Type* operator->() const {
37 return raw;
38 }
39
31private: 40private:
32 Type* raw; 41 Type* raw;
33}; 42};
@@ -35,6 +44,9 @@ private:
35template <typename T> 44template <typename T>
36using SharedPointer = std::shared_ptr<T>; 45using SharedPointer = std::shared_ptr<T>;
37 46
47template <typename T>
48using OutInterface = Out<SharedPointer<T>>;
49
38struct ClientProcessId { 50struct ClientProcessId {
39 explicit operator bool() const { 51 explicit operator bool() const {
40 return pid != 0; 52 return pid != 0;
@@ -101,17 +113,21 @@ class OutCopyHandle {
101public: 113public:
102 using Type = T*; 114 using Type = T*;
103 115
104 /* implicit */ OutCopyHandle(Type& t) : raw(&t) {} 116 /* implicit */ OutCopyHandle(AutoOut<Type>& t) : raw(&t.raw) {}
105 ~OutCopyHandle() = default; 117 /* implicit */ OutCopyHandle(Type* t) : raw(t) {}
106 118
107 Type* Get() const { 119 Type* Get() const {
108 return raw; 120 return raw;
109 } 121 }
110 122
111 Type& operator*() { 123 Type& operator*() const {
112 return *raw; 124 return *raw;
113 } 125 }
114 126
127 Type* operator->() const {
128 return raw;
129 }
130
115private: 131private:
116 Type* raw; 132 Type* raw;
117}; 133};
@@ -121,30 +137,34 @@ class OutMoveHandle {
121public: 137public:
122 using Type = T*; 138 using Type = T*;
123 139
124 /* implicit */ OutMoveHandle(Type& t) : raw(&t) {} 140 /* implicit */ OutMoveHandle(AutoOut<Type>& t) : raw(&t.raw) {}
125 ~OutMoveHandle() = default; 141 /* implicit */ OutMoveHandle(Type* t) : raw(t) {}
126 142
127 Type* Get() const { 143 Type* Get() const {
128 return raw; 144 return raw;
129 } 145 }
130 146
131 Type& operator*() { 147 Type& operator*() const {
132 return *raw; 148 return *raw;
133 } 149 }
134 150
151 Type* operator->() const {
152 return raw;
153 }
154
135private: 155private:
136 Type* raw; 156 Type* raw;
137}; 157};
138 158
139enum BufferAttr : int { 159enum BufferAttr : int {
140 BufferAttr_In = (1U << 0), 160 /* 0x01 */ BufferAttr_In = (1U << 0),
141 BufferAttr_Out = (1U << 1), 161 /* 0x02 */ BufferAttr_Out = (1U << 1),
142 BufferAttr_HipcMapAlias = (1U << 2), 162 /* 0x04 */ BufferAttr_HipcMapAlias = (1U << 2),
143 BufferAttr_HipcPointer = (1U << 3), 163 /* 0x08 */ BufferAttr_HipcPointer = (1U << 3),
144 BufferAttr_FixedSize = (1U << 4), 164 /* 0x10 */ BufferAttr_FixedSize = (1U << 4),
145 BufferAttr_HipcAutoSelect = (1U << 5), 165 /* 0x20 */ BufferAttr_HipcAutoSelect = (1U << 5),
146 BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6), 166 /* 0x40 */ BufferAttr_HipcMapTransferAllowsNonSecure = (1U << 6),
147 BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7), 167 /* 0x80 */ BufferAttr_HipcMapTransferAllowsNonDevice = (1U << 7),
148}; 168};
149 169
150template <typename T, int A> 170template <typename T, int A>
@@ -172,123 +192,80 @@ struct Buffer : public std::span<T> {
172 } 192 }
173}; 193};
174 194
175template <BufferAttr A> 195template <int A>
176using InBuffer = Buffer<const u8, BufferAttr_In | A>; 196using InBuffer = Buffer<const u8, BufferAttr_In | A>;
177 197
178template <typename T, BufferAttr A> 198template <typename T, int A>
179using InArray = Buffer<T, BufferAttr_In | A>; 199using InArray = Buffer<T, BufferAttr_In | A>;
180 200
181template <BufferAttr A> 201template <int A>
182using OutBuffer = Buffer<u8, BufferAttr_Out | A>; 202using OutBuffer = Buffer<u8, BufferAttr_Out | A>;
183 203
184template <typename T, BufferAttr A> 204template <typename T, int A>
185using OutArray = Buffer<T, BufferAttr_Out | A>; 205using OutArray = Buffer<T, BufferAttr_Out | A>;
186 206
187template <typename T, int A> 207template <typename T, int A>
188struct LargeData : public T { 208class InLargeData {
209public:
189 static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable"); 210 static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
190 static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize"); 211 static_assert((A & BufferAttr_Out) == 0, "InLargeData attr must not be Out");
191 static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out"); 212 static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize);
192 static constexpr BufferAttr Attr = static_cast<BufferAttr>(A); 213 using Type = const T;
193 using Type = T;
194
195 /* implicit */ LargeData(const T& rhs) : T(rhs) {}
196 /* implicit */ LargeData() = default;
197};
198
199template <typename T, BufferAttr A>
200using InLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_In | A>;
201
202template <typename T, BufferAttr A>
203using OutLargeData = LargeData<T, BufferAttr_FixedSize | BufferAttr_Out | A>;
204 214
205template <typename T> 215 /* implicit */ InLargeData(Type& t) : raw(&t) {}
206struct RemoveOut { 216 ~InLargeData() = default;
207 using Type = std::remove_reference_t<T>;
208};
209
210template <typename T>
211struct RemoveOut<Out<T>> {
212 using Type = typename Out<T>::Type;
213};
214 217
215template <typename T> 218 InLargeData& operator=(Type* rhs) {
216struct RemoveOut<OutCopyHandle<T>> { 219 raw = rhs;
217 using Type = typename OutCopyHandle<T>::Type; 220 return *this;
218}; 221 }
219
220template <typename T>
221struct RemoveOut<OutMoveHandle<T>> {
222 using Type = typename OutMoveHandle<T>::Type;
223};
224
225enum class ArgumentType {
226 InProcessId,
227 InData,
228 InInterface,
229 InCopyHandle,
230 OutData,
231 OutInterface,
232 OutCopyHandle,
233 OutMoveHandle,
234 InBuffer,
235 InLargeData,
236 OutBuffer,
237 OutLargeData,
238};
239 222
240template <typename T> 223 Type* Get() const {
241struct ArgumentTraits; 224 return raw;
225 }
242 226
243template <> 227 Type& operator*() const {
244struct ArgumentTraits<ClientProcessId> { 228 return *raw;
245 static constexpr ArgumentType Type = ArgumentType::InProcessId; 229 }
246};
247 230
248template <typename T> 231 Type* operator->() const {
249struct ArgumentTraits<SharedPointer<T>> { 232 return raw;
250 static constexpr ArgumentType Type = ArgumentType::InInterface; 233 }
251};
252 234
253template <typename T> 235 explicit operator bool() const {
254struct ArgumentTraits<InCopyHandle<T>> { 236 return raw != nullptr;
255 static constexpr ArgumentType Type = ArgumentType::InCopyHandle; 237 }
256};
257 238
258template <typename T> 239private:
259struct ArgumentTraits<Out<SharedPointer<T>>> { 240 Type* raw;
260 static constexpr ArgumentType Type = ArgumentType::OutInterface;
261}; 241};
262 242
263template <typename T> 243template <typename T, int A>
264struct ArgumentTraits<Out<T>> { 244class OutLargeData {
265 static constexpr ArgumentType Type = ArgumentType::OutData; 245public:
266}; 246 static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
247 static_assert((A & BufferAttr_In) == 0, "OutLargeData attr must not be In");
248 static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize);
249 using Type = T;
267 250
268template <typename T> 251 /* implicit */ OutLargeData(Type* t) : raw(t) {}
269struct ArgumentTraits<OutCopyHandle<T>> { 252 /* implicit */ OutLargeData(AutoOut<T>& t) : raw(&t.raw) {}
270 static constexpr ArgumentType Type = ArgumentType::OutCopyHandle;
271};
272 253
273template <typename T> 254 Type* Get() const {
274struct ArgumentTraits<OutMoveHandle<T>> { 255 return raw;
275 static constexpr ArgumentType Type = ArgumentType::OutMoveHandle; 256 }
276};
277 257
278template <typename T, int A> 258 Type& operator*() const {
279struct ArgumentTraits<Buffer<T, A>> { 259 return *raw;
280 static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutBuffer : ArgumentType::InBuffer; 260 }
281};
282 261
283template <typename T, int A> 262 Type* operator->() const {
284struct ArgumentTraits<LargeData<T, A>> { 263 return raw;
285 static constexpr ArgumentType Type = (A & BufferAttr_In) == 0 ? ArgumentType::OutLargeData : ArgumentType::InLargeData; 264 }
286};
287 265
288template <typename T> 266private:
289struct ArgumentTraits { 267 Type* raw;
290 static constexpr ArgumentType Type = ArgumentType::InData;
291}; 268};
292// clang-format on 269// clang-format on
293 270
294} // namespace Service 271} // namespace Service \ No newline at end of file
diff --git a/src/core/hle/service/glue/time/alarm_worker.cpp b/src/core/hle/service/glue/time/alarm_worker.cpp
index f549ed00a..3ff071f4a 100644
--- a/src/core/hle/service/glue/time/alarm_worker.cpp
+++ b/src/core/hle/service/glue/time/alarm_worker.cpp
@@ -41,7 +41,7 @@ bool AlarmWorker::GetClosestAlarmInfo(Service::PSC::Time::AlarmInfo& out_alarm_i
41 Service::PSC::Time::AlarmInfo alarm_info{}; 41 Service::PSC::Time::AlarmInfo alarm_info{};
42 s64 closest_time{}; 42 s64 closest_time{};
43 43
44 auto res = m_time_m->GetClosestAlarmInfo(is_valid, alarm_info, closest_time); 44 auto res = m_time_m->GetClosestAlarmInfo(&is_valid, &alarm_info, &closest_time);
45 ASSERT(res == ResultSuccess); 45 ASSERT(res == ResultSuccess);
46 46
47 if (is_valid) { 47 if (is_valid) {
@@ -76,6 +76,7 @@ void AlarmWorker::OnPowerStateChanged() {
76 76
77Result AlarmWorker::AttachToClosestAlarmEvent() { 77Result AlarmWorker::AttachToClosestAlarmEvent() {
78 m_time_m->GetClosestAlarmUpdatedEvent(&m_event); 78 m_time_m->GetClosestAlarmUpdatedEvent(&m_event);
79
79 R_SUCCEED(); 80 R_SUCCEED();
80} 81}
81 82
diff --git a/src/core/hle/service/glue/time/alarm_worker.h b/src/core/hle/service/glue/time/alarm_worker.h
index f269cffdb..131d012a6 100644
--- a/src/core/hle/service/glue/time/alarm_worker.h
+++ b/src/core/hle/service/glue/time/alarm_worker.h
@@ -26,7 +26,7 @@ public:
26 26
27 void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m); 27 void Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m);
28 28
29 Kernel::KEvent& GetEvent() { 29 Kernel::KReadableEvent& GetEvent() {
30 return *m_event; 30 return *m_event;
31 } 31 }
32 32
@@ -44,7 +44,7 @@ private:
44 KernelHelpers::ServiceContext m_ctx; 44 KernelHelpers::ServiceContext m_ctx;
45 std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m; 45 std::shared_ptr<Service::PSC::Time::ServiceManager> m_time_m;
46 46
47 Kernel::KEvent* m_event{}; 47 Kernel::KReadableEvent* m_event{};
48 Kernel::KEvent* m_timer_event{}; 48 Kernel::KEvent* m_timer_event{};
49 std::shared_ptr<Core::Timing::EventType> m_timer_timing_event; 49 std::shared_ptr<Core::Timing::EventType> m_timer_timing_event;
50 StandardSteadyClockResource& m_steady_clock_resource; 50 StandardSteadyClockResource& m_steady_clock_resource;
diff --git a/src/core/hle/service/glue/time/file_timestamp_worker.cpp b/src/core/hle/service/glue/time/file_timestamp_worker.cpp
index 5a6309549..048ff174c 100644
--- a/src/core/hle/service/glue/time/file_timestamp_worker.cpp
+++ b/src/core/hle/service/glue/time/file_timestamp_worker.cpp
@@ -13,8 +13,8 @@ void FileTimestampWorker::SetFilesystemPosixTime() {
13 Service::PSC::Time::CalendarTime calendar_time{}; 13 Service::PSC::Time::CalendarTime calendar_time{};
14 Service::PSC::Time::CalendarAdditionalInfo additional_info{}; 14 Service::PSC::Time::CalendarAdditionalInfo additional_info{};
15 15
16 if (m_initialized && m_system_clock->GetCurrentTime(time) == ResultSuccess && 16 if (m_initialized && m_system_clock->GetCurrentTime(&time) == ResultSuccess &&
17 m_time_zone->ToCalendarTimeWithMyRule(calendar_time, additional_info, time) == 17 m_time_zone->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, time) ==
18 ResultSuccess) { 18 ResultSuccess) {
19 // TODO IFileSystemProxy::SetCurrentPosixTime 19 // TODO IFileSystemProxy::SetCurrentPosixTime
20 } 20 }
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp
index b56762941..0c27e8029 100644
--- a/src/core/hle/service/glue/time/manager.cpp
+++ b/src/core/hle/service/glue/time/manager.cpp
@@ -79,18 +79,18 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN
79 auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); 79 auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
80 80
81 Service::PSC::Time::LocationName configured_name{}; 81 Service::PSC::Time::LocationName configured_name{};
82 std::memcpy(configured_name.name.data(), configured_zone.data(), 82 std::memcpy(configured_name.data(), configured_zone.data(),
83 std::min(configured_name.name.size(), configured_zone.size())); 83 std::min(configured_name.size(), configured_zone.size()));
84 84
85 if (!IsTimeZoneBinaryValid(configured_name)) { 85 if (!IsTimeZoneBinaryValid(configured_name)) {
86 configured_zone = Common::TimeZone::FindSystemTimeZone(); 86 configured_zone = Common::TimeZone::FindSystemTimeZone();
87 configured_name = {}; 87 configured_name = {};
88 std::memcpy(configured_name.name.data(), configured_zone.data(), 88 std::memcpy(configured_name.data(), configured_zone.data(),
89 std::min(configured_name.name.size(), configured_zone.size())); 89 std::min(configured_name.size(), configured_zone.size()));
90 } 90 }
91 91
92 ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!", 92 ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!",
93 configured_name.name.data()); 93 configured_name.data());
94 94
95 return configured_name; 95 return configured_name;
96} 96}
@@ -103,7 +103,7 @@ TimeManager::TimeManager(Core::System& system)
103 m_time_m = 103 m_time_m =
104 system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true); 104 system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true);
105 105
106 auto res = m_time_m->GetStaticServiceAsServiceManager(m_time_sm); 106 auto res = m_time_m->GetStaticServiceAsServiceManager(&m_time_sm);
107 ASSERT(res == ResultSuccess); 107 ASSERT(res == ResultSuccess);
108 108
109 m_set_sys = 109 m_set_sys =
@@ -114,10 +114,10 @@ TimeManager::TimeManager(Core::System& system)
114 114
115 m_worker.Initialize(m_time_sm, m_set_sys); 115 m_worker.Initialize(m_time_sm, m_set_sys);
116 116
117 res = m_time_sm->GetStandardUserSystemClock(m_file_timestamp_worker.m_system_clock); 117 res = m_time_sm->GetStandardUserSystemClock(&m_file_timestamp_worker.m_system_clock);
118 ASSERT(res == ResultSuccess); 118 ASSERT(res == ResultSuccess);
119 119
120 res = m_time_sm->GetTimeZoneService(m_file_timestamp_worker.m_time_zone); 120 res = m_time_sm->GetTimeZoneService(&m_file_timestamp_worker.m_time_zone);
121 ASSERT(res == ResultSuccess); 121 ASSERT(res == ResultSuccess);
122 122
123 res = SetupStandardSteadyClockCore(); 123 res = SetupStandardSteadyClockCore();
@@ -161,8 +161,8 @@ TimeManager::TimeManager(Core::System& system)
161 automatic_correction_time_point); 161 automatic_correction_time_point);
162 ASSERT(res == ResultSuccess); 162 ASSERT(res == ResultSuccess);
163 163
164 res = m_time_m->SetupStandardUserSystemClockCore(automatic_correction_time_point, 164 res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled,
165 is_automatic_correction_enabled); 165 automatic_correction_time_point);
166 ASSERT(res == ResultSuccess); 166 ASSERT(res == ResultSuccess);
167 167
168 res = m_time_m->SetupEphemeralNetworkSystemClockCore(); 168 res = m_time_m->SetupEphemeralNetworkSystemClockCore();
@@ -184,12 +184,12 @@ TimeManager::TimeManager(Core::System& system)
184 m_file_timestamp_worker.m_initialized = true; 184 m_file_timestamp_worker.m_initialized = true;
185 185
186 s64 system_clock_time{}; 186 s64 system_clock_time{};
187 if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(system_clock_time) == 187 if (m_file_timestamp_worker.m_system_clock->GetCurrentTime(&system_clock_time) ==
188 ResultSuccess) { 188 ResultSuccess) {
189 Service::PSC::Time::CalendarTime calendar_time{}; 189 Service::PSC::Time::CalendarTime calendar_time{};
190 Service::PSC::Time::CalendarAdditionalInfo calendar_additional{}; 190 Service::PSC::Time::CalendarAdditionalInfo calendar_additional{};
191 if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule( 191 if (m_file_timestamp_worker.m_time_zone->ToCalendarTimeWithMyRule(
192 calendar_time, calendar_additional, system_clock_time) == ResultSuccess) { 192 &calendar_time, &calendar_additional, system_clock_time) == ResultSuccess) {
193 // TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time, 193 // TODO IFileSystemProxy::SetCurrentPosixTime(system_clock_time,
194 // calendar_additional.ut_offset) 194 // calendar_additional.ut_offset)
195 } 195 }
@@ -228,10 +228,9 @@ Result TimeManager::SetupStandardSteadyClockCore() {
228 m_set_sys->SetExternalSteadyClockSourceId(clock_source_id); 228 m_set_sys->SetExternalSteadyClockSourceId(clock_source_id);
229 } 229 }
230 230
231 res = m_time_m->SetupStandardSteadyClockCore(clock_source_id, m_steady_clock_resource.GetTime(), 231 res = m_time_m->SetupStandardSteadyClockCore(
232 external_steady_clock_internal_offset_ns, 232 reset_detected, clock_source_id, m_steady_clock_resource.GetTime(),
233 standard_steady_clock_test_offset_ns, 233 external_steady_clock_internal_offset_ns, standard_steady_clock_test_offset_ns);
234 reset_detected);
235 ASSERT(res == ResultSuccess); 234 ASSERT(res == ResultSuccess);
236 R_SUCCEED(); 235 R_SUCCEED();
237} 236}
@@ -243,14 +242,15 @@ Result TimeManager::SetupTimeZoneServiceCore() {
243 242
244 auto configured_zone = GetTimeZoneString(name); 243 auto configured_zone = GetTimeZoneString(name);
245 244
246 if (configured_zone.name != name.name) { 245 if (configured_zone != name) {
247 m_set_sys->SetDeviceTimeZoneLocationName(configured_zone); 246 m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
248 name = configured_zone; 247 name = configured_zone;
249 248
250 std::shared_ptr<Service::PSC::Time::SystemClock> local_clock; 249 std::shared_ptr<Service::PSC::Time::SystemClock> local_clock;
251 m_time_sm->GetStandardLocalSystemClock(local_clock); 250 m_time_sm->GetStandardLocalSystemClock(&local_clock);
251
252 Service::PSC::Time::SystemClockContext context{}; 252 Service::PSC::Time::SystemClockContext context{};
253 local_clock->GetSystemClockContext(context); 253 local_clock->GetSystemClockContext(&context);
254 m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point); 254 m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(context.steady_time_point);
255 } 255 }
256 256
@@ -267,7 +267,7 @@ Result TimeManager::SetupTimeZoneServiceCore() {
267 res = GetTimeZoneRule(rule_buffer, rule_size, name); 267 res = GetTimeZoneRule(rule_buffer, rule_size, name);
268 ASSERT(res == ResultSuccess); 268 ASSERT(res == ResultSuccess);
269 269
270 res = m_time_m->SetupTimeZoneServiceCore(name, time_point, rule_version, location_count, 270 res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point,
271 rule_buffer); 271 rule_buffer);
272 ASSERT(res == ResultSuccess); 272 ASSERT(res == ResultSuccess);
273 273
diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp
index 63b7d91da..f56db76e1 100644
--- a/src/core/hle/service/glue/time/static.cpp
+++ b/src/core/hle/service/glue/time/static.cpp
@@ -3,9 +3,11 @@
3 3
4#include <chrono> 4#include <chrono>
5 5
6#include "common/scope_exit.h"
6#include "core/core.h" 7#include "core/core.h"
7#include "core/hle/kernel/k_shared_memory.h" 8#include "core/hle/kernel/k_shared_memory.h"
8#include "core/hle/kernel/svc.h" 9#include "core/hle/kernel/svc.h"
10#include "core/hle/service/cmif_serialization.h"
9#include "core/hle/service/glue/time/file_timestamp_worker.h" 11#include "core/hle/service/glue/time/file_timestamp_worker.h"
10#include "core/hle/service/glue/time/static.h" 12#include "core/hle/service/glue/time/static.h"
11#include "core/hle/service/psc/time/errors.h" 13#include "core/hle/service/psc/time/errors.h"
@@ -41,25 +43,25 @@ StaticService::StaticService(Core::System& system_,
41 time->m_steady_clock_resource} { 43 time->m_steady_clock_resource} {
42 // clang-format off 44 // clang-format off
43 static const FunctionInfo functions[] = { 45 static const FunctionInfo functions[] = {
44 {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"}, 46 {0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
45 {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, 47 {1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"},
46 {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"}, 48 {2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"},
47 {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"}, 49 {3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"},
48 {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, 50 {4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"},
49 {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"}, 51 {5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"},
50 {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, 52 {20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
51 {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"}, 53 {50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"},
52 {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"}, 54 {51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"},
53 {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, 55 {100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
54 {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, 56 {101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
55 {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"}, 57 {102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"},
56 {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"}, 58 {200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"},
57 {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, 59 {201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
58 {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"}, 60 {300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"},
59 {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"}, 61 {400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"},
60 {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"}, 62 {401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"},
61 {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"}, 63 {500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"},
62 {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"}, 64 {501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"},
63 }; 65 };
64 // clang-format on 66 // clang-format on
65 67
@@ -71,314 +73,80 @@ StaticService::StaticService(Core::System& system_,
71 if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock && 73 if (m_setup_info.can_write_local_clock && m_setup_info.can_write_user_clock &&
72 !m_setup_info.can_write_network_clock && m_setup_info.can_write_timezone_device_location && 74 !m_setup_info.can_write_network_clock && m_setup_info.can_write_timezone_device_location &&
73 !m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { 75 !m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) {
74 m_time_m->GetStaticServiceAsAdmin(m_wrapped_service); 76 m_time_m->GetStaticServiceAsAdmin(&m_wrapped_service);
75 } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && 77 } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock &&
76 !m_setup_info.can_write_network_clock && 78 !m_setup_info.can_write_network_clock &&
77 !m_setup_info.can_write_timezone_device_location && 79 !m_setup_info.can_write_timezone_device_location &&
78 !m_setup_info.can_write_steady_clock && 80 !m_setup_info.can_write_steady_clock &&
79 !m_setup_info.can_write_uninitialized_clock) { 81 !m_setup_info.can_write_uninitialized_clock) {
80 m_time_m->GetStaticServiceAsUser(m_wrapped_service); 82 m_time_m->GetStaticServiceAsUser(&m_wrapped_service);
81 } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock && 83 } else if (!m_setup_info.can_write_local_clock && !m_setup_info.can_write_user_clock &&
82 !m_setup_info.can_write_network_clock && 84 !m_setup_info.can_write_network_clock &&
83 !m_setup_info.can_write_timezone_device_location && 85 !m_setup_info.can_write_timezone_device_location &&
84 m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) { 86 m_setup_info.can_write_steady_clock && !m_setup_info.can_write_uninitialized_clock) {
85 m_time_m->GetStaticServiceAsRepair(m_wrapped_service); 87 m_time_m->GetStaticServiceAsRepair(&m_wrapped_service);
86 } else { 88 } else {
87 UNREACHABLE(); 89 UNREACHABLE();
88 } 90 }
89 91
90 auto res = m_wrapped_service->GetTimeZoneService(m_time_zone); 92 auto res = m_wrapped_service->GetTimeZoneService(&m_time_zone);
91 ASSERT(res == ResultSuccess); 93 ASSERT(res == ResultSuccess);
92} 94}
93 95
94void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) { 96Result StaticService::GetStandardUserSystemClock(
95 LOG_DEBUG(Service_Time, "called."); 97 OutInterface<Service::PSC::Time::SystemClock> out_service) {
96
97 std::shared_ptr<Service::PSC::Time::SystemClock> service{};
98 auto res = GetStandardUserSystemClock(service);
99
100 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
101 rb.Push(res);
102 rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
103}
104
105void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) {
106 LOG_DEBUG(Service_Time, "called.");
107
108 std::shared_ptr<Service::PSC::Time::SystemClock> service{};
109 auto res = GetStandardNetworkSystemClock(service);
110
111 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
112 rb.Push(res);
113 rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
114}
115
116void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) {
117 LOG_DEBUG(Service_Time, "called.");
118
119 std::shared_ptr<Service::PSC::Time::SteadyClock> service{};
120 auto res = GetStandardSteadyClock(service);
121
122 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
123 rb.Push(res);
124 rb.PushIpcInterface(std::move(service));
125}
126
127void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) {
128 LOG_DEBUG(Service_Time, "called.");
129
130 std::shared_ptr<TimeZoneService> service{};
131 auto res = GetTimeZoneService(service);
132
133 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
134 rb.Push(res);
135 rb.PushIpcInterface(std::move(service));
136}
137
138void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) {
139 LOG_DEBUG(Service_Time, "called.");
140
141 std::shared_ptr<Service::PSC::Time::SystemClock> service{};
142 auto res = GetStandardLocalSystemClock(service);
143
144 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
145 rb.Push(res);
146 rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
147}
148
149void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) {
150 LOG_DEBUG(Service_Time, "called.");
151
152 std::shared_ptr<Service::PSC::Time::SystemClock> service{};
153 auto res = GetEphemeralNetworkSystemClock(service);
154
155 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
156 rb.Push(res);
157 rb.PushIpcInterface<Service::PSC::Time::SystemClock>(std::move(service));
158}
159
160void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
161 LOG_DEBUG(Service_Time, "called.");
162
163 Kernel::KSharedMemory* shared_memory{};
164 auto res = GetSharedMemoryNativeHandle(&shared_memory);
165
166 IPC::ResponseBuilder rb{ctx, 2, 1};
167 rb.Push(res);
168 rb.PushCopyObjects(shared_memory);
169}
170
171void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) {
172 LOG_DEBUG(Service_Time, "called.");
173
174 IPC::RequestParser rp{ctx};
175 auto offset_ns{rp.Pop<s64>()};
176
177 auto res = SetStandardSteadyClockInternalOffset(offset_ns);
178
179 IPC::ResponseBuilder rb{ctx, 2};
180 rb.Push(res);
181}
182
183void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) {
184 LOG_DEBUG(Service_Time, "called.");
185
186 s64 rtc_value{};
187 auto res = GetStandardSteadyClockRtcValue(rtc_value);
188
189 IPC::ResponseBuilder rb{ctx, 4};
190 rb.Push(res);
191 rb.Push(rtc_value);
192}
193
194void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(
195 HLERequestContext& ctx) {
196 LOG_DEBUG(Service_Time, "called.");
197
198 bool is_enabled{};
199 auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled);
200
201 IPC::ResponseBuilder rb{ctx, 3};
202 rb.Push(res);
203 rb.Push<bool>(is_enabled);
204}
205
206void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(
207 HLERequestContext& ctx) {
208 LOG_DEBUG(Service_Time, "called.");
209
210 IPC::RequestParser rp{ctx};
211 auto automatic_correction{rp.Pop<bool>()};
212
213 auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
214
215 IPC::ResponseBuilder rb{ctx, 2};
216 rb.Push(res);
217}
218
219void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) {
220 LOG_DEBUG(Service_Time, "called.");
221
222 s32 initial_year{};
223 auto res = GetStandardUserSystemClockInitialYear(initial_year);
224
225 IPC::ResponseBuilder rb{ctx, 3};
226 rb.Push(res);
227 rb.Push(initial_year);
228}
229
230void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
231 LOG_DEBUG(Service_Time, "called."); 98 LOG_DEBUG(Service_Time, "called.");
232 99
233 bool is_sufficient{}; 100 R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service));
234 auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient);
235
236 IPC::ResponseBuilder rb{ctx, 3};
237 rb.Push(res);
238 rb.Push<bool>(is_sufficient);
239} 101}
240 102
241void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( 103Result StaticService::GetStandardNetworkSystemClock(
242 HLERequestContext& ctx) { 104 OutInterface<Service::PSC::Time::SystemClock> out_service) {
243 LOG_DEBUG(Service_Time, "called."); 105 LOG_DEBUG(Service_Time, "called.");
244 106
245 Service::PSC::Time::SteadyClockTimePoint time_point{}; 107 R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service));
246 auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
247
248 IPC::ResponseBuilder rb{ctx,
249 2 + sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32)};
250 rb.Push(res);
251 rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
252} 108}
253 109
254void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) { 110Result StaticService::GetStandardSteadyClock(
111 OutInterface<Service::PSC::Time::SteadyClock> out_service) {
255 LOG_DEBUG(Service_Time, "called."); 112 LOG_DEBUG(Service_Time, "called.");
256 113
257 IPC::RequestParser rp{ctx}; 114 R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service));
258 auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
259
260 s64 time{};
261 auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context);
262
263 IPC::ResponseBuilder rb{ctx, 4};
264 rb.Push(res);
265 rb.Push<s64>(time);
266} 115}
267 116
268void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) { 117Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) {
269 LOG_DEBUG(Service_Time, "called."); 118 LOG_DEBUG(Service_Time, "called.");
270 119
271 IPC::RequestParser rp{ctx}; 120 *out_service = std::make_shared<TimeZoneService>(
272 auto type{rp.PopEnum<Service::PSC::Time::TimeType>()}; 121 m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location,
273 122 m_time_zone);
274 Service::PSC::Time::ClockSnapshot snapshot{}; 123 R_SUCCEED();
275 auto res = GetClockSnapshot(snapshot, type);
276
277 ctx.WriteBuffer(snapshot);
278
279 IPC::ResponseBuilder rb{ctx, 2};
280 rb.Push(res);
281} 124}
282 125
283void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) { 126Result StaticService::GetStandardLocalSystemClock(
127 OutInterface<Service::PSC::Time::SystemClock> out_service) {
284 LOG_DEBUG(Service_Time, "called."); 128 LOG_DEBUG(Service_Time, "called.");
285 129
286 IPC::RequestParser rp{ctx}; 130 R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service));
287 auto clock_type{rp.PopEnum<Service::PSC::Time::TimeType>()};
288 [[maybe_unused]] auto alignment{rp.Pop<u32>()};
289 auto user_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
290 auto network_context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
291
292 Service::PSC::Time::ClockSnapshot snapshot{};
293 auto res =
294 GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type);
295
296 ctx.WriteBuffer(snapshot);
297
298 IPC::ResponseBuilder rb{ctx, 2};
299 rb.Push(res);
300} 131}
301 132
302void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser( 133Result StaticService::GetEphemeralNetworkSystemClock(
303 HLERequestContext& ctx) { 134 OutInterface<Service::PSC::Time::SystemClock> out_service) {
304 LOG_DEBUG(Service_Time, "called."); 135 LOG_DEBUG(Service_Time, "called.");
305 136
306 Service::PSC::Time::ClockSnapshot a{}; 137 R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service));
307 Service::PSC::Time::ClockSnapshot b{};
308
309 auto a_buffer{ctx.ReadBuffer(0)};
310 auto b_buffer{ctx.ReadBuffer(1)};
311
312 std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
313 std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
314
315 s64 difference{};
316 auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b);
317
318 IPC::ResponseBuilder rb{ctx, 4};
319 rb.Push(res);
320 rb.Push(difference);
321} 138}
322 139
323void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) { 140Result StaticService::GetSharedMemoryNativeHandle(
141 OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
324 LOG_DEBUG(Service_Time, "called."); 142 LOG_DEBUG(Service_Time, "called.");
325 143
326 Service::PSC::Time::ClockSnapshot a{};
327 Service::PSC::Time::ClockSnapshot b{};
328
329 auto a_buffer{ctx.ReadBuffer(0)};
330 auto b_buffer{ctx.ReadBuffer(1)};
331
332 std::memcpy(&a, a_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
333 std::memcpy(&b, b_buffer.data(), sizeof(Service::PSC::Time::ClockSnapshot));
334
335 s64 time{};
336 auto res = CalculateSpanBetween(time, a, b);
337
338 IPC::ResponseBuilder rb{ctx, 4};
339 rb.Push(res);
340 rb.Push(time);
341}
342
343// =============================== Implementations ===========================
344
345Result StaticService::GetStandardUserSystemClock(
346 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
347 R_RETURN(m_wrapped_service->GetStandardUserSystemClock(out_service));
348}
349
350Result StaticService::GetStandardNetworkSystemClock(
351 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
352 R_RETURN(m_wrapped_service->GetStandardNetworkSystemClock(out_service));
353}
354
355Result StaticService::GetStandardSteadyClock(
356 std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service) {
357 R_RETURN(m_wrapped_service->GetStandardSteadyClock(out_service));
358}
359
360Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) {
361 out_service = std::make_shared<TimeZoneService>(m_system, m_file_timestamp_worker,
362 m_setup_info.can_write_timezone_device_location,
363 m_time_zone);
364 R_SUCCEED();
365}
366
367Result StaticService::GetStandardLocalSystemClock(
368 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
369 R_RETURN(m_wrapped_service->GetStandardLocalSystemClock(out_service));
370}
371
372Result StaticService::GetEphemeralNetworkSystemClock(
373 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service) {
374 R_RETURN(m_wrapped_service->GetEphemeralNetworkSystemClock(out_service));
375}
376
377Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
378 R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory)); 144 R_RETURN(m_wrapped_service->GetSharedMemoryNativeHandle(out_shared_memory));
379} 145}
380 146
381Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { 147Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
148 LOG_DEBUG(Service_Time, "called. offset_ns={}", offset_ns);
149
382 R_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied); 150 R_UNLESS(m_setup_info.can_write_steady_clock, Service::PSC::Time::ResultPermissionDenied);
383 151
384 R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset( 152 R_RETURN(m_set_sys->SetExternalSteadyClockInternalOffset(
@@ -386,62 +154,92 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
386 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count())); 154 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()));
387} 155}
388 156
389Result StaticService::GetStandardSteadyClockRtcValue(s64& out_rtc_value) { 157Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
390 R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(out_rtc_value)); 158 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
159
160 R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value));
391} 161}
392 162
393Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( 163Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
394 bool& out_automatic_correction) { 164 Out<bool> out_automatic_correction) {
165 SCOPE_EXIT({
166 LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction);
167 });
168
395 R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled( 169 R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled(
396 out_automatic_correction)); 170 out_automatic_correction));
397} 171}
398 172
399Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( 173Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
400 bool automatic_correction) { 174 bool automatic_correction) {
175 LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
176
401 R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled( 177 R_RETURN(m_wrapped_service->SetStandardUserSystemClockAutomaticCorrectionEnabled(
402 automatic_correction)); 178 automatic_correction));
403} 179}
404 180
405Result StaticService::GetStandardUserSystemClockInitialYear(s32& out_year) { 181Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
406 out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year"); 182 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); });
183
184 *out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
407 R_SUCCEED(); 185 R_SUCCEED();
408} 186}
409 187
410Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) { 188Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
189 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
190
411 R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient)); 191 R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient));
412} 192}
413 193
414Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( 194Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
415 Service::PSC::Time::SteadyClockTimePoint& out_time_point) { 195 Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
196 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
197
416 R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( 198 R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
417 out_time_point)); 199 out_time_point));
418} 200}
419 201
420Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( 202Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(
421 s64& out_time, Service::PSC::Time::SystemClockContext& context) { 203 Out<s64> out_time, Service::PSC::Time::SystemClockContext& context) {
204 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
205
422 R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context)); 206 R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context));
423} 207}
424 208
425Result StaticService::GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot, 209Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot,
426 Service::PSC::Time::TimeType type) { 210 Service::PSC::Time::TimeType type) {
211 SCOPE_EXIT(
212 { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
213
427 R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type)); 214 R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type));
428} 215}
429 216
430Result StaticService::GetClockSnapshotFromSystemClockContext( 217Result StaticService::GetClockSnapshotFromSystemClockContext(
431 Service::PSC::Time::ClockSnapshot& out_snapshot, 218 Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,
432 Service::PSC::Time::SystemClockContext& user_context, 219 Service::PSC::Time::SystemClockContext& user_context,
433 Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type) { 220 Service::PSC::Time::SystemClockContext& network_context) {
434 R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(out_snapshot, user_context, 221 SCOPE_EXIT({
435 network_context, type)); 222 LOG_DEBUG(Service_Time,
223 "called. type={} out_snapshot={} user_context={} network_context={}", type,
224 *out_snapshot, user_context, network_context);
225 });
226
227 R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext(
228 type, out_snapshot, user_context, network_context));
436} 229}
437 230
438Result StaticService::CalculateStandardUserSystemClockDifferenceByUser( 231Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time,
439 s64& out_time, Service::PSC::Time::ClockSnapshot& a, Service::PSC::Time::ClockSnapshot& b) { 232 InClockSnapshot a,
233 InClockSnapshot b) {
234 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
235
440 R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b)); 236 R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b));
441} 237}
442 238
443Result StaticService::CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a, 239Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
444 Service::PSC::Time::ClockSnapshot& b) { 240 InClockSnapshot b) {
241 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
242
445 R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b)); 243 R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b));
446} 244}
447 245
diff --git a/src/core/hle/service/glue/time/static.h b/src/core/hle/service/glue/time/static.h
index 75fe4e2cd..d3cc0fdd6 100644
--- a/src/core/hle/service/glue/time/static.h
+++ b/src/core/hle/service/glue/time/static.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/glue/time/manager.h" 8#include "core/hle/service/glue/time/manager.h"
8#include "core/hle/service/glue/time/time_zone.h" 9#include "core/hle/service/glue/time/time_zone.h"
9#include "core/hle/service/psc/time/common.h" 10#include "core/hle/service/psc/time/common.h"
@@ -29,6 +30,10 @@ class FileTimestampWorker;
29class StandardSteadyClockResource; 30class StandardSteadyClockResource;
30 31
31class StaticService final : public ServiceFramework<StaticService> { 32class StaticService final : public ServiceFramework<StaticService> {
33 using InClockSnapshot = InLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>;
34 using OutClockSnapshot =
35 OutLargeData<Service::PSC::Time::ClockSnapshot, BufferAttr_HipcPointer>;
36
32public: 37public:
33 explicit StaticService(Core::System& system, 38 explicit StaticService(Core::System& system,
34 Service::PSC::Time::StaticServiceSetupInfo setup_info, 39 Service::PSC::Time::StaticServiceSetupInfo setup_info,
@@ -36,65 +41,34 @@ public:
36 41
37 ~StaticService() override = default; 42 ~StaticService() override = default;
38 43
39 Result GetStandardUserSystemClock( 44 Result GetStandardUserSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
40 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); 45 Result GetStandardNetworkSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
41 Result GetStandardNetworkSystemClock( 46 Result GetStandardSteadyClock(OutInterface<Service::PSC::Time::SteadyClock> out_service);
42 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); 47 Result GetTimeZoneService(OutInterface<TimeZoneService> out_service);
43 Result GetStandardSteadyClock(std::shared_ptr<Service::PSC::Time::SteadyClock>& out_service); 48 Result GetStandardLocalSystemClock(OutInterface<Service::PSC::Time::SystemClock> out_service);
44 Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service);
45 Result GetStandardLocalSystemClock(
46 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service);
47 Result GetEphemeralNetworkSystemClock( 49 Result GetEphemeralNetworkSystemClock(
48 std::shared_ptr<Service::PSC::Time::SystemClock>& out_service); 50 OutInterface<Service::PSC::Time::SystemClock> out_service);
49 Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory); 51 Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
50 Result SetStandardSteadyClockInternalOffset(s64 offset); 52 Result SetStandardSteadyClockInternalOffset(s64 offset_ns);
51 Result GetStandardSteadyClockRtcValue(s64& out_rtc_value); 53 Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
52 Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_automatic_correction); 54 Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
53 Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); 55 Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
54 Result GetStandardUserSystemClockInitialYear(s32& out_year); 56 Result GetStandardUserSystemClockInitialYear(Out<s32> out_year);
55 Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient); 57 Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
56 Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( 58 Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
57 Service::PSC::Time::SteadyClockTimePoint& out_time_point); 59 Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
58 Result CalculateMonotonicSystemClockBaseTimePoint( 60 Result CalculateMonotonicSystemClockBaseTimePoint(
59 s64& out_time, Service::PSC::Time::SystemClockContext& context); 61 Out<s64> out_time, Service::PSC::Time::SystemClockContext& context);
60 Result GetClockSnapshot(Service::PSC::Time::ClockSnapshot& out_snapshot, 62 Result GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type);
61 Service::PSC::Time::TimeType type);
62 Result GetClockSnapshotFromSystemClockContext( 63 Result GetClockSnapshotFromSystemClockContext(
63 Service::PSC::Time::ClockSnapshot& out_snapshot, 64 Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot,
64 Service::PSC::Time::SystemClockContext& user_context, 65 Service::PSC::Time::SystemClockContext& user_context,
65 Service::PSC::Time::SystemClockContext& network_context, Service::PSC::Time::TimeType type); 66 Service::PSC::Time::SystemClockContext& network_context);
66 Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, 67 Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
67 Service::PSC::Time::ClockSnapshot& a, 68 InClockSnapshot a, InClockSnapshot b);
68 Service::PSC::Time::ClockSnapshot& b); 69 Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b);
69 Result CalculateSpanBetween(s64& out_time, Service::PSC::Time::ClockSnapshot& a,
70 Service::PSC::Time::ClockSnapshot& b);
71 70
72private: 71private:
73 Result GetClockSnapshotImpl(Service::PSC::Time::ClockSnapshot& out_snapshot,
74 Service::PSC::Time::SystemClockContext& user_context,
75 Service::PSC::Time::SystemClockContext& network_context,
76 Service::PSC::Time::TimeType type);
77
78 void Handle_GetStandardUserSystemClock(HLERequestContext& ctx);
79 void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx);
80 void Handle_GetStandardSteadyClock(HLERequestContext& ctx);
81 void Handle_GetTimeZoneService(HLERequestContext& ctx);
82 void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx);
83 void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx);
84 void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx);
85 void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx);
86 void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx);
87 void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
88 void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
89 void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx);
90 void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
91 void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
92 void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
93 void Handle_GetClockSnapshot(HLERequestContext& ctx);
94 void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
95 void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
96 void Handle_CalculateSpanBetween(HLERequestContext& ctx);
97
98 Core::System& m_system; 72 Core::System& m_system;
99 73
100 std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; 74 std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp
index 503c327dd..5dc1187cb 100644
--- a/src/core/hle/service/glue/time/time_zone.cpp
+++ b/src/core/hle/service/glue/time/time_zone.cpp
@@ -3,8 +3,10 @@
3 3
4#include <chrono> 4#include <chrono>
5 5
6#include "common/scope_exit.h"
6#include "core/core.h" 7#include "core/core.h"
7#include "core/hle/kernel/svc.h" 8#include "core/hle/kernel/svc.h"
9#include "core/hle/service/cmif_serialization.h"
8#include "core/hle/service/glue/time/file_timestamp_worker.h" 10#include "core/hle/service/glue/time/file_timestamp_worker.h"
9#include "core/hle/service/glue/time/time_zone.h" 11#include "core/hle/service/glue/time/time_zone.h"
10#include "core/hle/service/glue/time/time_zone_binary.h" 12#include "core/hle/service/glue/time/time_zone_binary.h"
@@ -28,20 +30,20 @@ TimeZoneService::TimeZoneService(
28 m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} { 30 m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} {
29 // clang-format off 31 // clang-format off
30 static const FunctionInfo functions[] = { 32 static const FunctionInfo functions[] = {
31 {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"}, 33 {0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
32 {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"}, 34 {1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"},
33 {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"}, 35 {2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"},
34 {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"}, 36 {3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"},
35 {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"}, 37 {4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"},
36 {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"}, 38 {5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"},
37 {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"}, 39 {6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"},
38 {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"}, 40 {7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"},
39 {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"}, 41 {8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"},
40 {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"}, 42 {20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"},
41 {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"}, 43 {100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"},
42 {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, 44 {101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"},
43 {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"}, 45 {201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"},
44 {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, 46 {202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"},
45 }; 47 };
46 // clang-format on 48 // clang-format on
47 RegisterHandlers(functions); 49 RegisterHandlers(functions);
@@ -53,220 +55,16 @@ TimeZoneService::TimeZoneService(
53 55
54TimeZoneService::~TimeZoneService() = default; 56TimeZoneService::~TimeZoneService() = default;
55 57
56void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) { 58Result TimeZoneService::GetDeviceLocationName(
57 LOG_DEBUG(Service_Time, "called."); 59 Out<Service::PSC::Time::LocationName> out_location_name) {
58 60 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
59 Service::PSC::Time::LocationName name{};
60 auto res = GetDeviceLocationName(name);
61
62 IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)};
63 rb.Push(res);
64 rb.PushRaw<Service::PSC::Time::LocationName>(name);
65}
66
67void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
68 LOG_DEBUG(Service_Time, "called.");
69
70 IPC::RequestParser rp{ctx};
71 auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
72
73 auto res = SetDeviceLocation(name);
74
75 IPC::ResponseBuilder rb{ctx, 2};
76 rb.Push(res);
77}
78
79void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
80 LOG_DEBUG(Service_Time, "called.");
81
82 u32 count{};
83 auto res = GetTotalLocationNameCount(count);
84
85 IPC::ResponseBuilder rb{ctx, 3};
86 rb.Push(res);
87 rb.Push(count);
88}
89
90void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
91 LOG_DEBUG(Service_Time, "called.");
92
93 IPC::RequestParser rp{ctx};
94 auto index{rp.Pop<u32>()};
95
96 auto max_names{ctx.GetWriteBufferSize() / sizeof(Service::PSC::Time::LocationName)};
97
98 std::vector<Service::PSC::Time::LocationName> names{};
99 u32 count{};
100 auto res = LoadLocationNameList(count, names, max_names, index);
101
102 ctx.WriteBuffer(names);
103
104 IPC::ResponseBuilder rb{ctx, 3};
105 rb.Push(res);
106 rb.Push(count);
107}
108
109void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) {
110 LOG_DEBUG(Service_Time, "called.");
111
112 IPC::RequestParser rp{ctx};
113 auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
114
115 Tz::Rule rule{};
116 auto res = LoadTimeZoneRule(rule, name);
117
118 ctx.WriteBuffer(rule);
119
120 IPC::ResponseBuilder rb{ctx, 2};
121 rb.Push(res);
122}
123
124void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) {
125 LOG_DEBUG(Service_Time, "called.");
126
127 Service::PSC::Time::RuleVersion rule_version{};
128 auto res = GetTimeZoneRuleVersion(rule_version);
129
130 IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::RuleVersion) / sizeof(u32)};
131 rb.Push(res);
132 rb.PushRaw<Service::PSC::Time::RuleVersion>(rule_version);
133}
134
135void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) {
136 LOG_DEBUG(Service_Time, "called.");
137
138 Service::PSC::Time::LocationName name{};
139 Service::PSC::Time::SteadyClockTimePoint time_point{};
140 auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name);
141
142 IPC::ResponseBuilder rb{ctx,
143 2 + (sizeof(Service::PSC::Time::LocationName) / sizeof(u32)) +
144 (sizeof(Service::PSC::Time::SteadyClockTimePoint) / sizeof(u32))};
145 rb.Push(res);
146 rb.PushRaw<Service::PSC::Time::LocationName>(name);
147 rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
148}
149
150void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) {
151 LOG_DEBUG(Service_Time, "called.");
152
153 auto res = SetDeviceLocationNameWithTimeZoneRule();
154
155 IPC::ResponseBuilder rb{ctx, 2};
156 rb.Push(res);
157}
158
159void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) {
160 LOG_DEBUG(Service_Time, "called.");
161
162 IPC::ResponseBuilder rb{ctx, 2};
163 rb.Push(Service::PSC::Time::ResultNotImplemented);
164}
165
166void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle(
167 HLERequestContext& ctx) {
168 LOG_DEBUG(Service_Time, "called.");
169
170 Kernel::KEvent* event{};
171 auto res = GetDeviceLocationNameOperationEventReadableHandle(&event);
172
173 IPC::ResponseBuilder rb{ctx, 2, 1};
174 rb.Push(res);
175 rb.PushCopyObjects(event->GetReadableEvent());
176}
177
178void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) {
179 LOG_DEBUG(Service_Time, "called.");
180
181 IPC::RequestParser rp{ctx};
182 auto time{rp.Pop<s64>()};
183
184 auto rule_buffer{ctx.ReadBuffer()};
185 Tz::Rule rule{};
186 std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule));
187
188 Service::PSC::Time::CalendarTime calendar_time{};
189 Service::PSC::Time::CalendarAdditionalInfo additional_info{};
190 auto res = ToCalendarTime(calendar_time, additional_info, time, rule);
191
192 IPC::ResponseBuilder rb{ctx,
193 2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) +
194 (sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))};
195 rb.Push(res);
196 rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time);
197 rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info);
198}
199
200void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
201 IPC::RequestParser rp{ctx};
202 auto time{rp.Pop<s64>()};
203
204 LOG_DEBUG(Service_Time, "called. time={}", time);
205
206 Service::PSC::Time::CalendarTime calendar_time{};
207 Service::PSC::Time::CalendarAdditionalInfo additional_info{};
208 auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time);
209
210 IPC::ResponseBuilder rb{ctx,
211 2 + (sizeof(Service::PSC::Time::CalendarTime) / sizeof(u32)) +
212 (sizeof(Service::PSC::Time::CalendarAdditionalInfo) / sizeof(u32))};
213 rb.Push(res);
214 rb.PushRaw<Service::PSC::Time::CalendarTime>(calendar_time);
215 rb.PushRaw<Service::PSC::Time::CalendarAdditionalInfo>(additional_info);
216}
217
218void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) {
219 IPC::RequestParser rp{ctx};
220 auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()};
221
222 LOG_DEBUG(Service_Time, "called. calendar year {} month {} day {} hour {} minute {} second {}",
223 calendar.year, calendar.month, calendar.day, calendar.hour, calendar.minute,
224 calendar.second);
225
226 auto binary{ctx.ReadBuffer()};
227
228 Tz::Rule rule{};
229 std::memcpy(&rule, binary.data(), sizeof(Tz::Rule));
230
231 u32 count{};
232 std::array<s64, 2> times{};
233 u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
234
235 auto res = ToPosixTime(count, times, times_count, calendar, rule);
236
237 ctx.WriteBuffer(times);
238
239 IPC::ResponseBuilder rb{ctx, 3};
240 rb.Push(res);
241 rb.Push(count);
242}
243
244void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) {
245 LOG_DEBUG(Service_Time, "called.");
246
247 IPC::RequestParser rp{ctx};
248 auto calendar{rp.PopRaw<Service::PSC::Time::CalendarTime>()};
249
250 u32 count{};
251 std::array<s64, 2> times{};
252 u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
253
254 auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar);
255
256 ctx.WriteBuffer(times);
257
258 IPC::ResponseBuilder rb{ctx, 3};
259 rb.Push(res);
260 rb.Push(count);
261}
262 61
263// =============================== Implementations ===========================
264
265Result TimeZoneService::GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name) {
266 R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name)); 62 R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name));
267} 63}
268 64
269Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& location_name) { 65Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName& location_name) {
66 LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
67
270 R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); 68 R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
271 R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound); 69 R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound);
272 70
@@ -282,7 +80,7 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca
282 80
283 Service::PSC::Time::SteadyClockTimePoint time_point{}; 81 Service::PSC::Time::SteadyClockTimePoint time_point{};
284 Service::PSC::Time::LocationName name{}; 82 Service::PSC::Time::LocationName name{};
285 R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(time_point, name)); 83 R_TRY(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(&name, &time_point));
286 84
287 m_set_sys->SetDeviceTimeZoneLocationName(name); 85 m_set_sys->SetDeviceTimeZoneLocationName(name);
288 m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point); 86 m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point);
@@ -294,19 +92,27 @@ Result TimeZoneService::SetDeviceLocation(Service::PSC::Time::LocationName& loca
294 R_SUCCEED(); 92 R_SUCCEED();
295} 93}
296 94
297Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) { 95Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
96 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
97
298 R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count)); 98 R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count));
299} 99}
300 100
301Result TimeZoneService::LoadLocationNameList( 101Result TimeZoneService::LoadLocationNameList(
302 u32& out_count, std::vector<Service::PSC::Time::LocationName>& out_names, size_t max_names, 102 Out<u32> out_count,
303 u32 index) { 103 OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
104 SCOPE_EXIT({
105 LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}",
106 index, *out_count, out_names[0], out_names[1]);
107 });
108
304 std::scoped_lock l{m_mutex}; 109 std::scoped_lock l{m_mutex};
305 R_RETURN(GetTimeZoneLocationList(out_count, out_names, max_names, index)); 110 R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index));
306} 111}
307 112
308Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule, 113Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& name) {
309 Service::PSC::Time::LocationName& name) { 114 LOG_DEBUG(Service_Time, "called. name={}", name);
115
310 std::scoped_lock l{m_mutex}; 116 std::scoped_lock l{m_mutex};
311 std::span<const u8> binary{}; 117 std::span<const u8> binary{};
312 size_t binary_size{}; 118 size_t binary_size{};
@@ -314,23 +120,43 @@ Result TimeZoneService::LoadTimeZoneRule(Tz::Rule& out_rule,
314 R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary)); 120 R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
315} 121}
316 122
317Result TimeZoneService::GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version) { 123Result TimeZoneService::GetTimeZoneRuleVersion(
124 Out<Service::PSC::Time::RuleVersion> out_rule_version) {
125 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
126
318 R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version)); 127 R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version));
319} 128}
320 129
321Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( 130Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
322 Service::PSC::Time::SteadyClockTimePoint& out_time_point, 131 Out<Service::PSC::Time::LocationName> location_name,
323 Service::PSC::Time::LocationName& location_name) { 132 Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
324 R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(out_time_point, location_name)); 133 SCOPE_EXIT({
134 LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name,
135 *out_time_point);
136 });
137
138 R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point));
325} 139}
326 140
327Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule() { 141Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
142 Service::PSC::Time::LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) {
143 LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
144
328 R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); 145 R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
329 R_RETURN(Service::PSC::Time::ResultNotImplemented); 146 R_RETURN(Service::PSC::Time::ResultNotImplemented);
330} 147}
331 148
149Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule,
150 InBuffer<BufferAttr_HipcAutoSelect> binary) {
151 LOG_DEBUG(Service_Time, "called.");
152
153 R_RETURN(Service::PSC::Time::ResultNotImplemented);
154}
155
332Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( 156Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
333 Kernel::KEvent** out_event) { 157 OutCopyHandle<Kernel::KReadableEvent> out_event) {
158 LOG_DEBUG(Service_Time, "called.");
159
334 if (!operation_event_initialized) { 160 if (!operation_event_initialized) {
335 operation_event_initialized = false; 161 operation_event_initialized = false;
336 162
@@ -342,34 +168,59 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
342 g_list_nodes.push_back(m_operation_event); 168 g_list_nodes.push_back(m_operation_event);
343 } 169 }
344 170
345 *out_event = m_operation_event.m_event; 171 *out_event = &m_operation_event.m_event->GetReadableEvent();
346 R_SUCCEED(); 172 R_SUCCEED();
347} 173}
348 174
349Result TimeZoneService::ToCalendarTime( 175Result TimeZoneService::ToCalendarTime(
350 Service::PSC::Time::CalendarTime& out_calendar_time, 176 Out<Service::PSC::Time::CalendarTime> out_calendar_time,
351 Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule) { 177 Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) {
178 SCOPE_EXIT({
179 LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
180 *out_calendar_time, *out_additional_info);
181 });
182
352 R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule)); 183 R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
353} 184}
354 185
355Result TimeZoneService::ToCalendarTimeWithMyRule( 186Result TimeZoneService::ToCalendarTimeWithMyRule(
356 Service::PSC::Time::CalendarTime& out_calendar_time, 187 Out<Service::PSC::Time::CalendarTime> out_calendar_time,
357 Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time) { 188 Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) {
189 SCOPE_EXIT({
190 LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
191 *out_calendar_time, *out_additional_info);
192 });
193
358 R_RETURN( 194 R_RETURN(
359 m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); 195 m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
360} 196}
361 197
362Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, 198Result TimeZoneService::ToPosixTime(Out<u32> out_count,
363 u32 out_times_count, 199 OutArray<s64, BufferAttr_HipcPointer> out_times,
364 Service::PSC::Time::CalendarTime& calendar_time, 200 Out<u32> out_times_count,
365 Tz::Rule& rule) { 201 Service::PSC::Time::CalendarTime& calendar_time, InRule rule) {
202 SCOPE_EXIT({
203 LOG_DEBUG(Service_Time,
204 "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
205 "out_times_count={}",
206 calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
207 });
208
366 R_RETURN( 209 R_RETURN(
367 m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule)); 210 m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
368} 211}
369 212
370Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, 213Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
371 u32 out_times_count, 214 OutArray<s64, BufferAttr_HipcPointer> out_times,
215 Out<u32> out_times_count,
372 Service::PSC::Time::CalendarTime& calendar_time) { 216 Service::PSC::Time::CalendarTime& calendar_time) {
217 SCOPE_EXIT({
218 LOG_DEBUG(Service_Time,
219 "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
220 "out_times_count={}",
221 calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
222 });
223
373 R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count, 224 R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count,
374 calendar_time)); 225 calendar_time));
375} 226}
diff --git a/src/core/hle/service/glue/time/time_zone.h b/src/core/hle/service/glue/time/time_zone.h
index 3c8ae4bf8..bf12adbdc 100644
--- a/src/core/hle/service/glue/time/time_zone.h
+++ b/src/core/hle/service/glue/time/time_zone.h
@@ -8,6 +8,7 @@
8#include <span> 8#include <span>
9#include <vector> 9#include <vector>
10 10
11#include "core/hle/service/cmif_types.h"
11#include "core/hle/service/ipc_helpers.h" 12#include "core/hle/service/ipc_helpers.h"
12#include "core/hle/service/psc/time/common.h" 13#include "core/hle/service/psc/time/common.h"
13#include "core/hle/service/server_manager.h" 14#include "core/hle/service/server_manager.h"
@@ -33,6 +34,9 @@ namespace Service::Glue::Time {
33class FileTimestampWorker; 34class FileTimestampWorker;
34 35
35class TimeZoneService final : public ServiceFramework<TimeZoneService> { 36class TimeZoneService final : public ServiceFramework<TimeZoneService> {
37 using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
38 using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
39
36public: 40public:
37 explicit TimeZoneService( 41 explicit TimeZoneService(
38 Core::System& system, FileTimestampWorker& file_timestamp_worker, 42 Core::System& system, FileTimestampWorker& file_timestamp_worker,
@@ -41,46 +45,37 @@ public:
41 45
42 ~TimeZoneService() override; 46 ~TimeZoneService() override;
43 47
44 Result GetDeviceLocationName(Service::PSC::Time::LocationName& out_location_name); 48 Result GetDeviceLocationName(Out<Service::PSC::Time::LocationName> out_location_name);
45 Result SetDeviceLocation(Service::PSC::Time::LocationName& location_name); 49 Result SetDeviceLocationName(Service::PSC::Time::LocationName& location_name);
46 Result GetTotalLocationNameCount(u32& out_count); 50 Result GetTotalLocationNameCount(Out<u32> out_count);
47 Result LoadLocationNameList(u32& out_count, 51 Result LoadLocationNameList(
48 std::vector<Service::PSC::Time::LocationName>& out_names, 52 Out<u32> out_count,
49 size_t max_names, u32 index); 53 OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index);
50 Result LoadTimeZoneRule(Tz::Rule& out_rule, Service::PSC::Time::LocationName& name); 54 Result LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& location_name);
51 Result GetTimeZoneRuleVersion(Service::PSC::Time::RuleVersion& out_rule_version); 55 Result GetTimeZoneRuleVersion(Out<Service::PSC::Time::RuleVersion> out_rule_version);
52 Result GetDeviceLocationNameAndUpdatedTime( 56 Result GetDeviceLocationNameAndUpdatedTime(
53 Service::PSC::Time::SteadyClockTimePoint& out_time_point, 57 Out<Service::PSC::Time::LocationName> location_name,
54 Service::PSC::Time::LocationName& location_name); 58 Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
55 Result SetDeviceLocationNameWithTimeZoneRule(); 59 Result SetDeviceLocationNameWithTimeZoneRule(Service::PSC::Time::LocationName& location_name,
56 Result GetDeviceLocationNameOperationEventReadableHandle(Kernel::KEvent** out_event); 60 InBuffer<BufferAttr_HipcAutoSelect> binary);
57 Result ToCalendarTime(Service::PSC::Time::CalendarTime& out_calendar_time, 61 Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary);
58 Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, s64 time, 62 Result GetDeviceLocationNameOperationEventReadableHandle(
59 Tz::Rule& rule); 63 OutCopyHandle<Kernel::KReadableEvent> out_event);
60 Result ToCalendarTimeWithMyRule(Service::PSC::Time::CalendarTime& out_calendar_time, 64 Result ToCalendarTime(Out<Service::PSC::Time::CalendarTime> out_calendar_time,
61 Service::PSC::Time::CalendarAdditionalInfo& out_additional_info, 65 Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info,
62 s64 time); 66 s64 time, InRule rule);
63 Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 67 Result ToCalendarTimeWithMyRule(
64 Service::PSC::Time::CalendarTime& calendar_time, Tz::Rule& rule); 68 Out<Service::PSC::Time::CalendarTime> out_calendar_time,
65 Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 69 Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time);
70 Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
71 Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time,
72 InRule rule);
73 Result ToPosixTimeWithMyRule(Out<u32> out_count,
74 OutArray<s64, BufferAttr_HipcPointer> out_times,
75 Out<u32> out_times_count,
66 Service::PSC::Time::CalendarTime& calendar_time); 76 Service::PSC::Time::CalendarTime& calendar_time);
67 77
68private: 78private:
69 void Handle_GetDeviceLocationName(HLERequestContext& ctx);
70 void Handle_SetDeviceLocationName(HLERequestContext& ctx);
71 void Handle_GetTotalLocationNameCount(HLERequestContext& ctx);
72 void Handle_LoadLocationNameList(HLERequestContext& ctx);
73 void Handle_LoadTimeZoneRule(HLERequestContext& ctx);
74 void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx);
75 void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx);
76 void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx);
77 void Handle_ParseTimeZoneBinary(HLERequestContext& ctx);
78 void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx);
79 void Handle_ToCalendarTime(HLERequestContext& ctx);
80 void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx);
81 void Handle_ToPosixTime(HLERequestContext& ctx);
82 void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx);
83
84 Core::System& m_system; 79 Core::System& m_system;
85 std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; 80 std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
86 81
diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp
index d33f784c0..cc50b6b7b 100644
--- a/src/core/hle/service/glue/time/time_zone_binary.cpp
+++ b/src/core/hle/service/glue/time/time_zone_binary.cpp
@@ -103,7 +103,7 @@ void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName
103 return; 103 return;
104 } 104 }
105 // out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name); 105 // out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name);
106 out_path = fmt::format("/zoneinfo/{}", name.name.data()); 106 out_path = fmt::format("/zoneinfo/{}", name.data());
107} 107}
108 108
109bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) { 109bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) {
@@ -169,7 +169,7 @@ Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
169} 169}
170 170
171Result GetTimeZoneLocationList(u32& out_count, 171Result GetTimeZoneLocationList(u32& out_count,
172 std::vector<Service::PSC::Time::LocationName>& out_names, 172 std::span<Service::PSC::Time::LocationName> out_names,
173 size_t max_names, u32 index) { 173 size_t max_names, u32 index) {
174 std::string path{}; 174 std::string path{};
175 GetTimeZoneBinaryListPath(path); 175 GetTimeZoneBinaryListPath(path);
@@ -193,7 +193,7 @@ Result GetTimeZoneLocationList(u32& out_count,
193 193
194 if (chr == '\n') { 194 if (chr == '\n') {
195 if (name_count >= index) { 195 if (name_count >= index) {
196 out_names.push_back(current_name); 196 out_names[out_count] = current_name;
197 out_count++; 197 out_count++;
198 if (out_count >= max_names) { 198 if (out_count >= max_names) {
199 break; 199 break;
@@ -209,10 +209,9 @@ Result GetTimeZoneLocationList(u32& out_count,
209 break; 209 break;
210 } 210 }
211 211
212 R_UNLESS(current_name_len <= current_name.name.size() - 2, 212 R_UNLESS(current_name_len <= current_name.size() - 2, Service::PSC::Time::ResultFailed);
213 Service::PSC::Time::ResultFailed);
214 213
215 current_name.name[current_name_len++] = chr; 214 current_name[current_name_len++] = chr;
216 } 215 }
217 216
218 R_SUCCEED(); 217 R_SUCCEED();
diff --git a/src/core/hle/service/glue/time/time_zone_binary.h b/src/core/hle/service/glue/time/time_zone_binary.h
index 2cad6b458..461f4577e 100644
--- a/src/core/hle/service/glue/time/time_zone_binary.h
+++ b/src/core/hle/service/glue/time/time_zone_binary.h
@@ -26,7 +26,7 @@ Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version);
26Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, 26Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
27 Service::PSC::Time::LocationName& name); 27 Service::PSC::Time::LocationName& name);
28Result GetTimeZoneLocationList(u32& out_count, 28Result GetTimeZoneLocationList(u32& out_count,
29 std::vector<Service::PSC::Time::LocationName>& out_names, 29 std::span<Service::PSC::Time::LocationName> out_names,
30 size_t max_names, u32 index); 30 size_t max_names, u32 index);
31 31
32} // namespace Service::Glue::Time 32} // namespace Service::Glue::Time
diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp
index ea0e49b90..f44f3077e 100644
--- a/src/core/hle/service/glue/time/worker.cpp
+++ b/src/core/hle/service/glue/time/worker.cpp
@@ -38,11 +38,12 @@ T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set
38 38
39TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, 39TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
40 FileTimestampWorker& file_timestamp_worker) 40 FileTimestampWorker& file_timestamp_worker)
41 : m_system{system}, m_ctx{m_system, "Glue:58"}, m_event{m_ctx.CreateEvent("Glue:58:Event")}, 41 : m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent(
42 "Glue:TimeWorker:Event")},
42 m_steady_clock_resource{steady_clock_resource}, 43 m_steady_clock_resource{steady_clock_resource},
43 m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent( 44 m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent(
44 "Glue:58:SteadyClockTimerEvent")}, 45 "Glue:TimeWorker:SteadyClockTimerEvent")},
45 m_timer_file_system{m_ctx.CreateEvent("Glue:58:FileTimeTimerEvent")}, 46 m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
46 m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} { 47 m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
47 g_ig_report_network_clock_context_set = false; 48 g_ig_report_network_clock_context_set = false;
48 g_report_network_clock_context = {}; 49 g_report_network_clock_context = {};
@@ -113,17 +114,17 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t
113 std::chrono::nanoseconds(fs_notify_time_ns), 114 std::chrono::nanoseconds(fs_notify_time_ns),
114 m_timer_file_system_timing_event); 115 m_timer_file_system_timing_event);
115 116
116 auto res = m_time_sm->GetStandardLocalSystemClock(m_local_clock); 117 auto res = m_time_sm->GetStandardLocalSystemClock(&m_local_clock);
117 ASSERT(res == ResultSuccess); 118 ASSERT(res == ResultSuccess);
118 res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event); 119 res = m_time_m->GetStandardLocalClockOperationEvent(&m_local_clock_event);
119 ASSERT(res == ResultSuccess); 120 ASSERT(res == ResultSuccess);
120 121
121 res = m_time_sm->GetStandardNetworkSystemClock(m_network_clock); 122 res = m_time_sm->GetStandardNetworkSystemClock(&m_network_clock);
122 ASSERT(res == ResultSuccess); 123 ASSERT(res == ResultSuccess);
123 res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event); 124 res = m_time_m->GetStandardNetworkClockOperationEventForServiceManager(&m_network_clock_event);
124 ASSERT(res == ResultSuccess); 125 ASSERT(res == ResultSuccess);
125 126
126 res = m_time_sm->GetEphemeralNetworkSystemClock(m_ephemeral_clock); 127 res = m_time_sm->GetEphemeralNetworkSystemClock(&m_ephemeral_clock);
127 ASSERT(res == ResultSuccess); 128 ASSERT(res == ResultSuccess);
128 res = 129 res =
129 m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event); 130 m_time_m->GetEphemeralNetworkClockOperationEventForServiceManager(&m_ephemeral_clock_event);
@@ -183,22 +184,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
183 AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); 184 AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
184 // TODO 185 // TODO
185 // AddWaiter(gIPmModuleService::GetEvent(), 1); 186 // AddWaiter(gIPmModuleService::GetEvent(), 1);
186 AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange); 187 AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange);
187 } else { 188 } else {
188 AddWaiter(&m_event->GetReadableEvent(), EventType::Exit); 189 AddWaiter(&m_event->GetReadableEvent(), EventType::Exit);
189 // TODO 190 // TODO
190 // AddWaiter(gIPmModuleService::GetEvent(), 1); 191 // AddWaiter(gIPmModuleService::GetEvent(), 1);
191 AddWaiter(&m_alarm_worker.GetEvent().GetReadableEvent(), EventType::PowerStateChange); 192 AddWaiter(&m_alarm_worker.GetEvent(), EventType::PowerStateChange);
192 AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms); 193 AddWaiter(&m_alarm_worker.GetTimerEvent().GetReadableEvent(), EventType::SignalAlarms);
193 AddWaiter(&m_local_clock_event->GetReadableEvent(), EventType::UpdateLocalSystemClock); 194 AddWaiter(m_local_clock_event, EventType::UpdateLocalSystemClock);
194 AddWaiter(&m_network_clock_event->GetReadableEvent(), 195 AddWaiter(m_network_clock_event, EventType::UpdateNetworkSystemClock);
195 EventType::UpdateNetworkSystemClock); 196 AddWaiter(m_ephemeral_clock_event, EventType::UpdateEphemeralSystemClock);
196 AddWaiter(&m_ephemeral_clock_event->GetReadableEvent(),
197 EventType::UpdateEphemeralSystemClock);
198 AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock); 197 AddWaiter(&m_timer_steady_clock->GetReadableEvent(), EventType::UpdateSteadyClock);
199 AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp); 198 AddWaiter(&m_timer_file_system->GetReadableEvent(), EventType::UpdateFileTimestamp);
200 AddWaiter(&m_standard_user_auto_correct_clock_event->GetReadableEvent(), 199 AddWaiter(m_standard_user_auto_correct_clock_event, EventType::AutoCorrect);
201 EventType::AutoCorrect);
202 } 200 }
203 201
204 s32 out_index{-1}; 202 s32 out_index{-1};
@@ -237,7 +235,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
237 m_local_clock_event->Clear(); 235 m_local_clock_event->Clear();
238 236
239 Service::PSC::Time::SystemClockContext context{}; 237 Service::PSC::Time::SystemClockContext context{};
240 auto res = m_local_clock->GetSystemClockContext(context); 238 auto res = m_local_clock->GetSystemClockContext(&context);
241 ASSERT(res == ResultSuccess); 239 ASSERT(res == ResultSuccess);
242 240
243 m_set_sys->SetUserSystemClockContext(context); 241 m_set_sys->SetUserSystemClockContext(context);
@@ -248,12 +246,12 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
248 case EventType::UpdateNetworkSystemClock: { 246 case EventType::UpdateNetworkSystemClock: {
249 m_network_clock_event->Clear(); 247 m_network_clock_event->Clear();
250 Service::PSC::Time::SystemClockContext context{}; 248 Service::PSC::Time::SystemClockContext context{};
251 auto res = m_network_clock->GetSystemClockContext(context); 249 auto res = m_network_clock->GetSystemClockContext(&context);
252 ASSERT(res == ResultSuccess); 250 ASSERT(res == ResultSuccess);
253 m_set_sys->SetNetworkSystemClockContext(context); 251 m_set_sys->SetNetworkSystemClockContext(context);
254 252
255 s64 time{}; 253 s64 time{};
256 if (m_network_clock->GetCurrentTime(time) != ResultSuccess) { 254 if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) {
257 break; 255 break;
258 } 256 }
259 257
@@ -275,13 +273,13 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
275 m_ephemeral_clock_event->Clear(); 273 m_ephemeral_clock_event->Clear();
276 274
277 Service::PSC::Time::SystemClockContext context{}; 275 Service::PSC::Time::SystemClockContext context{};
278 auto res = m_ephemeral_clock->GetSystemClockContext(context); 276 auto res = m_ephemeral_clock->GetSystemClockContext(&context);
279 if (res != ResultSuccess) { 277 if (res != ResultSuccess) {
280 break; 278 break;
281 } 279 }
282 280
283 s64 time{}; 281 s64 time{};
284 res = m_ephemeral_clock->GetCurrentTime(time); 282 res = m_ephemeral_clock->GetCurrentTime(&time);
285 if (res != ResultSuccess) { 283 if (res != ResultSuccess) {
286 break; 284 break;
287 } 285 }
@@ -317,11 +315,11 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
317 315
318 bool automatic_correction{}; 316 bool automatic_correction{};
319 auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( 317 auto res = m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled(
320 automatic_correction); 318 &automatic_correction);
321 ASSERT(res == ResultSuccess); 319 ASSERT(res == ResultSuccess);
322 320
323 Service::PSC::Time::SteadyClockTimePoint time_point{}; 321 Service::PSC::Time::SteadyClockTimePoint time_point{};
324 res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); 322 res = m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point);
325 ASSERT(res == ResultSuccess); 323 ASSERT(res == ResultSuccess);
326 324
327 m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction); 325 m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
diff --git a/src/core/hle/service/glue/time/worker.h b/src/core/hle/service/glue/time/worker.h
index adbbe6b6d..75e5c4d0f 100644
--- a/src/core/hle/service/glue/time/worker.h
+++ b/src/core/hle/service/glue/time/worker.h
@@ -49,10 +49,10 @@ private:
49 std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock; 49 std::shared_ptr<Service::PSC::Time::SystemClock> m_ephemeral_clock;
50 StandardSteadyClockResource& m_steady_clock_resource; 50 StandardSteadyClockResource& m_steady_clock_resource;
51 FileTimestampWorker& m_file_timestamp_worker; 51 FileTimestampWorker& m_file_timestamp_worker;
52 Kernel::KEvent* m_local_clock_event{}; 52 Kernel::KReadableEvent* m_local_clock_event{};
53 Kernel::KEvent* m_network_clock_event{}; 53 Kernel::KReadableEvent* m_network_clock_event{};
54 Kernel::KEvent* m_ephemeral_clock_event{}; 54 Kernel::KReadableEvent* m_ephemeral_clock_event{};
55 Kernel::KEvent* m_standard_user_auto_correct_clock_event{}; 55 Kernel::KReadableEvent* m_standard_user_auto_correct_clock_event{};
56 Kernel::KEvent* m_timer_steady_clock{}; 56 Kernel::KEvent* m_timer_steady_clock{};
57 std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event; 57 std::shared_ptr<Core::Timing::EventType> m_timer_steady_clock_timing_event;
58 Kernel::KEvent* m_timer_file_system{}; 58 Kernel::KEvent* m_timer_file_system{};
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 1e2d2d212..28e3000bd 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -1405,7 +1405,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
1405 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); 1405 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
1406 1406
1407 std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{}; 1407 std::shared_ptr<Service::Glue::Time::TimeZoneService> timezone_service{};
1408 static_service->GetTimeZoneService(timezone_service); 1408 static_service->GetTimeZoneService(&timezone_service);
1409 1409
1410 Service::PSC::Time::CalendarTime calendar_time{}; 1410 Service::PSC::Time::CalendarTime calendar_time{};
1411 Service::PSC::Time::CalendarAdditionalInfo additional_info{}; 1411 Service::PSC::Time::CalendarAdditionalInfo additional_info{};
@@ -1416,7 +1416,7 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
1416 amiibo_date.SetMonth(1); 1416 amiibo_date.SetMonth(1);
1417 amiibo_date.SetDay(1); 1417 amiibo_date.SetDay(1);
1418 1418
1419 if (timezone_service->ToCalendarTimeWithMyRule(calendar_time, additional_info, posix_time) == 1419 if (timezone_service->ToCalendarTimeWithMyRule(&calendar_time, &additional_info, posix_time) ==
1420 ResultSuccess) { 1420 ResultSuccess) {
1421 amiibo_date.SetYear(calendar_time.year); 1421 amiibo_date.SetYear(calendar_time.year);
1422 amiibo_date.SetMonth(calendar_time.month); 1422 amiibo_date.SetMonth(calendar_time.month);
@@ -1431,10 +1431,10 @@ s64 NfcDevice::GetCurrentPosixTime() const {
1431 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); 1431 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
1432 1432
1433 std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; 1433 std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
1434 static_service->GetStandardSteadyClock(steady_clock); 1434 static_service->GetStandardSteadyClock(&steady_clock);
1435 1435
1436 Service::PSC::Time::SteadyClockTimePoint time_point{}; 1436 Service::PSC::Time::SteadyClockTimePoint time_point{};
1437 R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); 1437 R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
1438 return time_point.time_point; 1438 return time_point.time_point;
1439} 1439}
1440 1440
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp
index b60699c45..94a8243b5 100644
--- a/src/core/hle/service/nfc/common/device_manager.cpp
+++ b/src/core/hle/service/nfc/common/device_manager.cpp
@@ -91,10 +91,10 @@ Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max
91 true); 91 true);
92 92
93 std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; 93 std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
94 static_service->GetStandardSteadyClock(steady_clock); 94 static_service->GetStandardSteadyClock(&steady_clock);
95 95
96 Service::PSC::Time::SteadyClockTimePoint time_point{}; 96 Service::PSC::Time::SteadyClockTimePoint time_point{};
97 R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); 97 R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
98 98
99 const s64 elapsed_time = time_point.time_point - time_since_last_error; 99 const s64 elapsed_time = time_point.time_point - time_since_last_error;
100 if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) { 100 if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) {
@@ -754,10 +754,10 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
754 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true); 754 system.ServiceManager().GetService<Service::Glue::Time::StaticService>("time:u", true);
755 755
756 std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{}; 756 std::shared_ptr<Service::PSC::Time::SteadyClock> steady_clock{};
757 static_service->GetStandardSteadyClock(steady_clock); 757 static_service->GetStandardSteadyClock(&steady_clock);
758 758
759 Service::PSC::Time::SteadyClockTimePoint time_point{}; 759 Service::PSC::Time::SteadyClockTimePoint time_point{};
760 R_ASSERT(steady_clock->GetCurrentTimePoint(time_point)); 760 R_ASSERT(steady_clock->GetCurrentTimePoint(&time_point));
761 761
762 time_since_last_error = time_point.time_point; 762 time_since_last_error = time_point.time_point;
763 } 763 }
diff --git a/src/core/hle/service/psc/time/common.h b/src/core/hle/service/psc/time/common.h
index d17b31143..596828b8b 100644
--- a/src/core/hle/service/psc/time/common.h
+++ b/src/core/hle/service/psc/time/common.h
@@ -5,6 +5,7 @@
5 5
6#include <array> 6#include <array>
7#include <chrono> 7#include <chrono>
8#include <fmt/format.h>
8 9
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "common/intrusive_list.h" 11#include "common/intrusive_list.h"
@@ -21,8 +22,14 @@ class System;
21namespace Service::PSC::Time { 22namespace Service::PSC::Time {
22using ClockSourceId = Common::UUID; 23using ClockSourceId = Common::UUID;
23 24
25enum class TimeType : u8 {
26 UserSystemClock = 0,
27 NetworkSystemClock = 1,
28 LocalSystemClock = 2,
29};
30
24struct SteadyClockTimePoint { 31struct SteadyClockTimePoint {
25 constexpr bool IdMatches(SteadyClockTimePoint& other) { 32 constexpr bool IdMatches(const SteadyClockTimePoint& other) const {
26 return clock_source_id == other.clock_source_id; 33 return clock_source_id == other.clock_source_id;
27 } 34 }
28 bool operator==(const SteadyClockTimePoint& other) const = default; 35 bool operator==(const SteadyClockTimePoint& other) const = default;
@@ -42,12 +49,6 @@ struct SystemClockContext {
42static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!"); 49static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!");
43static_assert(std::is_trivial_v<SystemClockContext>); 50static_assert(std::is_trivial_v<SystemClockContext>);
44 51
45enum class TimeType : u8 {
46 UserSystemClock,
47 NetworkSystemClock,
48 LocalSystemClock,
49};
50
51struct CalendarTime { 52struct CalendarTime {
52 s16 year; 53 s16 year;
53 s8 month; 54 s8 month;
@@ -67,14 +68,10 @@ struct CalendarAdditionalInfo {
67}; 68};
68static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!"); 69static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!");
69 70
70struct LocationName { 71using LocationName = std::array<char, 0x24>;
71 std::array<char, 36> name;
72};
73static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!"); 72static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!");
74 73
75struct RuleVersion { 74using RuleVersion = std::array<char, 0x10>;
76 std::array<char, 16> version;
77};
78static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!"); 75static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!");
79 76
80struct ClockSnapshot { 77struct ClockSnapshot {
@@ -152,8 +149,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) {
152 return std::chrono::nanoseconds(a + b); 149 return std::chrono::nanoseconds(a + b);
153} 150}
154 151
155constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTimePoint& a, 152constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyClockTimePoint& a,
156 SteadyClockTimePoint& b) { 153 const SteadyClockTimePoint& b) {
157 R_UNLESS(out_seconds, ResultInvalidArgument); 154 R_UNLESS(out_seconds, ResultInvalidArgument);
158 R_UNLESS(a.IdMatches(b), ResultInvalidArgument); 155 R_UNLESS(a.IdMatches(b), ResultInvalidArgument);
159 R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(), 156 R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(),
@@ -166,3 +163,111 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTi
166} 163}
167 164
168} // namespace Service::PSC::Time 165} // namespace Service::PSC::Time
166
167template <>
168struct fmt::formatter<Service::PSC::Time::TimeType> : fmt::formatter<fmt::string_view> {
169 template <typename FormatContext>
170 auto format(Service::PSC::Time::TimeType type, FormatContext& ctx) {
171 const string_view name = [type] {
172 using Service::PSC::Time::TimeType;
173 switch (type) {
174 case TimeType::UserSystemClock:
175 return "UserSystemClock";
176 case TimeType::NetworkSystemClock:
177 return "NetworkSystemClock";
178 case TimeType::LocalSystemClock:
179 return "LocalSystemClock";
180 }
181 return "Invalid";
182 }();
183 return formatter<string_view>::format(name, ctx);
184 }
185};
186
187template <>
188struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter<fmt::string_view> {
189 template <typename FormatContext>
190 auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point,
191 FormatContext& ctx) const {
192 return fmt::format_to(ctx.out(), "time_point={}", time_point.time_point);
193 }
194};
195
196template <>
197struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> {
198 template <typename FormatContext>
199 auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const {
200 return fmt::format_to(ctx.out(), "offset={} steady_time_point={}", context.offset,
201 context.steady_time_point.time_point);
202 }
203};
204
205template <>
206struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> {
207 template <typename FormatContext>
208 auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const {
209 return fmt::format_to(ctx.out(), "{}/{}/{} {}:{}:{}", calendar.day, calendar.month,
210 calendar.year, calendar.hour, calendar.minute, calendar.second);
211 }
212};
213
214template <>
215struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo>
216 : fmt::formatter<fmt::string_view> {
217 template <typename FormatContext>
218 auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional,
219 FormatContext& ctx) const {
220 return fmt::format_to(ctx.out(), "weekday={} yearday={} name={} is_dst={} ut_offset={}",
221 additional.day_of_week, additional.day_of_year,
222 additional.name.data(), additional.is_dst, additional.ut_offset);
223 }
224};
225
226template <>
227struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> {
228 template <typename FormatContext>
229 auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const {
230 std::string_view n{name.data(), name.size()};
231 return formatter<string_view>::format(n, ctx);
232 }
233};
234
235template <>
236struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> {
237 template <typename FormatContext>
238 auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const {
239 std::string_view v{version.data(), version.size()};
240 return formatter<string_view>::format(v, ctx);
241 }
242};
243
244template <>
245struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::string_view> {
246 template <typename FormatContext>
247 auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const {
248 return fmt::format_to(
249 ctx.out(),
250 "user_context={} network_context={} user_time={} network_time={} user_calendar_time={} "
251 "network_calendar_time={} user_calendar_additional_time={} "
252 "network_calendar_additional_time={} steady_clock_time_point={} location={} "
253 "is_automatic_correction_enabled={} type={}",
254 snapshot.user_context, snapshot.network_context, snapshot.user_time,
255 snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time,
256 snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time,
257 snapshot.steady_clock_time_point, snapshot.location_name,
258 snapshot.is_automatic_correction_enabled, snapshot.type);
259 }
260};
261
262template <>
263struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint>
264 : fmt::formatter<fmt::string_view> {
265 template <typename FormatContext>
266 auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point,
267 FormatContext& ctx) const {
268 return fmt::format_to(ctx.out(),
269 "rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}",
270 time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount,
271 time_point.lower, time_point.upper);
272 }
273}; \ No newline at end of file
diff --git a/src/core/hle/service/psc/time/power_state_service.cpp b/src/core/hle/service/psc/time/power_state_service.cpp
index b0ae71bf9..ab1d32c70 100644
--- a/src/core/hle/service/psc/time/power_state_service.cpp
+++ b/src/core/hle/service/psc/time/power_state_service.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/cmif_serialization.h"
4#include "core/hle/service/psc/time/power_state_service.h" 5#include "core/hle/service/psc/time/power_state_service.h"
5 6
6namespace Service::PSC::Time { 7namespace Service::PSC::Time {
@@ -11,39 +12,34 @@ IPowerStateRequestHandler::IPowerStateRequestHandler(
11 power_state_request_manager} { 12 power_state_request_manager} {
12 // clang-format off 13 // clang-format off
13 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
14 {0, &IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle, "GetPowerStateRequestEventReadableHandle"}, 15 {0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"},
15 {1, &IPowerStateRequestHandler::GetAndClearPowerStateRequest, "GetAndClearPowerStateRequest"}, 16 {1, D<&IPowerStateRequestHandler::GetAndClearPowerStateRequest>, "GetAndClearPowerStateRequest"},
16 }; 17 };
17 // clang-format on 18 // clang-format on
18 19
19 RegisterHandlers(functions); 20 RegisterHandlers(functions);
20} 21}
21 22
22void IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx) { 23Result IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(
24 OutCopyHandle<Kernel::KReadableEvent> out_event) {
23 LOG_DEBUG(Service_Time, "called."); 25 LOG_DEBUG(Service_Time, "called.");
24 26
25 IPC::ResponseBuilder rb{ctx, 2, 1}; 27 *out_event = &m_power_state_request_manager.GetReadableEvent();
26 rb.Push(ResultSuccess); 28 R_SUCCEED();
27 rb.PushCopyObjects(m_power_state_request_manager.GetReadableEvent());
28} 29}
29 30
30void IPowerStateRequestHandler::GetAndClearPowerStateRequest(HLERequestContext& ctx) { 31Result IPowerStateRequestHandler::GetAndClearPowerStateRequest(Out<bool> out_cleared,
32 Out<u32> out_priority) {
31 LOG_DEBUG(Service_Time, "called."); 33 LOG_DEBUG(Service_Time, "called.");
32 34
33 u32 priority{}; 35 u32 priority{};
34 auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority); 36 auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority);
37 *out_cleared = cleared;
35 38
36 if (cleared) { 39 if (cleared) {
37 IPC::ResponseBuilder rb{ctx, 4}; 40 *out_priority = priority;
38 rb.Push(ResultSuccess);
39 rb.Push(priority);
40 rb.Push(cleared);
41 return;
42 } 41 }
43 42 R_SUCCEED();
44 IPC::ResponseBuilder rb{ctx, 3};
45 rb.Push(ResultSuccess);
46 rb.Push(cleared);
47} 43}
48 44
49} // namespace Service::PSC::Time 45} // namespace Service::PSC::Time
diff --git a/src/core/hle/service/psc/time/power_state_service.h b/src/core/hle/service/psc/time/power_state_service.h
index 3ebfddb79..56e2c4b87 100644
--- a/src/core/hle/service/psc/time/power_state_service.h
+++ b/src/core/hle/service/psc/time/power_state_service.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/cmif_types.h"
6#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
7#include "core/hle/service/psc/time/power_state_request_manager.h" 8#include "core/hle/service/psc/time/power_state_request_manager.h"
8#include "core/hle/service/server_manager.h" 9#include "core/hle/service/server_manager.h"
@@ -21,10 +22,10 @@ public:
21 22
22 ~IPowerStateRequestHandler() override = default; 23 ~IPowerStateRequestHandler() override = default;
23 24
24private: 25 Result GetPowerStateRequestEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
25 void GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx); 26 Result GetAndClearPowerStateRequest(Out<bool> out_cleared, Out<u32> out_priority);
26 void GetAndClearPowerStateRequest(HLERequestContext& ctx);
27 27
28private:
28 Core::System& m_system; 29 Core::System& m_system;
29 PowerStateRequestManager& m_power_state_request_manager; 30 PowerStateRequestManager& m_power_state_request_manager;
30}; 31};
diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp
index 60820aa9b..ec906b723 100644
--- a/src/core/hle/service/psc/time/service_manager.cpp
+++ b/src/core/hle/service/psc/time/service_manager.cpp
@@ -3,6 +3,7 @@
3 3
4#include "core/core.h" 4#include "core/core.h"
5#include "core/core_timing.h" 5#include "core/core_timing.h"
6#include "core/hle/service/cmif_serialization.h"
6#include "core/hle/service/psc/time/power_state_service.h" 7#include "core/hle/service/psc/time/power_state_service.h"
7#include "core/hle/service/psc/time/service_manager.h" 8#include "core/hle/service/psc/time/service_manager.h"
8#include "core/hle/service/psc/time/static.h" 9#include "core/hle/service/psc/time/static.h"
@@ -25,24 +26,24 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
25 m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} { 26 m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} {
26 // clang-format off 27 // clang-format off
27 static const FunctionInfo functions[] = { 28 static const FunctionInfo functions[] = {
28 {0, &ServiceManager::Handle_GetStaticServiceAsUser, "GetStaticServiceAsUser"}, 29 {0, D<&ServiceManager::GetStaticServiceAsUser>, "GetStaticServiceAsUser"},
29 {5, &ServiceManager::Handle_GetStaticServiceAsAdmin, "GetStaticServiceAsAdmin"}, 30 {5, D<&ServiceManager::GetStaticServiceAsAdmin>, "GetStaticServiceAsAdmin"},
30 {6, &ServiceManager::Handle_GetStaticServiceAsRepair, "GetStaticServiceAsRepair"}, 31 {6, D<&ServiceManager::GetStaticServiceAsRepair>, "GetStaticServiceAsRepair"},
31 {9, &ServiceManager::Handle_GetStaticServiceAsServiceManager, "GetStaticServiceAsServiceManager"}, 32 {9, D<&ServiceManager::GetStaticServiceAsServiceManager>, "GetStaticServiceAsServiceManager"},
32 {10, &ServiceManager::Handle_SetupStandardSteadyClockCore, "SetupStandardSteadyClockCore"}, 33 {10, D<&ServiceManager::SetupStandardSteadyClockCore>, "SetupStandardSteadyClockCore"},
33 {11, &ServiceManager::Handle_SetupStandardLocalSystemClockCore, "SetupStandardLocalSystemClockCore"}, 34 {11, D<&ServiceManager::SetupStandardLocalSystemClockCore>, "SetupStandardLocalSystemClockCore"},
34 {12, &ServiceManager::Handle_SetupStandardNetworkSystemClockCore, "SetupStandardNetworkSystemClockCore"}, 35 {12, D<&ServiceManager::SetupStandardNetworkSystemClockCore>, "SetupStandardNetworkSystemClockCore"},
35 {13, &ServiceManager::Handle_SetupStandardUserSystemClockCore, "SetupStandardUserSystemClockCore"}, 36 {13, D<&ServiceManager::SetupStandardUserSystemClockCore>, "SetupStandardUserSystemClockCore"},
36 {14, &ServiceManager::Handle_SetupTimeZoneServiceCore, "SetupTimeZoneServiceCore"}, 37 {14, D<&ServiceManager::SetupTimeZoneServiceCore>, "SetupTimeZoneServiceCore"},
37 {15, &ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore, "SetupEphemeralNetworkSystemClockCore"}, 38 {15, D<&ServiceManager::SetupEphemeralNetworkSystemClockCore>, "SetupEphemeralNetworkSystemClockCore"},
38 {50, &ServiceManager::Handle_GetStandardLocalClockOperationEvent, "GetStandardLocalClockOperationEvent"}, 39 {50, D<&ServiceManager::GetStandardLocalClockOperationEvent>, "GetStandardLocalClockOperationEvent"},
39 {51, &ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager, "GetStandardNetworkClockOperationEventForServiceManager"}, 40 {51, D<&ServiceManager::GetStandardNetworkClockOperationEventForServiceManager>, "GetStandardNetworkClockOperationEventForServiceManager"},
40 {52, &ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager, "GetEphemeralNetworkClockOperationEventForServiceManager"}, 41 {52, D<&ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager>, "GetEphemeralNetworkClockOperationEventForServiceManager"},
41 {60, &ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"}, 42 {60, D<&ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
42 {100, &ServiceManager::Handle_SetStandardSteadyClockBaseTime, "SetStandardSteadyClockBaseTime"}, 43 {100, D<&ServiceManager::SetStandardSteadyClockBaseTime>, "SetStandardSteadyClockBaseTime"},
43 {200, &ServiceManager::Handle_GetClosestAlarmUpdatedEvent, "GetClosestAlarmUpdatedEvent"}, 44 {200, D<&ServiceManager::GetClosestAlarmUpdatedEvent>, "GetClosestAlarmUpdatedEvent"},
44 {201, &ServiceManager::Handle_CheckAndSignalAlarms, "CheckAndSignalAlarms"}, 45 {201, D<&ServiceManager::CheckAndSignalAlarms>, "CheckAndSignalAlarms"},
45 {202, &ServiceManager::Handle_GetClosestAlarmInfo, "GetClosestAlarmInfo "}, 46 {202, D<&ServiceManager::GetClosestAlarmInfo>, "GetClosestAlarmInfo "},
46 }; 47 };
47 // clang-format on 48 // clang-format on
48 RegisterHandlers(functions); 49 RegisterHandlers(functions);
@@ -52,302 +53,39 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
52 m_ephemeral_system_context_writer.Link(m_ephemeral_operation); 53 m_ephemeral_system_context_writer.Link(m_ephemeral_operation);
53} 54}
54 55
55void ServiceManager::SetupSAndP() { 56Result ServiceManager::GetStaticServiceAsUser(OutInterface<StaticService> out_service) {
56 if (!m_is_s_and_p_setup) {
57 m_is_s_and_p_setup = true;
58 m_server_manager.RegisterNamedService(
59 "time:s", std::make_shared<StaticService>(
60 m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
61 m_server_manager.RegisterNamedService("time:p",
62 std::make_shared<IPowerStateRequestHandler>(
63 m_system, m_time->m_power_state_request_manager));
64 }
65}
66
67void ServiceManager::CheckAndSetupServicesSAndP() {
68 if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
69 m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
70 m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
71 SetupSAndP();
72 }
73}
74
75void ServiceManager::Handle_GetStaticServiceAsUser(HLERequestContext& ctx) {
76 LOG_DEBUG(Service_Time, "called.");
77
78 std::shared_ptr<StaticService> service{};
79 auto res = GetStaticServiceAsUser(service);
80
81 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
82 rb.Push(res);
83 rb.PushIpcInterface<StaticService>(std::move(service));
84}
85
86void ServiceManager::Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx) {
87 LOG_DEBUG(Service_Time, "called.");
88
89 std::shared_ptr<StaticService> service{};
90 auto res = GetStaticServiceAsAdmin(service);
91
92 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
93 rb.Push(res);
94 rb.PushIpcInterface<StaticService>(std::move(service));
95}
96
97void ServiceManager::Handle_GetStaticServiceAsRepair(HLERequestContext& ctx) {
98 LOG_DEBUG(Service_Time, "called.");
99
100 std::shared_ptr<StaticService> service{};
101 auto res = GetStaticServiceAsRepair(service);
102
103 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
104 rb.Push(res);
105 rb.PushIpcInterface<StaticService>(std::move(service));
106}
107
108void ServiceManager::Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx) {
109 LOG_DEBUG(Service_Time, "called.");
110
111 std::shared_ptr<StaticService> service{};
112 auto res = GetStaticServiceAsServiceManager(service);
113
114 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
115 rb.Push(res);
116 rb.PushIpcInterface<StaticService>(std::move(service));
117}
118
119void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) {
120 LOG_DEBUG(Service_Time, "called.");
121
122 struct Parameters {
123 bool reset_detected;
124 Common::UUID clock_source_id;
125 s64 rtc_offset;
126 s64 internal_offset;
127 s64 test_offset;
128 };
129 static_assert(sizeof(Parameters) == 0x30);
130
131 IPC::RequestParser rp{ctx};
132 auto params{rp.PopRaw<Parameters>()};
133
134 auto res = SetupStandardSteadyClockCore(params.clock_source_id, params.rtc_offset,
135 params.internal_offset, params.test_offset,
136 params.reset_detected);
137
138 IPC::ResponseBuilder rb{ctx, 2};
139 rb.Push(res);
140}
141
142void ServiceManager::Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx) {
143 LOG_DEBUG(Service_Time, "called.");
144
145 IPC::RequestParser rp{ctx};
146 auto context{rp.PopRaw<SystemClockContext>()};
147 auto time{rp.Pop<s64>()};
148
149 auto res = SetupStandardLocalSystemClockCore(context, time);
150
151 IPC::ResponseBuilder rb{ctx, 2};
152 rb.Push(res);
153}
154
155void ServiceManager::Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx) {
156 LOG_DEBUG(Service_Time, "called.");
157
158 IPC::RequestParser rp{ctx};
159 auto context{rp.PopRaw<SystemClockContext>()};
160 auto accuracy{rp.Pop<s64>()};
161
162 auto res = SetupStandardNetworkSystemClockCore(context, accuracy);
163
164 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(res);
166}
167
168void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) {
169 LOG_DEBUG(Service_Time, "called.");
170
171 struct Parameters {
172 bool automatic_correction;
173 SteadyClockTimePoint time_point;
174 };
175 static_assert(sizeof(Parameters) == 0x20);
176
177 IPC::RequestParser rp{ctx};
178 auto params{rp.PopRaw<Parameters>()};
179
180 auto res = SetupStandardUserSystemClockCore(params.time_point, params.automatic_correction);
181
182 IPC::ResponseBuilder rb{ctx, 2};
183 rb.Push(res);
184}
185
186void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) {
187 LOG_DEBUG(Service_Time, "called.");
188
189 struct Parameters {
190 u32 location_count;
191 LocationName name;
192 SteadyClockTimePoint time_point;
193 RuleVersion rule_version;
194 };
195 static_assert(sizeof(Parameters) == 0x50);
196
197 IPC::RequestParser rp{ctx};
198 auto params{rp.PopRaw<Parameters>()};
199
200 auto rule_buffer{ctx.ReadBuffer()};
201
202 auto res = SetupTimeZoneServiceCore(params.name, params.time_point, params.rule_version,
203 params.location_count, rule_buffer);
204
205 IPC::ResponseBuilder rb{ctx, 2};
206 rb.Push(res);
207}
208
209void ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx) {
210 LOG_DEBUG(Service_Time, "called.");
211
212 auto res = SetupEphemeralNetworkSystemClockCore();
213
214 IPC::ResponseBuilder rb{ctx, 2};
215 rb.Push(res);
216}
217
218void ServiceManager::Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx) {
219 LOG_DEBUG(Service_Time, "called.");
220
221 Kernel::KEvent* event{};
222 auto res = GetStandardLocalClockOperationEvent(&event);
223
224 IPC::ResponseBuilder rb{ctx, 2, 1};
225 rb.Push(res);
226 rb.PushCopyObjects(event->GetReadableEvent());
227}
228
229void ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager(
230 HLERequestContext& ctx) {
231 LOG_DEBUG(Service_Time, "called.");
232
233 Kernel::KEvent* event{};
234 auto res = GetStandardNetworkClockOperationEventForServiceManager(&event);
235
236 IPC::ResponseBuilder rb{ctx, 2, 1};
237 rb.Push(res);
238 rb.PushCopyObjects(event);
239}
240
241void ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager(
242 HLERequestContext& ctx) {
243 LOG_DEBUG(Service_Time, "called.");
244
245 Kernel::KEvent* event{};
246 auto res = GetEphemeralNetworkClockOperationEventForServiceManager(&event);
247
248 IPC::ResponseBuilder rb{ctx, 2, 1};
249 rb.Push(res);
250 rb.PushCopyObjects(event);
251}
252
253void ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
254 HLERequestContext& ctx) {
255 LOG_DEBUG(Service_Time, "called.");
256
257 Kernel::KEvent* event{};
258 auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(&event);
259
260 IPC::ResponseBuilder rb{ctx, 2, 1};
261 rb.Push(res);
262 rb.PushCopyObjects(event);
263}
264
265void ServiceManager::Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx) {
266 LOG_DEBUG(Service_Time, "called."); 57 LOG_DEBUG(Service_Time, "called.");
267 58
268 IPC::RequestParser rp{ctx}; 59 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u"));
269 auto base_time{rp.Pop<s64>()};
270
271 auto res = SetStandardSteadyClockBaseTime(base_time);
272
273 IPC::ResponseBuilder rb{ctx, 2};
274 rb.Push(res);
275} 60}
276 61
277void ServiceManager::Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx) { 62Result ServiceManager::GetStaticServiceAsAdmin(OutInterface<StaticService> out_service) {
278 LOG_DEBUG(Service_Time, "called."); 63 LOG_DEBUG(Service_Time, "called.");
279 64
280 Kernel::KEvent* event{}; 65 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a"));
281 auto res = GetClosestAlarmUpdatedEvent(&event);
282
283 IPC::ResponseBuilder rb{ctx, 3};
284 rb.Push(res);
285 rb.PushCopyObjects(event->GetReadableEvent());
286} 66}
287 67
288void ServiceManager::Handle_CheckAndSignalAlarms(HLERequestContext& ctx) { 68Result ServiceManager::GetStaticServiceAsRepair(OutInterface<StaticService> out_service) {
289 LOG_DEBUG(Service_Time, "called."); 69 LOG_DEBUG(Service_Time, "called.");
290 70
291 auto res = CheckAndSignalAlarms(); 71 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r"));
292
293 IPC::ResponseBuilder rb{ctx, 2};
294 rb.Push(res);
295} 72}
296 73
297void ServiceManager::Handle_GetClosestAlarmInfo(HLERequestContext& ctx) { 74Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service) {
298 LOG_DEBUG(Service_Time, "called."); 75 LOG_DEBUG(Service_Time, "called.");
299 76
300 AlarmInfo alarm_info{};
301 bool is_valid{};
302 s64 time{};
303 auto res = GetClosestAlarmInfo(is_valid, alarm_info, time);
304
305 struct OutParameters {
306 bool is_valid;
307 AlarmInfo alarm_info;
308 s64 time;
309 };
310 static_assert(sizeof(OutParameters) == 0x20);
311
312 OutParameters out_params{
313 .is_valid = is_valid,
314 .alarm_info = alarm_info,
315 .time = time,
316 };
317
318 IPC::ResponseBuilder rb{ctx, 2 + sizeof(OutParameters) / sizeof(u32)};
319 rb.Push(res);
320 rb.PushRaw<OutParameters>(out_params);
321}
322
323// =============================== Implementations ===========================
324
325Result ServiceManager::GetStaticService(std::shared_ptr<StaticService>& out_service,
326 StaticServiceSetupInfo setup_info, const char* name) {
327 out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
328 R_SUCCEED();
329}
330
331Result ServiceManager::GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service) {
332 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u"));
333}
334
335Result ServiceManager::GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service) {
336 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a"));
337}
338
339Result ServiceManager::GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service) {
340 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r"));
341}
342
343Result ServiceManager::GetStaticServiceAsServiceManager(
344 std::shared_ptr<StaticService>& out_service) {
345 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm")); 77 R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm"));
346} 78}
347 79
348Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset, 80Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected,
349 s64 internal_offset, s64 test_offset, 81 Common::UUID& clock_source_id, s64 rtc_offset,
350 bool is_rtc_reset_detected) { 82 s64 internal_offset, s64 test_offset) {
83 LOG_DEBUG(Service_Time,
84 "called. is_rtc_reset_detected={} clock_source_id={} rtc_offset={} "
85 "internal_offset={} test_offset={}",
86 is_rtc_reset_detected, clock_source_id.RawString(), rtc_offset, internal_offset,
87 test_offset);
88
351 m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset, 89 m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset,
352 is_rtc_reset_detected); 90 is_rtc_reset_detected);
353 auto time = m_steady_clock.GetRawTime(); 91 auto time = m_steady_clock.GetRawTime();
@@ -365,6 +103,10 @@ Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_i
365} 103}
366 104
367Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) { 105Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) {
106 LOG_DEBUG(Service_Time,
107 "called. context={} context.steady_time_point.clock_source_id={} time={}", context,
108 context.steady_time_point.clock_source_id.RawString(), time);
109
368 m_local_system_clock.SetContextWriter(m_local_system_context_writer); 110 m_local_system_clock.SetContextWriter(m_local_system_context_writer);
369 m_local_system_clock.Initialize(context, time); 111 m_local_system_clock.Initialize(context, time);
370 112
@@ -374,6 +116,9 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con
374 116
375Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context, 117Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context,
376 s64 accuracy) { 118 s64 accuracy) {
119 LOG_DEBUG(Service_Time, "called. context={} steady_time_point.clock_source_id={} accuracy={}",
120 context, context.steady_time_point.clock_source_id.RawString(), accuracy);
121
377 // TODO this is a hack! The network clock should be updated independently, from the ntc service 122 // TODO this is a hack! The network clock should be updated independently, from the ntc service
378 // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot 123 // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
379 // to avoid it being stuck at 0. 124 // to avoid it being stuck at 0.
@@ -388,8 +133,11 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c
388 R_SUCCEED(); 133 R_SUCCEED();
389} 134}
390 135
391Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point, 136Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction,
392 bool automatic_correction) { 137 SteadyClockTimePoint& time_point) {
138 LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}",
139 automatic_correction, time_point, time_point.clock_source_id.RawString());
140
393 // TODO this is a hack! The user clock should be updated independently, from the ntc service 141 // TODO this is a hack! The user clock should be updated independently, from the ntc service
394 // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot 142 // and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
395 // to avoid it being stuck at 0. 143 // to avoid it being stuck at 0.
@@ -406,10 +154,16 @@ Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& ti
406 R_SUCCEED(); 154 R_SUCCEED();
407} 155}
408 156
409Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, 157Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
158 u32 location_count,
410 SteadyClockTimePoint& time_point, 159 SteadyClockTimePoint& time_point,
411 RuleVersion& rule_version, u32 location_count, 160 InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) {
412 std::span<const u8> rule_buffer) { 161 LOG_DEBUG(Service_Time,
162 "called. name={} rule_version={} location_count={} time_point={} "
163 "clock_source_id={}",
164 name, rule_version, location_count, time_point,
165 time_point.clock_source_id.RawString());
166
413 if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) { 167 if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) {
414 LOG_ERROR(Service_Time, "Failed to parse time zone binary!"); 168 LOG_ERROR(Service_Time, "Failed to parse time zone binary!");
415 } 169 }
@@ -424,6 +178,8 @@ Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
424} 178}
425 179
426Result ServiceManager::SetupEphemeralNetworkSystemClockCore() { 180Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
181 LOG_DEBUG(Service_Time, "called.");
182
427 m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer); 183 m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer);
428 m_ephemeral_network_clock.SetInitialized(); 184 m_ephemeral_network_clock.SetInitialized();
429 185
@@ -431,30 +187,41 @@ Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
431 R_SUCCEED(); 187 R_SUCCEED();
432} 188}
433 189
434Result ServiceManager::GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event) { 190Result ServiceManager::GetStandardLocalClockOperationEvent(
435 *out_event = m_local_operation.m_event; 191 OutCopyHandle<Kernel::KReadableEvent> out_event) {
192 LOG_DEBUG(Service_Time, "called.");
193
194 *out_event = &m_local_operation.m_event->GetReadableEvent();
436 R_SUCCEED(); 195 R_SUCCEED();
437} 196}
438 197
439Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager( 198Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager(
440 Kernel::KEvent** out_event) { 199 OutCopyHandle<Kernel::KReadableEvent> out_event) {
441 *out_event = m_network_operation.m_event; 200 LOG_DEBUG(Service_Time, "called.");
201
202 *out_event = &m_network_operation.m_event->GetReadableEvent();
442 R_SUCCEED(); 203 R_SUCCEED();
443} 204}
444 205
445Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager( 206Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager(
446 Kernel::KEvent** out_event) { 207 OutCopyHandle<Kernel::KReadableEvent> out_event) {
447 *out_event = m_ephemeral_operation.m_event; 208 LOG_DEBUG(Service_Time, "called.");
209
210 *out_event = &m_ephemeral_operation.m_event->GetReadableEvent();
448 R_SUCCEED(); 211 R_SUCCEED();
449} 212}
450 213
451Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent( 214Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
452 Kernel::KEvent** out_event) { 215 OutCopyHandle<Kernel::KReadableEvent> out_event) {
453 *out_event = &m_user_system_clock.GetEvent(); 216 LOG_DEBUG(Service_Time, "called.");
217
218 *out_event = &m_user_system_clock.GetEvent().GetReadableEvent();
454 R_SUCCEED(); 219 R_SUCCEED();
455} 220}
456 221
457Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) { 222Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
223 LOG_DEBUG(Service_Time, "called. base_time={}", base_time);
224
458 m_steady_clock.SetRtcOffset(base_time); 225 m_steady_clock.SetRtcOffset(base_time);
459 auto time = m_steady_clock.GetRawTime(); 226 auto time = m_steady_clock.GetRawTime();
460 auto ticks = m_system.CoreTiming().GetClockTicks(); 227 auto ticks = m_system.CoreTiming().GetClockTicks();
@@ -468,26 +235,63 @@ Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
468 R_SUCCEED(); 235 R_SUCCEED();
469} 236}
470 237
471Result ServiceManager::GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event) { 238Result ServiceManager::GetClosestAlarmUpdatedEvent(
472 *out_event = &m_alarms.GetEvent(); 239 OutCopyHandle<Kernel::KReadableEvent> out_event) {
240 LOG_DEBUG(Service_Time, "called.");
241
242 *out_event = &m_alarms.GetEvent().GetReadableEvent();
473 R_SUCCEED(); 243 R_SUCCEED();
474} 244}
475 245
476Result ServiceManager::CheckAndSignalAlarms() { 246Result ServiceManager::CheckAndSignalAlarms() {
247 LOG_DEBUG(Service_Time, "called.");
248
477 m_alarms.CheckAndSignal(); 249 m_alarms.CheckAndSignal();
478 R_SUCCEED(); 250 R_SUCCEED();
479} 251}
480 252
481Result ServiceManager::GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time) { 253Result ServiceManager::GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info,
254 Out<s64> out_time) {
482 Alarm* alarm{nullptr}; 255 Alarm* alarm{nullptr};
483 out_is_valid = m_alarms.GetClosestAlarm(&alarm); 256 *out_is_valid = m_alarms.GetClosestAlarm(&alarm);
484 if (out_is_valid) { 257 if (*out_is_valid) {
485 out_info = { 258 *out_info = {
486 .alert_time = alarm->GetAlertTime(), 259 .alert_time = alarm->GetAlertTime(),
487 .priority = alarm->GetPriority(), 260 .priority = alarm->GetPriority(),
488 }; 261 };
489 out_time = m_alarms.GetRawTime(); 262 *out_time = m_alarms.GetRawTime();
263 }
264
265 LOG_DEBUG(Service_Time,
266 "called. out_is_valid={} out_info.alert_time={} out_info.priority={}, out_time={}",
267 *out_is_valid, out_info->alert_time, out_info->priority, *out_time);
268
269 R_SUCCEED();
270}
271
272void ServiceManager::CheckAndSetupServicesSAndP() {
273 if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
274 m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
275 m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
276 SetupSAndP();
277 }
278}
279
280void ServiceManager::SetupSAndP() {
281 if (!m_is_s_and_p_setup) {
282 m_is_s_and_p_setup = true;
283 m_server_manager.RegisterNamedService(
284 "time:s", std::make_shared<StaticService>(
285 m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
286 m_server_manager.RegisterNamedService("time:p",
287 std::make_shared<IPowerStateRequestHandler>(
288 m_system, m_time->m_power_state_request_manager));
490 } 289 }
290}
291
292Result ServiceManager::GetStaticService(OutInterface<StaticService> out_service,
293 StaticServiceSetupInfo setup_info, const char* name) {
294 *out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
491 R_SUCCEED(); 295 R_SUCCEED();
492} 296}
493 297
diff --git a/src/core/hle/service/psc/time/service_manager.h b/src/core/hle/service/psc/time/service_manager.h
index 1d9952317..25d361d4f 100644
--- a/src/core/hle/service/psc/time/service_manager.h
+++ b/src/core/hle/service/psc/time/service_manager.h
@@ -6,6 +6,7 @@
6#include <list> 6#include <list>
7#include <memory> 7#include <memory>
8 8
9#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/ipc_helpers.h" 10#include "core/hle/service/ipc_helpers.h"
10#include "core/hle/service/psc/time/common.h" 11#include "core/hle/service/psc/time/common.h"
11#include "core/hle/service/psc/time/manager.h" 12#include "core/hle/service/psc/time/manager.h"
@@ -29,55 +30,38 @@ public:
29 ServerManager* server_manager); 30 ServerManager* server_manager);
30 ~ServiceManager() override = default; 31 ~ServiceManager() override = default;
31 32
32 Result GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service); 33 Result GetStaticServiceAsUser(OutInterface<StaticService> out_service);
33 Result GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service); 34 Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service);
34 Result GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service); 35 Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service);
35 Result GetStaticServiceAsServiceManager(std::shared_ptr<StaticService>& out_service); 36 Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service);
36 Result SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset, 37 Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id,
37 s64 internal_offset, s64 test_offset, 38 s64 rtc_offset, s64 internal_offset, s64 test_offset);
38 bool is_rtc_reset_detected);
39 Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time); 39 Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time);
40 Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy); 40 Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy);
41 Result SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point, 41 Result SetupStandardUserSystemClockCore(bool automatic_correction,
42 bool automatic_correction); 42 SteadyClockTimePoint& time_point);
43 Result SetupTimeZoneServiceCore(LocationName& name, SteadyClockTimePoint& time_point, 43 Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
44 RuleVersion& rule_version, u32 location_count, 44 u32 location_count, SteadyClockTimePoint& time_point,
45 std::span<const u8> rule_buffer); 45 InBuffer<BufferAttr_HipcAutoSelect> rule_buffer);
46 Result SetupEphemeralNetworkSystemClockCore(); 46 Result SetupEphemeralNetworkSystemClockCore();
47 Result GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event); 47 Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
48 Result GetStandardNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event); 48 Result GetStandardNetworkClockOperationEventForServiceManager(
49 Result GetEphemeralNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event); 49 OutCopyHandle<Kernel::KReadableEvent> out_event);
50 Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(Kernel::KEvent** out_event); 50 Result GetEphemeralNetworkClockOperationEventForServiceManager(
51 OutCopyHandle<Kernel::KReadableEvent> out_event);
52 Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
53 OutCopyHandle<Kernel::KReadableEvent> out_event);
51 Result SetStandardSteadyClockBaseTime(s64 base_time); 54 Result SetStandardSteadyClockBaseTime(s64 base_time);
52 Result GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event); 55 Result GetClosestAlarmUpdatedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
53 Result CheckAndSignalAlarms(); 56 Result CheckAndSignalAlarms();
54 Result GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time); 57 Result GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Out<s64> out_time);
55 58
56private: 59private:
57 void CheckAndSetupServicesSAndP(); 60 void CheckAndSetupServicesSAndP();
58 void SetupSAndP(); 61 void SetupSAndP();
59 Result GetStaticService(std::shared_ptr<StaticService>& out_service, 62 Result GetStaticService(OutInterface<StaticService> out_service,
60 StaticServiceSetupInfo setup_info, const char* name); 63 StaticServiceSetupInfo setup_info, const char* name);
61 64
62 void Handle_GetStaticServiceAsUser(HLERequestContext& ctx);
63 void Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx);
64 void Handle_GetStaticServiceAsRepair(HLERequestContext& ctx);
65 void Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx);
66 void Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx);
67 void Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx);
68 void Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx);
69 void Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx);
70 void Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx);
71 void Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx);
72 void Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx);
73 void Handle_GetStandardNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
74 void Handle_GetEphemeralNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
75 void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(HLERequestContext& ctx);
76 void Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx);
77 void Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx);
78 void Handle_CheckAndSignalAlarms(HLERequestContext& ctx);
79 void Handle_GetClosestAlarmInfo(HLERequestContext& ctx);
80
81 Core::System& m_system; 65 Core::System& m_system;
82 std::shared_ptr<TimeManager> m_time; 66 std::shared_ptr<TimeManager> m_time;
83 ServerManager& m_server_manager; 67 ServerManager& m_server_manager;
diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp
index 6f8cf3f88..3ca3311af 100644
--- a/src/core/hle/service/psc/time/static.cpp
+++ b/src/core/hle/service/psc/time/static.cpp
@@ -1,9 +1,11 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/scope_exit.h"
4#include "core/core.h" 5#include "core/core.h"
5#include "core/core_timing.h" 6#include "core/core_timing.h"
6#include "core/hle/kernel/k_shared_memory.h" 7#include "core/hle/kernel/k_shared_memory.h"
8#include "core/hle/service/cmif_serialization.h"
7#include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h" 9#include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h"
8#include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h" 10#include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h"
9#include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h" 11#include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h"
@@ -39,358 +41,122 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup
39 m_time->m_shared_memory} { 41 m_time->m_shared_memory} {
40 // clang-format off 42 // clang-format off
41 static const FunctionInfo functions[] = { 43 static const FunctionInfo functions[] = {
42 {0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"}, 44 {0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
43 {1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, 45 {1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"},
44 {2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"}, 46 {2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"},
45 {3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"}, 47 {3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"},
46 {4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, 48 {4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"},
47 {5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"}, 49 {5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"},
48 {20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, 50 {20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
49 {50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"}, 51 {50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"},
50 {51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"}, 52 {51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"},
51 {100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, 53 {100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
52 {101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, 54 {101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
53 {102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"}, 55 {102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"},
54 {200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"}, 56 {200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"},
55 {201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, 57 {201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
56 {300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"}, 58 {300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"},
57 {400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"}, 59 {400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"},
58 {401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"}, 60 {401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"},
59 {500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"}, 61 {500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"},
60 {501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"}, 62 {501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"},
61 }; 63 };
62 // clang-format on 64 // clang-format on
63 65
64 RegisterHandlers(functions); 66 RegisterHandlers(functions);
65} 67}
66 68
67Result StaticService::GetClockSnapshotImpl(ClockSnapshot& out_snapshot, 69Result StaticService::GetStandardUserSystemClock(OutInterface<SystemClock> out_service) {
68 SystemClockContext& user_context,
69 SystemClockContext& network_context, TimeType type) {
70 out_snapshot.user_context = user_context;
71 out_snapshot.network_context = network_context;
72
73 R_TRY(
74 m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot.steady_clock_time_point));
75
76 out_snapshot.is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
77
78 R_TRY(m_time_zone.GetLocationName(out_snapshot.location_name));
79
80 R_TRY(GetTimeFromTimePointAndContext(
81 &out_snapshot.user_time, out_snapshot.steady_clock_time_point, out_snapshot.user_context));
82
83 R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.user_calendar_time,
84 out_snapshot.user_calendar_additional_time,
85 out_snapshot.user_time));
86
87 if (GetTimeFromTimePointAndContext(&out_snapshot.network_time,
88 out_snapshot.steady_clock_time_point,
89 out_snapshot.network_context) != ResultSuccess) {
90 out_snapshot.network_time = 0;
91 }
92
93 R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.network_calendar_time,
94 out_snapshot.network_calendar_additional_time,
95 out_snapshot.network_time));
96 out_snapshot.type = type;
97 out_snapshot.unk_CE = 0;
98 R_SUCCEED();
99}
100
101void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
102 LOG_DEBUG(Service_Time, "called.");
103
104 std::shared_ptr<SystemClock> service{};
105 auto res = GetStandardUserSystemClock(service);
106
107 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
108 rb.Push(res);
109 rb.PushIpcInterface<SystemClock>(std::move(service));
110}
111
112void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) {
113 LOG_DEBUG(Service_Time, "called."); 70 LOG_DEBUG(Service_Time, "called.");
114 71
115 std::shared_ptr<SystemClock> service{}; 72 *out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
116 auto res = GetStandardNetworkSystemClock(service); 73 m_setup_info.can_write_user_clock,
117 74 m_setup_info.can_write_uninitialized_clock);
118 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 75 R_SUCCEED();
119 rb.Push(res);
120 rb.PushIpcInterface<SystemClock>(std::move(service));
121}
122
123void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) {
124 LOG_DEBUG(Service_Time, "called.");
125
126 std::shared_ptr<SteadyClock> service{};
127 auto res = GetStandardSteadyClock(service);
128
129 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
130 rb.Push(res);
131 rb.PushIpcInterface(std::move(service));
132}
133
134void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) {
135 LOG_DEBUG(Service_Time, "called.");
136
137 std::shared_ptr<TimeZoneService> service{};
138 auto res = GetTimeZoneService(service);
139
140 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
141 rb.Push(res);
142 rb.PushIpcInterface(std::move(service));
143}
144
145void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) {
146 LOG_DEBUG(Service_Time, "called.");
147
148 std::shared_ptr<SystemClock> service{};
149 auto res = GetStandardLocalSystemClock(service);
150
151 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
152 rb.Push(res);
153 rb.PushIpcInterface<SystemClock>(std::move(service));
154}
155
156void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) {
157 LOG_DEBUG(Service_Time, "called.");
158
159 std::shared_ptr<SystemClock> service{};
160 auto res = GetEphemeralNetworkSystemClock(service);
161
162 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
163 rb.Push(res);
164 rb.PushIpcInterface<SystemClock>(std::move(service));
165}
166
167void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
168 LOG_DEBUG(Service_Time, "called.");
169
170 Kernel::KSharedMemory* shared_memory{};
171 auto res = GetSharedMemoryNativeHandle(&shared_memory);
172
173 IPC::ResponseBuilder rb{ctx, 2, 1};
174 rb.Push(res);
175 rb.PushCopyObjects(shared_memory);
176}
177
178void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) {
179 LOG_DEBUG(Service_Time, "called.");
180
181 IPC::ResponseBuilder rb{ctx, 2};
182 rb.Push(m_setup_info.can_write_steady_clock ? ResultNotImplemented : ResultPermissionDenied);
183}
184
185void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) {
186 LOG_DEBUG(Service_Time, "called.");
187
188 IPC::ResponseBuilder rb{ctx, 2};
189 rb.Push(ResultNotImplemented);
190}
191
192void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(
193 HLERequestContext& ctx) {
194 LOG_DEBUG(Service_Time, "called.");
195
196 bool is_enabled{};
197 auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled);
198
199 IPC::ResponseBuilder rb{ctx, 3};
200 rb.Push(res);
201 rb.Push<bool>(is_enabled);
202}
203
204void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(
205 HLERequestContext& ctx) {
206 LOG_DEBUG(Service_Time, "called.");
207
208 IPC::RequestParser rp{ctx};
209 auto automatic_correction{rp.Pop<bool>()};
210
211 auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
212
213 IPC::ResponseBuilder rb{ctx, 2};
214 rb.Push(res);
215}
216
217void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) {
218 LOG_DEBUG(Service_Time, "called.");
219
220 IPC::ResponseBuilder rb{ctx, 2};
221 rb.Push(ResultNotImplemented);
222}
223
224void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
225 LOG_DEBUG(Service_Time, "called.");
226
227 bool is_sufficient{};
228 auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient);
229
230 IPC::ResponseBuilder rb{ctx, 3};
231 rb.Push(res);
232 rb.Push<bool>(is_sufficient);
233} 76}
234 77
235void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( 78Result StaticService::GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service) {
236 HLERequestContext& ctx) {
237 LOG_DEBUG(Service_Time, "called."); 79 LOG_DEBUG(Service_Time, "called.");
238 80
239 SteadyClockTimePoint time_point{}; 81 *out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock,
240 auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point); 82 m_setup_info.can_write_network_clock,
241 83 m_setup_info.can_write_uninitialized_clock);
242 IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)}; 84 R_SUCCEED();
243 rb.Push(res);
244 rb.PushRaw<SteadyClockTimePoint>(time_point);
245} 85}
246 86
247void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) { 87Result StaticService::GetStandardSteadyClock(OutInterface<SteadyClock> out_service) {
248 LOG_DEBUG(Service_Time, "called."); 88 LOG_DEBUG(Service_Time, "called.");
249 89
250 IPC::RequestParser rp{ctx}; 90 *out_service =
251 auto context{rp.PopRaw<SystemClockContext>()}; 91 std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock,
252 92 m_setup_info.can_write_uninitialized_clock);
253 s64 time{}; 93 R_SUCCEED();
254 auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context);
255
256 IPC::ResponseBuilder rb{ctx, 4};
257 rb.Push(res);
258 rb.Push<s64>(time);
259} 94}
260 95
261void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) { 96Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) {
262 LOG_DEBUG(Service_Time, "called."); 97 LOG_DEBUG(Service_Time, "called.");
263 98
264 IPC::RequestParser rp{ctx}; 99 *out_service =
265 auto type{rp.PopEnum<TimeType>()}; 100 std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone,
266 101 m_setup_info.can_write_timezone_device_location);
267 ClockSnapshot snapshot{}; 102 R_SUCCEED();
268 auto res = GetClockSnapshot(snapshot, type);
269
270 ctx.WriteBuffer(snapshot);
271
272 IPC::ResponseBuilder rb{ctx, 2};
273 rb.Push(res);
274} 103}
275 104
276void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) { 105Result StaticService::GetStandardLocalSystemClock(OutInterface<SystemClock> out_service) {
277 LOG_DEBUG(Service_Time, "called."); 106 LOG_DEBUG(Service_Time, "called.");
278 107
279 IPC::RequestParser rp{ctx}; 108 *out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock,
280 auto clock_type{rp.PopEnum<TimeType>()}; 109 m_setup_info.can_write_local_clock,
281 [[maybe_unused]] auto alignment{rp.Pop<u32>()}; 110 m_setup_info.can_write_uninitialized_clock);
282 auto user_context{rp.PopRaw<SystemClockContext>()}; 111 R_SUCCEED();
283 auto network_context{rp.PopRaw<SystemClockContext>()};
284
285 ClockSnapshot snapshot{};
286 auto res =
287 GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type);
288
289 ctx.WriteBuffer(snapshot);
290
291 IPC::ResponseBuilder rb{ctx, 2};
292 rb.Push(res);
293} 112}
294 113
295void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser( 114Result StaticService::GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service) {
296 HLERequestContext& ctx) {
297 LOG_DEBUG(Service_Time, "called."); 115 LOG_DEBUG(Service_Time, "called.");
298 116
299 ClockSnapshot a{}; 117 *out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
300 ClockSnapshot b{}; 118 m_setup_info.can_write_network_clock,
301 119 m_setup_info.can_write_uninitialized_clock);
302 auto a_buffer{ctx.ReadBuffer(0)}; 120 R_SUCCEED();
303 auto b_buffer{ctx.ReadBuffer(1)};
304
305 std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
306 std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
307
308 s64 difference{};
309 auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b);
310
311 IPC::ResponseBuilder rb{ctx, 4};
312 rb.Push(res);
313 rb.Push(difference);
314} 121}
315 122
316void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) { 123Result StaticService::GetSharedMemoryNativeHandle(
124 OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
317 LOG_DEBUG(Service_Time, "called."); 125 LOG_DEBUG(Service_Time, "called.");
318 126
319 ClockSnapshot a{}; 127 *out_shared_memory = &m_shared_memory.GetKSharedMemory();
320 ClockSnapshot b{};
321
322 auto a_buffer{ctx.ReadBuffer(0)};
323 auto b_buffer{ctx.ReadBuffer(1)};
324
325 std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
326 std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
327
328 s64 time{};
329 auto res = CalculateSpanBetween(time, a, b);
330
331 IPC::ResponseBuilder rb{ctx, 4};
332 rb.Push(res);
333 rb.Push(time);
334}
335
336// =============================== Implementations ===========================
337
338Result StaticService::GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service) {
339 out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
340 m_setup_info.can_write_user_clock,
341 m_setup_info.can_write_uninitialized_clock);
342 R_SUCCEED(); 128 R_SUCCEED();
343} 129}
344 130
345Result StaticService::GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) { 131Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
346 out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock, 132 LOG_DEBUG(Service_Time, "called. This function is not implemented!");
347 m_setup_info.can_write_network_clock,
348 m_setup_info.can_write_uninitialized_clock);
349 R_SUCCEED();
350}
351 133
352Result StaticService::GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service) { 134 R_UNLESS(m_setup_info.can_write_steady_clock, ResultPermissionDenied);
353 out_service =
354 std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock,
355 m_setup_info.can_write_uninitialized_clock);
356 R_SUCCEED();
357}
358 135
359Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) { 136 R_RETURN(ResultNotImplemented);
360 out_service =
361 std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone,
362 m_setup_info.can_write_timezone_device_location);
363 R_SUCCEED();
364} 137}
365 138
366Result StaticService::GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service) { 139Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
367 out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock, 140 LOG_DEBUG(Service_Time, "called. This function is not implemented!");
368 m_setup_info.can_write_local_clock,
369 m_setup_info.can_write_uninitialized_clock);
370 R_SUCCEED();
371}
372 141
373Result StaticService::GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) { 142 R_RETURN(ResultNotImplemented);
374 out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
375 m_setup_info.can_write_network_clock,
376 m_setup_info.can_write_uninitialized_clock);
377 R_SUCCEED();
378} 143}
379 144
380Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) { 145Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
381 *out_shared_memory = &m_shared_memory.GetKSharedMemory(); 146 Out<bool> out_is_enabled) {
382 R_SUCCEED(); 147 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); });
383}
384 148
385Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled) {
386 R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); 149 R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
387 150
388 out_is_enabled = m_user_system_clock.GetAutomaticCorrection(); 151 *out_is_enabled = m_user_system_clock.GetAutomaticCorrection();
152
389 R_SUCCEED(); 153 R_SUCCEED();
390} 154}
391 155
392Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( 156Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
393 bool automatic_correction) { 157 bool automatic_correction) {
158 LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
159
394 R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(), 160 R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(),
395 ResultClockUninitialized); 161 ResultClockUninitialized);
396 R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied); 162 R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied);
@@ -407,22 +173,35 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
407 R_SUCCEED(); 173 R_SUCCEED();
408} 174}
409 175
410Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) { 176Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
411 out_is_sufficient = m_network_system_clock.IsAccuracySufficient(); 177 LOG_DEBUG(Service_Time, "called. This function is not implemented!");
178
179 R_RETURN(ResultNotImplemented);
180}
181
182Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
183 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
184
185 *out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
186
412 R_SUCCEED(); 187 R_SUCCEED();
413} 188}
414 189
415Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( 190Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
416 SteadyClockTimePoint& out_time_point) { 191 Out<SteadyClockTimePoint> out_time_point) {
192 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
193
417 R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); 194 R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
418 195
419 m_user_system_clock.GetTimePoint(out_time_point); 196 m_user_system_clock.GetTimePoint(*out_time_point);
420 197
421 R_SUCCEED(); 198 R_SUCCEED();
422} 199}
423 200
424Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, 201Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
425 SystemClockContext& context) { 202 SystemClockContext& context) {
203 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
204
426 R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); 205 R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized);
427 206
428 SteadyClockTimePoint time_point{}; 207 SteadyClockTimePoint time_point{};
@@ -433,12 +212,16 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
433 auto one_second_ns{ 212 auto one_second_ns{
434 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()}; 213 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()};
435 auto ticks{m_system.CoreTiming().GetClockTicks()}; 214 auto ticks{m_system.CoreTiming().GetClockTicks()};
436 auto current_time{ConvertToTimeSpan(ticks).count()}; 215 auto current_time_ns{ConvertToTimeSpan(ticks).count()};
437 out_time = ((context.offset + time_point.time_point) - (current_time / one_second_ns)); 216 *out_time = ((context.offset + time_point.time_point) - (current_time_ns / one_second_ns));
217
438 R_SUCCEED(); 218 R_SUCCEED();
439} 219}
440 220
441Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type) { 221Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) {
222 SCOPE_EXIT(
223 { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
224
442 SystemClockContext user_context{}; 225 SystemClockContext user_context{};
443 R_TRY(m_user_system_clock.GetContext(user_context)); 226 R_TRY(m_user_system_clock.GetContext(user_context));
444 227
@@ -448,53 +231,101 @@ Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType typ
448 R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); 231 R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
449} 232}
450 233
451Result StaticService::GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot, 234Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type,
235 OutClockSnapshot out_snapshot,
452 SystemClockContext& user_context, 236 SystemClockContext& user_context,
453 SystemClockContext& network_context, 237 SystemClockContext& network_context) {
454 TimeType type) { 238 SCOPE_EXIT({
239 LOG_DEBUG(Service_Time,
240 "called. type={} user_context={} network_context={} out_snapshot={}", type,
241 user_context, network_context, *out_snapshot);
242 });
243
455 R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); 244 R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
456} 245}
457 246
458Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, 247Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
459 ClockSnapshot& a, 248 InClockSnapshot a,
460 ClockSnapshot& b) { 249 InClockSnapshot b) {
250 SCOPE_EXIT({
251 LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference);
252 });
253
461 auto diff_s = 254 auto diff_s =
462 std::chrono::seconds(b.user_context.offset) - std::chrono::seconds(a.user_context.offset); 255 std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset);
463 256
464 if (a.user_context == b.user_context || 257 if (a->user_context == b->user_context ||
465 !a.user_context.steady_time_point.IdMatches(b.user_context.steady_time_point)) { 258 !a->user_context.steady_time_point.IdMatches(b->user_context.steady_time_point)) {
466 out_time = 0; 259 *out_difference = 0;
467 R_SUCCEED(); 260 R_SUCCEED();
468 } 261 }
469 262
470 if (!a.is_automatic_correction_enabled || !b.is_automatic_correction_enabled) { 263 if (!a->is_automatic_correction_enabled || !b->is_automatic_correction_enabled) {
471 out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); 264 *out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
472 R_SUCCEED(); 265 R_SUCCEED();
473 } 266 }
474 267
475 if (a.network_context.steady_time_point.IdMatches(a.steady_clock_time_point) || 268 if (a->network_context.steady_time_point.IdMatches(a->steady_clock_time_point) ||
476 b.network_context.steady_time_point.IdMatches(b.steady_clock_time_point)) { 269 b->network_context.steady_time_point.IdMatches(b->steady_clock_time_point)) {
477 out_time = 0; 270 *out_difference = 0;
478 R_SUCCEED(); 271 R_SUCCEED();
479 } 272 }
480 273
481 out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count(); 274 *out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
482 R_SUCCEED(); 275 R_SUCCEED();
483} 276}
484 277
485Result StaticService::CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b) { 278Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
279 InClockSnapshot b) {
280 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
281
486 s64 time_s{}; 282 s64 time_s{};
487 auto res = 283 auto res =
488 GetSpanBetweenTimePoints(&time_s, a.steady_clock_time_point, b.steady_clock_time_point); 284 GetSpanBetweenTimePoints(&time_s, a->steady_clock_time_point, b->steady_clock_time_point);
489 285
490 if (res != ResultSuccess) { 286 if (res != ResultSuccess) {
491 R_UNLESS(a.network_time != 0 && b.network_time != 0, ResultTimeNotFound); 287 R_UNLESS(a->network_time != 0 && b->network_time != 0, ResultTimeNotFound);
492 time_s = b.network_time - a.network_time; 288 time_s = b->network_time - a->network_time;
493 } 289 }
494 290
495 out_time = 291 *out_time =
496 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count(); 292 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count();
497 R_SUCCEED(); 293 R_SUCCEED();
498} 294}
499 295
296Result StaticService::GetClockSnapshotImpl(OutClockSnapshot out_snapshot,
297 SystemClockContext& user_context,
298 SystemClockContext& network_context, TimeType type) {
299 out_snapshot->user_context = user_context;
300 out_snapshot->network_context = network_context;
301
302 R_TRY(
303 m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot->steady_clock_time_point));
304
305 out_snapshot->is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
306
307 R_TRY(m_time_zone.GetLocationName(out_snapshot->location_name));
308
309 R_TRY(GetTimeFromTimePointAndContext(&out_snapshot->user_time,
310 out_snapshot->steady_clock_time_point,
311 out_snapshot->user_context));
312
313 R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->user_calendar_time,
314 out_snapshot->user_calendar_additional_time,
315 out_snapshot->user_time));
316
317 if (GetTimeFromTimePointAndContext(&out_snapshot->network_time,
318 out_snapshot->steady_clock_time_point,
319 out_snapshot->network_context) != ResultSuccess) {
320 out_snapshot->network_time = 0;
321 }
322
323 R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->network_calendar_time,
324 out_snapshot->network_calendar_additional_time,
325 out_snapshot->network_time));
326 out_snapshot->type = type;
327 out_snapshot->unk_CE = 0;
328 R_SUCCEED();
329}
330
500} // namespace Service::PSC::Time 331} // namespace Service::PSC::Time
diff --git a/src/core/hle/service/psc/time/static.h b/src/core/hle/service/psc/time/static.h
index 498cd5ab5..120bab259 100644
--- a/src/core/hle/service/psc/time/static.h
+++ b/src/core/hle/service/psc/time/static.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/cmif_types.h"
6#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
7#include "core/hle/service/psc/time/common.h" 8#include "core/hle/service/psc/time/common.h"
8#include "core/hle/service/server_manager.h" 9#include "core/hle/service/server_manager.h"
@@ -29,58 +30,44 @@ class EphemeralNetworkSystemClockCore;
29class SharedMemory; 30class SharedMemory;
30 31
31class StaticService final : public ServiceFramework<StaticService> { 32class StaticService final : public ServiceFramework<StaticService> {
33 using InClockSnapshot = InLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
34 using OutClockSnapshot = OutLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
35
32public: 36public:
33 explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info, 37 explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info,
34 std::shared_ptr<TimeManager> time, const char* name); 38 std::shared_ptr<TimeManager> time, const char* name);
35 39
36 ~StaticService() override = default; 40 ~StaticService() override = default;
37 41
38 Result GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service); 42 Result GetStandardUserSystemClock(OutInterface<SystemClock> out_service);
39 Result GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service); 43 Result GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service);
40 Result GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service); 44 Result GetStandardSteadyClock(OutInterface<SteadyClock> out_service);
41 Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service); 45 Result GetTimeZoneService(OutInterface<TimeZoneService> out_service);
42 Result GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service); 46 Result GetStandardLocalSystemClock(OutInterface<SystemClock> out_service);
43 Result GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service); 47 Result GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service);
44 Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory); 48 Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
45 Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled); 49 Result SetStandardSteadyClockInternalOffset(s64 offset_ns);
50 Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
51 Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
46 Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction); 52 Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
47 Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient); 53 Result GetStandardUserSystemClockInitialYear(Out<s32> out_year);
54 Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
48 Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( 55 Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
49 SteadyClockTimePoint& out_time_point); 56 Out<SteadyClockTimePoint> out_time_point);
50 Result CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, SystemClockContext& context); 57 Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
51 Result GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type); 58 SystemClockContext& context);
52 Result GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot, 59 Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type);
60 Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot,
53 SystemClockContext& user_context, 61 SystemClockContext& user_context,
54 SystemClockContext& network_context, 62 SystemClockContext& network_context);
55 TimeType type); 63 Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
56 Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, ClockSnapshot& a, 64 InClockSnapshot a, InClockSnapshot b);
57 ClockSnapshot& b); 65 Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b);
58 Result CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b);
59 66
60private: 67private:
61 Result GetClockSnapshotImpl(ClockSnapshot& out_snapshot, SystemClockContext& user_context, 68 Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context,
62 SystemClockContext& network_context, TimeType type); 69 SystemClockContext& network_context, TimeType type);
63 70
64 void Handle_GetStandardUserSystemClock(HLERequestContext& ctx);
65 void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx);
66 void Handle_GetStandardSteadyClock(HLERequestContext& ctx);
67 void Handle_GetTimeZoneService(HLERequestContext& ctx);
68 void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx);
69 void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx);
70 void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx);
71 void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx);
72 void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx);
73 void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
74 void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
75 void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx);
76 void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
77 void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
78 void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
79 void Handle_GetClockSnapshot(HLERequestContext& ctx);
80 void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
81 void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
82 void Handle_CalculateSpanBetween(HLERequestContext& ctx);
83
84 Core::System& m_system; 71 Core::System& m_system;
85 StaticServiceSetupInfo m_setup_info; 72 StaticServiceSetupInfo m_setup_info;
86 std::shared_ptr<TimeManager> m_time; 73 std::shared_ptr<TimeManager> m_time;
diff --git a/src/core/hle/service/psc/time/steady_clock.cpp b/src/core/hle/service/psc/time/steady_clock.cpp
index 1ed5c7679..948610a2b 100644
--- a/src/core/hle/service/psc/time/steady_clock.cpp
+++ b/src/core/hle/service/psc/time/steady_clock.cpp
@@ -1,7 +1,9 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/scope_exit.h"
4#include "core/core.h" 5#include "core/core.h"
6#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/psc/time/steady_clock.h" 7#include "core/hle/service/psc/time/steady_clock.h"
6 8
7namespace Service::PSC::Time { 9namespace Service::PSC::Time {
@@ -14,114 +16,40 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
14 can_write_uninitialized_clock} { 16 can_write_uninitialized_clock} {
15 // clang-format off 17 // clang-format off
16 static const FunctionInfo functions[] = { 18 static const FunctionInfo functions[] = {
17 {0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"}, 19 {0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"},
18 {2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"}, 20 {2, D<&SteadyClock::GetTestOffset>, "GetTestOffset"},
19 {3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"}, 21 {3, D<&SteadyClock::SetTestOffset>, "SetTestOffset"},
20 {100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"}, 22 {100, D<&SteadyClock::GetRtcValue>, "GetRtcValue"},
21 {101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"}, 23 {101, D<&SteadyClock::IsRtcResetDetected>, "IsRtcResetDetected"},
22 {102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"}, 24 {102, D<&SteadyClock::GetSetupResultValue>, "GetSetupResultValue"},
23 {200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"}, 25 {200, D<&SteadyClock::GetInternalOffset>, "GetInternalOffset"},
24 }; 26 };
25 // clang-format on 27 // clang-format on
26 RegisterHandlers(functions); 28 RegisterHandlers(functions);
27} 29}
28 30
29void SteadyClock::Handle_GetCurrentTimePoint(HLERequestContext& ctx) { 31Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) {
30 LOG_DEBUG(Service_Time, "called."); 32 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
31 33
32 SteadyClockTimePoint time_point{};
33 auto res = GetCurrentTimePoint(time_point);
34
35 IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
36 rb.Push(res);
37 rb.PushRaw<SteadyClockTimePoint>(time_point);
38}
39
40void SteadyClock::Handle_GetTestOffset(HLERequestContext& ctx) {
41 LOG_DEBUG(Service_Time, "called.");
42
43 s64 test_offset{};
44 auto res = GetTestOffset(test_offset);
45
46 IPC::ResponseBuilder rb{ctx, 4};
47 rb.Push(res);
48 rb.Push(test_offset);
49}
50
51void SteadyClock::Handle_SetTestOffset(HLERequestContext& ctx) {
52 LOG_DEBUG(Service_Time, "called.");
53
54 IPC::RequestParser rp{ctx};
55 auto test_offset{rp.Pop<s64>()};
56
57 auto res = SetTestOffset(test_offset);
58
59 IPC::ResponseBuilder rb{ctx, 2};
60 rb.Push(res);
61}
62
63void SteadyClock::Handle_GetRtcValue(HLERequestContext& ctx) {
64 LOG_DEBUG(Service_Time, "called.");
65
66 s64 rtc_value{};
67 auto res = GetRtcValue(rtc_value);
68
69 IPC::ResponseBuilder rb{ctx, 4};
70 rb.Push(res);
71 rb.Push(rtc_value);
72}
73
74void SteadyClock::Handle_IsRtcResetDetected(HLERequestContext& ctx) {
75 LOG_DEBUG(Service_Time, "called.");
76
77 bool reset_detected{false};
78 auto res = IsRtcResetDetected(reset_detected);
79
80 IPC::ResponseBuilder rb{ctx, 3};
81 rb.Push(res);
82 rb.Push(reset_detected);
83}
84
85void SteadyClock::Handle_GetSetupResultValue(HLERequestContext& ctx) {
86 LOG_DEBUG(Service_Time, "called.");
87
88 Result result_value{ResultSuccess};
89 auto res = GetSetupResultValue(result_value);
90
91 IPC::ResponseBuilder rb{ctx, 3};
92 rb.Push(res);
93 rb.Push(result_value);
94}
95
96void SteadyClock::Handle_GetInternalOffset(HLERequestContext& ctx) {
97 LOG_DEBUG(Service_Time, "called.");
98
99 s64 internal_offset{};
100 auto res = GetInternalOffset(internal_offset);
101
102 IPC::ResponseBuilder rb{ctx, 4};
103 rb.Push(res);
104 rb.Push(internal_offset);
105}
106
107// =============================== Implementations ===========================
108
109Result SteadyClock::GetCurrentTimePoint(SteadyClockTimePoint& out_time_point) {
110 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 34 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
111 ResultClockUninitialized); 35 ResultClockUninitialized);
112 36
113 R_RETURN(m_clock_core.GetCurrentTimePoint(out_time_point)); 37 R_RETURN(m_clock_core.GetCurrentTimePoint(*out_time_point));
114} 38}
115 39
116Result SteadyClock::GetTestOffset(s64& out_test_offset) { 40Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) {
41 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); });
42
117 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 43 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
118 ResultClockUninitialized); 44 ResultClockUninitialized);
119 45
120 out_test_offset = m_clock_core.GetTestOffset(); 46 *out_test_offset = m_clock_core.GetTestOffset();
121 R_SUCCEED(); 47 R_SUCCEED();
122} 48}
123 49
124Result SteadyClock::SetTestOffset(s64 test_offset) { 50Result SteadyClock::SetTestOffset(s64 test_offset) {
51 LOG_DEBUG(Service_Time, "called. test_offset={}", test_offset);
52
125 R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied); 53 R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied);
126 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 54 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
127 ResultClockUninitialized); 55 ResultClockUninitialized);
@@ -130,34 +58,43 @@ Result SteadyClock::SetTestOffset(s64 test_offset) {
130 R_SUCCEED(); 58 R_SUCCEED();
131} 59}
132 60
133Result SteadyClock::GetRtcValue(s64& out_rtc_value) { 61Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) {
62 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
63
134 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 64 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
135 ResultClockUninitialized); 65 ResultClockUninitialized);
136 66
137 R_RETURN(m_clock_core.GetRtcValue(out_rtc_value)); 67 R_RETURN(m_clock_core.GetRtcValue(*out_rtc_value));
138} 68}
139 69
140Result SteadyClock::IsRtcResetDetected(bool& out_is_detected) { 70Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {
71 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); });
72
141 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 73 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
142 ResultClockUninitialized); 74 ResultClockUninitialized);
143 75
144 out_is_detected = m_clock_core.IsResetDetected(); 76 *out_is_detected = m_clock_core.IsResetDetected();
145 R_SUCCEED(); 77 R_SUCCEED();
146} 78}
147 79
148Result SteadyClock::GetSetupResultValue(Result& out_result) { 80Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
81 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); });
82
149 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 83 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
150 ResultClockUninitialized); 84 ResultClockUninitialized);
151 85
152 out_result = m_clock_core.GetSetupResultValue(); 86 *out_result = m_clock_core.GetSetupResultValue();
153 R_SUCCEED(); 87 R_SUCCEED();
154} 88}
155 89
156Result SteadyClock::GetInternalOffset(s64& out_internal_offset) { 90Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) {
91 SCOPE_EXIT(
92 { LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); });
93
157 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 94 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
158 ResultClockUninitialized); 95 ResultClockUninitialized);
159 96
160 out_internal_offset = m_clock_core.GetInternalOffset(); 97 *out_internal_offset = m_clock_core.GetInternalOffset();
161 R_SUCCEED(); 98 R_SUCCEED();
162} 99}
163 100
diff --git a/src/core/hle/service/psc/time/steady_clock.h b/src/core/hle/service/psc/time/steady_clock.h
index 115e9b138..025d758a6 100644
--- a/src/core/hle/service/psc/time/steady_clock.h
+++ b/src/core/hle/service/psc/time/steady_clock.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/cmif_types.h"
6#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
7#include "core/hle/service/psc/time/common.h" 8#include "core/hle/service/psc/time/common.h"
8#include "core/hle/service/psc/time/manager.h" 9#include "core/hle/service/psc/time/manager.h"
@@ -22,23 +23,15 @@ public:
22 23
23 ~SteadyClock() override = default; 24 ~SteadyClock() override = default;
24 25
25 Result GetCurrentTimePoint(SteadyClockTimePoint& out_time_point); 26 Result GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point);
26 Result GetTestOffset(s64& out_test_offset); 27 Result GetTestOffset(Out<s64> out_test_offset);
27 Result SetTestOffset(s64 test_offset); 28 Result SetTestOffset(s64 test_offset);
28 Result GetRtcValue(s64& out_rtc_value); 29 Result GetRtcValue(Out<s64> out_rtc_value);
29 Result IsRtcResetDetected(bool& out_is_detected); 30 Result IsRtcResetDetected(Out<bool> out_is_detected);
30 Result GetSetupResultValue(Result& out_result); 31 Result GetSetupResultValue(Out<Result> out_result);
31 Result GetInternalOffset(s64& out_internal_offset); 32 Result GetInternalOffset(Out<s64> out_internal_offset);
32 33
33private: 34private:
34 void Handle_GetCurrentTimePoint(HLERequestContext& ctx);
35 void Handle_GetTestOffset(HLERequestContext& ctx);
36 void Handle_SetTestOffset(HLERequestContext& ctx);
37 void Handle_GetRtcValue(HLERequestContext& ctx);
38 void Handle_IsRtcResetDetected(HLERequestContext& ctx);
39 void Handle_GetSetupResultValue(HLERequestContext& ctx);
40 void Handle_GetInternalOffset(HLERequestContext& ctx);
41
42 Core::System& m_system; 35 Core::System& m_system;
43 36
44 StandardSteadyClockCore& m_clock_core; 37 StandardSteadyClockCore& m_clock_core;
diff --git a/src/core/hle/service/psc/time/system_clock.cpp b/src/core/hle/service/psc/time/system_clock.cpp
index 13d2f1d11..0695502d5 100644
--- a/src/core/hle/service/psc/time/system_clock.cpp
+++ b/src/core/hle/service/psc/time/system_clock.cpp
@@ -1,7 +1,9 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/scope_exit.h"
4#include "core/core.h" 5#include "core/core.h"
6#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/psc/time/system_clock.h" 7#include "core/hle/service/psc/time/system_clock.h"
6 8
7namespace Service::PSC::Time { 9namespace Service::PSC::Time {
@@ -13,83 +15,28 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo
13 can_write_uninitialized_clock} { 15 can_write_uninitialized_clock} {
14 // clang-format off 16 // clang-format off
15 static const FunctionInfo functions[] = { 17 static const FunctionInfo functions[] = {
16 {0, &SystemClock::Handle_GetCurrentTime, "GetCurrentTime"}, 18 {0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"},
17 {1, &SystemClock::Handle_SetCurrentTime, "SetCurrentTime"}, 19 {1, D<&SystemClock::SetCurrentTime>, "SetCurrentTime"},
18 {2, &SystemClock::Handle_GetSystemClockContext, "GetSystemClockContext"}, 20 {2, D<&SystemClock::GetSystemClockContext>, "GetSystemClockContext"},
19 {3, &SystemClock::Handle_SetSystemClockContext, "SetSystemClockContext"}, 21 {3, D<&SystemClock::SetSystemClockContext>, "SetSystemClockContext"},
20 {4, &SystemClock::Handle_GetOperationEventReadableHandle, "GetOperationEventReadableHandle"}, 22 {4, D<&SystemClock::GetOperationEventReadableHandle>, "GetOperationEventReadableHandle"},
21 }; 23 };
22 // clang-format on 24 // clang-format on
23 RegisterHandlers(functions); 25 RegisterHandlers(functions);
24} 26}
25 27
26void SystemClock::Handle_GetCurrentTime(HLERequestContext& ctx) { 28Result SystemClock::GetCurrentTime(Out<s64> out_time) {
27 LOG_DEBUG(Service_Time, "called."); 29 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); });
28
29 s64 time{};
30 auto res = GetCurrentTime(time);
31
32 IPC::ResponseBuilder rb{ctx, 4};
33 rb.Push(res);
34 rb.Push<s64>(time);
35}
36
37void SystemClock::Handle_SetCurrentTime(HLERequestContext& ctx) {
38 LOG_DEBUG(Service_Time, "called.");
39
40 IPC::RequestParser rp{ctx};
41 auto time{rp.Pop<s64>()};
42
43 auto res = SetCurrentTime(time);
44
45 IPC::ResponseBuilder rb{ctx, 2};
46 rb.Push(res);
47}
48
49void SystemClock::Handle_GetSystemClockContext(HLERequestContext& ctx) {
50 LOG_DEBUG(Service_Time, "called.");
51
52 SystemClockContext context{};
53 auto res = GetSystemClockContext(context);
54
55 IPC::ResponseBuilder rb{ctx, 2 + sizeof(SystemClockContext) / sizeof(u32)};
56 rb.Push(res);
57 rb.PushRaw<SystemClockContext>(context);
58}
59
60void SystemClock::Handle_SetSystemClockContext(HLERequestContext& ctx) {
61 LOG_DEBUG(Service_Time, "called.");
62
63 IPC::RequestParser rp{ctx};
64 auto context{rp.PopRaw<SystemClockContext>()};
65
66 auto res = SetSystemClockContext(context);
67
68 IPC::ResponseBuilder rb{ctx, 2};
69 rb.Push(res);
70}
71
72void SystemClock::Handle_GetOperationEventReadableHandle(HLERequestContext& ctx) {
73 LOG_DEBUG(Service_Time, "called.");
74
75 Kernel::KEvent* event{};
76 auto res = GetOperationEventReadableHandle(&event);
77 30
78 IPC::ResponseBuilder rb{ctx, 2, 1};
79 rb.Push(res);
80 rb.PushCopyObjects(event->GetReadableEvent());
81}
82
83// =============================== Implementations ===========================
84
85Result SystemClock::GetCurrentTime(s64& out_time) {
86 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 31 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
87 ResultClockUninitialized); 32 ResultClockUninitialized);
88 33
89 R_RETURN(m_clock_core.GetCurrentTime(&out_time)); 34 R_RETURN(m_clock_core.GetCurrentTime(out_time.Get()));
90} 35}
91 36
92Result SystemClock::SetCurrentTime(s64 time) { 37Result SystemClock::SetCurrentTime(s64 time) {
38 LOG_DEBUG(Service_Time, "called. time={}", time);
39
93 R_UNLESS(m_can_write_clock, ResultPermissionDenied); 40 R_UNLESS(m_can_write_clock, ResultPermissionDenied);
94 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 41 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
95 ResultClockUninitialized); 42 ResultClockUninitialized);
@@ -97,14 +44,18 @@ Result SystemClock::SetCurrentTime(s64 time) {
97 R_RETURN(m_clock_core.SetCurrentTime(time)); 44 R_RETURN(m_clock_core.SetCurrentTime(time));
98} 45}
99 46
100Result SystemClock::GetSystemClockContext(SystemClockContext& out_context) { 47Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) {
48 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); });
49
101 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 50 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
102 ResultClockUninitialized); 51 ResultClockUninitialized);
103 52
104 R_RETURN(m_clock_core.GetContext(out_context)); 53 R_RETURN(m_clock_core.GetContext(*out_context));
105} 54}
106 55
107Result SystemClock::SetSystemClockContext(SystemClockContext& context) { 56Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
57 LOG_DEBUG(Service_Time, "called. context={}", context);
58
108 R_UNLESS(m_can_write_clock, ResultPermissionDenied); 59 R_UNLESS(m_can_write_clock, ResultPermissionDenied);
109 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), 60 R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
110 ResultClockUninitialized); 61 ResultClockUninitialized);
@@ -112,7 +63,10 @@ Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
112 R_RETURN(m_clock_core.SetContextAndWrite(context)); 63 R_RETURN(m_clock_core.SetContextAndWrite(context));
113} 64}
114 65
115Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) { 66Result SystemClock::GetOperationEventReadableHandle(
67 OutCopyHandle<Kernel::KReadableEvent> out_event) {
68 LOG_DEBUG(Service_Time, "called.");
69
116 if (!m_operation_event) { 70 if (!m_operation_event) {
117 m_operation_event = std::make_unique<OperationEvent>(m_system); 71 m_operation_event = std::make_unique<OperationEvent>(m_system);
118 R_UNLESS(m_operation_event != nullptr, ResultFailed); 72 R_UNLESS(m_operation_event != nullptr, ResultFailed);
@@ -120,7 +74,7 @@ Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event)
120 m_clock_core.LinkOperationEvent(*m_operation_event); 74 m_clock_core.LinkOperationEvent(*m_operation_event);
121 } 75 }
122 76
123 *out_event = m_operation_event->m_event; 77 *out_event = &m_operation_event->m_event->GetReadableEvent();
124 R_SUCCEED(); 78 R_SUCCEED();
125} 79}
126 80
diff --git a/src/core/hle/service/psc/time/system_clock.h b/src/core/hle/service/psc/time/system_clock.h
index f30027e7b..b40d73595 100644
--- a/src/core/hle/service/psc/time/system_clock.h
+++ b/src/core/hle/service/psc/time/system_clock.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/cmif_types.h"
6#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
7#include "core/hle/service/psc/time/common.h" 8#include "core/hle/service/psc/time/common.h"
8#include "core/hle/service/psc/time/manager.h" 9#include "core/hle/service/psc/time/manager.h"
@@ -22,19 +23,13 @@ public:
22 23
23 ~SystemClock() override = default; 24 ~SystemClock() override = default;
24 25
25 Result GetCurrentTime(s64& out_time); 26 Result GetCurrentTime(Out<s64> out_time);
26 Result SetCurrentTime(s64 time); 27 Result SetCurrentTime(s64 time);
27 Result GetSystemClockContext(SystemClockContext& out_context); 28 Result GetSystemClockContext(Out<SystemClockContext> out_context);
28 Result SetSystemClockContext(SystemClockContext& context); 29 Result SetSystemClockContext(SystemClockContext& context);
29 Result GetOperationEventReadableHandle(Kernel::KEvent** out_event); 30 Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
30 31
31private: 32private:
32 void Handle_GetCurrentTime(HLERequestContext& ctx);
33 void Handle_SetCurrentTime(HLERequestContext& ctx);
34 void Handle_GetSystemClockContext(HLERequestContext& ctx);
35 void Handle_SetSystemClockContext(HLERequestContext& ctx);
36 void Handle_GetOperationEventReadableHandle(HLERequestContext& ctx);
37
38 Core::System& m_system; 33 Core::System& m_system;
39 34
40 SystemClockCore& m_clock_core; 35 SystemClockCore& m_clock_core;
diff --git a/src/core/hle/service/psc/time/time_zone.cpp b/src/core/hle/service/psc/time/time_zone.cpp
index cfee8f866..82ddba42f 100644
--- a/src/core/hle/service/psc/time/time_zone.cpp
+++ b/src/core/hle/service/psc/time/time_zone.cpp
@@ -5,7 +5,7 @@
5 5
6namespace Service::PSC::Time { 6namespace Service::PSC::Time {
7namespace { 7namespace {
8constexpr Result ValidateRule(Tz::Rule& rule) { 8constexpr Result ValidateRule(const Tz::Rule& rule) {
9 if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) || 9 if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) ||
10 rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) || 10 rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) ||
11 rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) { 11 rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) {
@@ -26,7 +26,7 @@ constexpr Result ValidateRule(Tz::Rule& rule) {
26 R_SUCCEED(); 26 R_SUCCEED();
27} 27}
28 28
29constexpr bool GetTimeZoneTime(s64& out_time, Tz::Rule& rule, s64 time, s32 index, 29constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s32 index,
30 s32 index_offset) { 30 s32 index_offset) {
31 s32 found_idx{}; 31 s32 found_idx{};
32 s32 expected_index{index + index_offset}; 32 s32 expected_index{index + index_offset};
@@ -107,7 +107,7 @@ Result TimeZone::GetTimePoint(SteadyClockTimePoint& out_time_point) {
107 107
108Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time, 108Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time,
109 CalendarAdditionalInfo& out_additional_info, s64 time, 109 CalendarAdditionalInfo& out_additional_info, s64 time,
110 Tz::Rule& rule) { 110 const Tz::Rule& rule) {
111 std::scoped_lock l{m_mutex}; 111 std::scoped_lock l{m_mutex};
112 R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule)); 112 R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule));
113} 113}
@@ -140,8 +140,8 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary)
140 R_RETURN(ParseBinaryImpl(out_rule, binary)); 140 R_RETURN(ParseBinaryImpl(out_rule, binary));
141} 141}
142 142
143Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 143Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
144 CalendarTime& calendar, Tz::Rule& rule) { 144 CalendarTime& calendar, const Tz::Rule& rule) {
145 std::scoped_lock l{m_mutex}; 145 std::scoped_lock l{m_mutex};
146 146
147 auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1); 147 auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1);
@@ -157,7 +157,7 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 ou
157 R_RETURN(res); 157 R_RETURN(res);
158} 158}
159 159
160Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, 160Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
161 u32 out_times_count, CalendarTime& calendar) { 161 u32 out_times_count, CalendarTime& calendar) {
162 std::scoped_lock l{m_mutex}; 162 std::scoped_lock l{m_mutex};
163 163
@@ -183,7 +183,7 @@ Result TimeZone::ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary)
183 183
184Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time, 184Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
185 CalendarAdditionalInfo& out_additional_info, s64 time, 185 CalendarAdditionalInfo& out_additional_info, s64 time,
186 Tz::Rule& rule) { 186 const Tz::Rule& rule) {
187 R_TRY(ValidateRule(rule)); 187 R_TRY(ValidateRule(rule));
188 188
189 Tz::CalendarTimeInternal calendar_internal{}; 189 Tz::CalendarTimeInternal calendar_internal{};
@@ -212,8 +212,8 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
212 R_SUCCEED(); 212 R_SUCCEED();
213} 213}
214 214
215Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 215Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
216 CalendarTime& calendar, Tz::Rule& rule, s32 is_dst) { 216 CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst) {
217 R_TRY(ValidateRule(rule)); 217 R_TRY(ValidateRule(rule));
218 218
219 calendar.month -= 1; 219 calendar.month -= 1;
diff --git a/src/core/hle/service/psc/time/time_zone.h b/src/core/hle/service/psc/time/time_zone.h
index ce2acca17..6bd8f2fda 100644
--- a/src/core/hle/service/psc/time/time_zone.h
+++ b/src/core/hle/service/psc/time/time_zone.h
@@ -32,23 +32,24 @@ public:
32 Result GetTimePoint(SteadyClockTimePoint& out_time_point); 32 Result GetTimePoint(SteadyClockTimePoint& out_time_point);
33 33
34 Result ToCalendarTime(CalendarTime& out_calendar_time, 34 Result ToCalendarTime(CalendarTime& out_calendar_time,
35 CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule); 35 CalendarAdditionalInfo& out_additional_info, s64 time,
36 const Tz::Rule& rule);
36 Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time, 37 Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time,
37 CalendarAdditionalInfo& calendar_additional, s64 time); 38 CalendarAdditionalInfo& calendar_additional, s64 time);
38 Result ParseBinary(LocationName& name, std::span<const u8> binary); 39 Result ParseBinary(LocationName& name, std::span<const u8> binary);
39 Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); 40 Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
40 Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 41 Result ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
41 CalendarTime& calendar, Tz::Rule& rule); 42 CalendarTime& calendar, const Tz::Rule& rule);
42 Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 43 Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count,
43 CalendarTime& calendar); 44 CalendarTime& calendar);
44 45
45private: 46private:
46 Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary); 47 Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
47 Result ToCalendarTimeImpl(CalendarTime& out_calendar_time, 48 Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
48 CalendarAdditionalInfo& out_additional_info, s64 time, 49 CalendarAdditionalInfo& out_additional_info, s64 time,
49 Tz::Rule& rule); 50 const Tz::Rule& rule);
50 Result ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 51 Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
51 CalendarTime& calendar, Tz::Rule& rule, s32 is_dst); 52 CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
52 53
53 bool m_initialized{}; 54 bool m_initialized{};
54 std::recursive_mutex m_mutex; 55 std::recursive_mutex m_mutex;
diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp
index e304c8387..9376a0324 100644
--- a/src/core/hle/service/psc/time/time_zone_service.cpp
+++ b/src/core/hle/service/psc/time/time_zone_service.cpp
@@ -2,7 +2,10 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <tz/tz.h> 4#include <tz/tz.h>
5
6#include "common/scope_exit.h"
5#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/service/cmif_serialization.h"
6#include "core/hle/service/psc/time/time_zone_service.h" 9#include "core/hle/service/psc/time/time_zone_service.h"
7 10
8namespace Service::PSC::Time { 11namespace Service::PSC::Time {
@@ -14,276 +17,153 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore&
14 can_write_timezone_device_location} { 17 can_write_timezone_device_location} {
15 // clang-format off 18 // clang-format off
16 static const FunctionInfo functions[] = { 19 static const FunctionInfo functions[] = {
17 {0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"}, 20 {0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
18 {1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"}, 21 {1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"},
19 {2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"}, 22 {2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"},
20 {3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"}, 23 {3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"},
21 {4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"}, 24 {4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"},
22 {5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"}, 25 {5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"},
23 {6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"}, 26 {6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"},
24 {7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"}, 27 {7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"},
25 {8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"}, 28 {8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"},
26 {20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"}, 29 {20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"},
27 {100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"}, 30 {100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"},
28 {101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, 31 {101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"},
29 {201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"}, 32 {201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"},
30 {202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, 33 {202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"},
31 }; 34 };
32 // clang-format on 35 // clang-format on
33 RegisterHandlers(functions); 36 RegisterHandlers(functions);
34} 37}
35 38
36void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) { 39Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) {
37 LOG_DEBUG(Service_Time, "called."); 40 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
38
39 LocationName name{};
40 auto res = GetDeviceLocationName(name);
41
42 IPC::ResponseBuilder rb{ctx, 2 + sizeof(LocationName) / sizeof(u32)};
43 rb.Push(res);
44 rb.PushRaw<LocationName>(name);
45}
46
47void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
48 LOG_DEBUG(Service_Time, "called.");
49
50 IPC::RequestParser rp{ctx};
51 [[maybe_unused]] auto name{rp.PopRaw<LocationName>()};
52
53 if (!m_can_write_timezone_device_location) {
54 IPC::ResponseBuilder rb{ctx, 2};
55 rb.Push(ResultPermissionDenied);
56 return;
57 }
58
59 IPC::ResponseBuilder rb{ctx, 2};
60 rb.Push(ResultNotImplemented);
61}
62
63void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
64 LOG_DEBUG(Service_Time, "called.");
65
66 u32 count{};
67 auto res = GetTotalLocationNameCount(count);
68
69 IPC::ResponseBuilder rb{ctx, 3};
70 rb.Push(res);
71 rb.Push(count);
72}
73
74void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
75 LOG_DEBUG(Service_Time, "called.");
76 41
77 IPC::ResponseBuilder rb{ctx, 2}; 42 R_RETURN(m_time_zone.GetLocationName(*out_location_name));
78 rb.Push(ResultNotImplemented);
79} 43}
80 44
81void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) { 45Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) {
82 LOG_DEBUG(Service_Time, "called."); 46 LOG_DEBUG(Service_Time, "called. This function is not implemented!");
83 47
84 IPC::ResponseBuilder rb{ctx, 2}; 48 R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
85 rb.Push(ResultNotImplemented); 49 R_RETURN(ResultNotImplemented);
86} 50}
87 51
88void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) { 52Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
89 LOG_DEBUG(Service_Time, "called."); 53 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
90
91 RuleVersion rule_version{};
92 auto res = GetTimeZoneRuleVersion(rule_version);
93 54
94 IPC::ResponseBuilder rb{ctx, 2 + sizeof(RuleVersion) / sizeof(u32)}; 55 R_RETURN(m_time_zone.GetTotalLocationCount(*out_count));
95 rb.Push(res);
96 rb.PushRaw<RuleVersion>(rule_version);
97} 56}
98 57
99void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) { 58Result TimeZoneService::LoadLocationNameList(
100 LOG_DEBUG(Service_Time, "called."); 59 Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
101 60 LOG_DEBUG(Service_Time, "called. This function is not implemented!");
102 LocationName name{};
103 SteadyClockTimePoint time_point{};
104 auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name);
105 61
106 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(LocationName) / sizeof(u32)) + 62 R_RETURN(ResultNotImplemented);
107 (sizeof(SteadyClockTimePoint) / sizeof(u32))};
108 rb.Push(res);
109 rb.PushRaw<LocationName>(name);
110 rb.PushRaw<SteadyClockTimePoint>(time_point);
111} 63}
112 64
113void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) { 65Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) {
114 LOG_DEBUG(Service_Time, "called."); 66 LOG_DEBUG(Service_Time, "called. This function is not implemented!");
115
116 IPC::RequestParser rp{ctx};
117 auto name{rp.PopRaw<LocationName>()};
118
119 auto binary{ctx.ReadBuffer()};
120 auto res = SetDeviceLocationNameWithTimeZoneRule(name, binary);
121 67
122 IPC::ResponseBuilder rb{ctx, 2}; 68 R_RETURN(ResultNotImplemented);
123 rb.Push(res);
124} 69}
125 70
126void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) { 71Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) {
127 LOG_DEBUG(Service_Time, "called."); 72 SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
128
129 auto binary{ctx.ReadBuffer()};
130 73
131 Tz::Rule rule{}; 74 R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version));
132 auto res = ParseTimeZoneBinary(rule, binary);
133
134 ctx.WriteBuffer(rule);
135
136 IPC::ResponseBuilder rb{ctx, 2};
137 rb.Push(res);
138} 75}
139 76
140void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle( 77Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
141 HLERequestContext& ctx) { 78 Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) {
142 LOG_DEBUG(Service_Time, "called."); 79 SCOPE_EXIT({
80 LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}",
81 *out_location_name, *out_time_point);
82 });
143 83
144 IPC::ResponseBuilder rb{ctx, 2}; 84 R_TRY(m_time_zone.GetLocationName(*out_location_name));
145 rb.Push(ResultNotImplemented); 85 R_RETURN(m_time_zone.GetTimePoint(*out_time_point));
146} 86}
147 87
148void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) { 88Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
149 LOG_DEBUG(Service_Time, "called."); 89 LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) {
150 90 LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
151 IPC::RequestParser rp{ctx};
152 auto time{rp.Pop<s64>()};
153 91
154 auto rule_buffer{ctx.ReadBuffer()}; 92 R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
155 Tz::Rule rule{}; 93 R_TRY(m_time_zone.ParseBinary(location_name, binary));
156 std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule));
157
158 CalendarTime calendar_time{};
159 CalendarAdditionalInfo additional_info{};
160 auto res = ToCalendarTime(calendar_time, additional_info, time, rule);
161
162 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) +
163 (sizeof(CalendarAdditionalInfo) / sizeof(u32))};
164 rb.Push(res);
165 rb.PushRaw<CalendarTime>(calendar_time);
166 rb.PushRaw<CalendarAdditionalInfo>(additional_info);
167}
168
169void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
170 LOG_DEBUG(Service_Time, "called.");
171
172 IPC::RequestParser rp{ctx};
173 auto time{rp.Pop<s64>()};
174 94
175 CalendarTime calendar_time{}; 95 SteadyClockTimePoint time_point{};
176 CalendarAdditionalInfo additional_info{}; 96 R_TRY(m_clock_core.GetCurrentTimePoint(time_point));
177 auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time);
178 97
179 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) + 98 m_time_zone.SetTimePoint(time_point);
180 (sizeof(CalendarAdditionalInfo) / sizeof(u32))}; 99 R_SUCCEED();
181 rb.Push(res);
182 rb.PushRaw<CalendarTime>(calendar_time);
183 rb.PushRaw<CalendarAdditionalInfo>(additional_info);
184} 100}
185 101
186void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) { 102Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule,
103 InBuffer<BufferAttr_HipcAutoSelect> binary) {
187 LOG_DEBUG(Service_Time, "called."); 104 LOG_DEBUG(Service_Time, "called.");
188 105
189 IPC::RequestParser rp{ctx}; 106 R_RETURN(m_time_zone.ParseBinaryInto(*out_rule, binary));
190 auto calendar{rp.PopRaw<CalendarTime>()};
191
192 auto binary{ctx.ReadBuffer()};
193
194 Tz::Rule rule{};
195 std::memcpy(&rule, binary.data(), sizeof(Tz::Rule));
196
197 u32 count{};
198 std::array<s64, 2> times{};
199 u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
200
201 auto res = ToPosixTime(count, times, times_count, calendar, rule);
202
203 ctx.WriteBuffer(times);
204
205 IPC::ResponseBuilder rb{ctx, 3};
206 rb.Push(res);
207 rb.Push(count);
208} 107}
209 108
210void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) { 109Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
211 LOG_DEBUG(Service_Time, "called."); 110 OutCopyHandle<Kernel::KReadableEvent> out_event) {
212 111 LOG_DEBUG(Service_Time, "called. This function is not implemented!");
213 IPC::RequestParser rp{ctx};
214 auto calendar{rp.PopRaw<CalendarTime>()};
215 112
216 u32 count{}; 113 R_RETURN(ResultNotImplemented);
217 std::array<s64, 2> times{};
218 u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
219
220 auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar);
221
222 ctx.WriteBuffer(times);
223
224 IPC::ResponseBuilder rb{ctx, 3};
225 rb.Push(res);
226 rb.Push(count);
227} 114}
228 115
229// =============================== Implementations =========================== 116Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,
230 117 Out<CalendarAdditionalInfo> out_additional_info, s64 time,
231Result TimeZoneService::GetDeviceLocationName(LocationName& out_location_name) { 118 InRule rule) {
232 R_RETURN(m_time_zone.GetLocationName(out_location_name)); 119 SCOPE_EXIT({
233} 120 LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
121 *out_calendar_time, *out_additional_info);
122 });
234 123
235Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) { 124 R_RETURN(
236 R_RETURN(m_time_zone.GetTotalLocationCount(out_count)); 125 m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get()));
237}
238
239Result TimeZoneService::GetTimeZoneRuleVersion(RuleVersion& out_rule_version) {
240 R_RETURN(m_time_zone.GetRuleVersion(out_rule_version));
241}
242
243Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
244 LocationName& location_name) {
245 R_TRY(m_time_zone.GetLocationName(location_name));
246 R_RETURN(m_time_zone.GetTimePoint(out_time_point));
247} 126}
248 127
249Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, 128Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
250 std::span<const u8> binary) { 129 Out<CalendarAdditionalInfo> out_additional_info,
251 R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); 130 s64 time) {
252 R_TRY(m_time_zone.ParseBinary(location_name, binary)); 131 SCOPE_EXIT({
253 132 LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
254 SteadyClockTimePoint time_point{}; 133 *out_calendar_time, *out_additional_info);
255 R_TRY(m_clock_core.GetCurrentTimePoint(time_point)); 134 });
256 135
257 m_time_zone.SetTimePoint(time_point); 136 R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time));
258 R_SUCCEED();
259} 137}
260 138
261Result TimeZoneService::ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary) { 139Result TimeZoneService::ToPosixTime(Out<u32> out_count,
262 R_RETURN(m_time_zone.ParseBinaryInto(out_rule, binary)); 140 OutArray<s64, BufferAttr_HipcPointer> out_times,
263} 141 Out<u32> out_times_count, CalendarTime& calendar_time,
142 InRule rule) {
143 SCOPE_EXIT({
144 LOG_DEBUG(Service_Time,
145 "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
146 "out_times_count={}",
147 calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
148 });
264 149
265Result TimeZoneService::ToCalendarTime(CalendarTime& out_calendar_time, 150 R_RETURN(
266 CalendarAdditionalInfo& out_additional_info, s64 time, 151 m_time_zone.ToPosixTime(*out_count, out_times, *out_times_count, calendar_time, *rule));
267 Tz::Rule& rule) {
268 R_RETURN(m_time_zone.ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
269}
270
271Result TimeZoneService::ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
272 CalendarAdditionalInfo& out_additional_info,
273 s64 time) {
274 R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
275} 152}
276 153
277Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, 154Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
278 u32 out_times_count, CalendarTime& calendar_time, 155 OutArray<s64, BufferAttr_HipcPointer> out_times,
279 Tz::Rule& rule) { 156 Out<u32> out_times_count,
280 R_RETURN(m_time_zone.ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule)); 157 CalendarTime& calendar_time) {
281} 158 SCOPE_EXIT({
159 LOG_DEBUG(Service_Time,
160 "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
161 "out_times_count={}",
162 calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
163 });
282 164
283Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
284 u32 out_times_count, CalendarTime& calendar_time) {
285 R_RETURN( 165 R_RETURN(
286 m_time_zone.ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time)); 166 m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, *out_times_count, calendar_time));
287} 167}
288 168
289} // namespace Service::PSC::Time 169} // namespace Service::PSC::Time
diff --git a/src/core/hle/service/psc/time/time_zone_service.h b/src/core/hle/service/psc/time/time_zone_service.h
index 074c1d4ae..084e3f907 100644
--- a/src/core/hle/service/psc/time/time_zone_service.h
+++ b/src/core/hle/service/psc/time/time_zone_service.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/cmif_types.h"
6#include "core/hle/service/ipc_helpers.h" 7#include "core/hle/service/ipc_helpers.h"
7#include "core/hle/service/psc/time/common.h" 8#include "core/hle/service/psc/time/common.h"
8#include "core/hle/service/psc/time/manager.h" 9#include "core/hle/service/psc/time/manager.h"
@@ -20,45 +21,41 @@ struct Rule;
20namespace Service::PSC::Time { 21namespace Service::PSC::Time {
21 22
22class TimeZoneService final : public ServiceFramework<TimeZoneService> { 23class TimeZoneService final : public ServiceFramework<TimeZoneService> {
24 using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
25 using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
26
23public: 27public:
24 explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core, 28 explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core,
25 TimeZone& time_zone, bool can_write_timezone_device_location); 29 TimeZone& time_zone, bool can_write_timezone_device_location);
26 30
27 ~TimeZoneService() override = default; 31 ~TimeZoneService() override = default;
28 32
29 Result GetDeviceLocationName(LocationName& out_location_name); 33 Result GetDeviceLocationName(Out<LocationName> out_location_name);
30 Result GetTotalLocationNameCount(u32& out_count); 34 Result SetDeviceLocationName(LocationName& location_name);
31 Result GetTimeZoneRuleVersion(RuleVersion& out_rule_version); 35 Result GetTotalLocationNameCount(Out<u32> out_count);
32 Result GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point, 36 Result LoadLocationNameList(Out<u32> out_count,
33 LocationName& location_name); 37 OutArray<LocationName, BufferAttr_HipcMapAlias> out_names,
38 u32 index);
39 Result LoadTimeZoneRule(OutRule out_rule, LocationName& location_name);
40 Result GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version);
41 Result GetDeviceLocationNameAndUpdatedTime(Out<LocationName> location_name,
42 Out<SteadyClockTimePoint> out_time_point);
34 Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, 43 Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
35 std::span<const u8> binary); 44 InBuffer<BufferAttr_HipcAutoSelect> binary);
36 Result ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary); 45 Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary);
37 Result ToCalendarTime(CalendarTime& out_calendar_time, 46 Result GetDeviceLocationNameOperationEventReadableHandle(
38 CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule); 47 OutCopyHandle<Kernel::KReadableEvent> out_event);
39 Result ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time, 48 Result ToCalendarTime(Out<CalendarTime> out_calendar_time,
40 CalendarAdditionalInfo& out_additional_info, s64 time); 49 Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule);
41 Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 50 Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
42 CalendarTime& calendar_time, Tz::Rule& rule); 51 Out<CalendarAdditionalInfo> out_additional_info, s64 time);
43 Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count, 52 Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
44 CalendarTime& calendar_time); 53 Out<u32> out_times_count, CalendarTime& calendar_time, InRule rule);
54 Result ToPosixTimeWithMyRule(Out<u32> out_count,
55 OutArray<s64, BufferAttr_HipcPointer> out_times,
56 Out<u32> out_times_count, CalendarTime& calendar_time);
45 57
46private: 58private:
47 void Handle_GetDeviceLocationName(HLERequestContext& ctx);
48 void Handle_SetDeviceLocationName(HLERequestContext& ctx);
49 void Handle_GetTotalLocationNameCount(HLERequestContext& ctx);
50 void Handle_LoadLocationNameList(HLERequestContext& ctx);
51 void Handle_LoadTimeZoneRule(HLERequestContext& ctx);
52 void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx);
53 void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx);
54 void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx);
55 void Handle_ParseTimeZoneBinary(HLERequestContext& ctx);
56 void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx);
57 void Handle_ToCalendarTime(HLERequestContext& ctx);
58 void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx);
59 void Handle_ToPosixTime(HLERequestContext& ctx);
60 void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx);
61
62 Core::System& m_system; 59 Core::System& m_system;
63 60
64 StandardSteadyClockCore& m_clock_core; 61 StandardSteadyClockCore& m_clock_core;
diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt
index 136109a0c..c0dcc0241 100644
--- a/src/dedicated_room/CMakeLists.txt
+++ b/src/dedicated_room/CMakeLists.txt
@@ -7,8 +7,6 @@ add_executable(yuzu-room
7 yuzu_room.rc 7 yuzu_room.rc
8) 8)
9 9
10create_target_directory_groups(yuzu-room)
11
12target_link_libraries(yuzu-room PRIVATE common network) 10target_link_libraries(yuzu-room PRIVATE common network)
13if (ENABLE_WEB_SERVICE) 11if (ENABLE_WEB_SERVICE)
14 target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) 12 target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE)
@@ -28,3 +26,5 @@ endif()
28if (YUZU_USE_PRECOMPILED_HEADERS) 26if (YUZU_USE_PRECOMPILED_HEADERS)
29 target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h) 27 target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h)
30endif() 28endif()
29
30create_target_directory_groups(yuzu-room)
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 5ed0ad0ed..521a0e253 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -289,8 +289,6 @@ add_library(video_core STATIC
289 vulkan_common/vulkan.h 289 vulkan_common/vulkan.h
290) 290)
291 291
292create_target_directory_groups(video_core)
293
294target_link_libraries(video_core PUBLIC common core) 292target_link_libraries(video_core PUBLIC common core)
295target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder) 293target_link_libraries(video_core PUBLIC glad shader_recompiler stb bc_decoder)
296 294
@@ -365,3 +363,5 @@ endif()
365if (ANDROID AND ARCHITECTURE_arm64) 363if (ANDROID AND ARCHITECTURE_arm64)
366 target_link_libraries(video_core PRIVATE adrenotools) 364 target_link_libraries(video_core PRIVATE adrenotools)
367endif() 365endif()
366
367create_target_directory_groups(video_core)
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 93b03b917..b058dba17 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -375,8 +375,6 @@ elseif(WIN32)
375 endif() 375 endif()
376endif() 376endif()
377 377
378create_target_directory_groups(yuzu)
379
380target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core) 378target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
381target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) 379target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets)
382target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) 380target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
@@ -472,3 +470,5 @@ endif()
472if (YUZU_USE_PRECOMPILED_HEADERS) 470if (YUZU_USE_PRECOMPILED_HEADERS)
473 target_precompile_headers(yuzu PRIVATE precompiled_headers.h) 471 target_precompile_headers(yuzu PRIVATE precompiled_headers.h)
474endif() 472endif()
473
474create_target_directory_groups(yuzu)
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt
index fbeba8813..ebd8fd738 100644
--- a/src/yuzu_cmd/CMakeLists.txt
+++ b/src/yuzu_cmd/CMakeLists.txt
@@ -28,8 +28,6 @@ add_executable(yuzu-cmd
28 yuzu.rc 28 yuzu.rc
29) 29)
30 30
31create_target_directory_groups(yuzu-cmd)
32
33target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common) 31target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common)
34target_link_libraries(yuzu-cmd PRIVATE glad) 32target_link_libraries(yuzu-cmd PRIVATE glad)
35if (MSVC) 33if (MSVC)
@@ -63,3 +61,5 @@ endif()
63if (YUZU_USE_PRECOMPILED_HEADERS) 61if (YUZU_USE_PRECOMPILED_HEADERS)
64 target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.h) 62 target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.h)
65endif() 63endif()
64
65create_target_directory_groups(yuzu-cmd)