Compare commits
2 Commits
clean-shor
...
im_steady_
Author | SHA1 | Date | |
---|---|---|---|
47a469804b | |||
3c3ca709de |
@ -781,40 +781,28 @@ add_library(core STATIC
|
|||||||
hle/service/ssl/ssl.cpp
|
hle/service/ssl/ssl.cpp
|
||||||
hle/service/ssl/ssl.h
|
hle/service/ssl/ssl.h
|
||||||
hle/service/ssl/ssl_backend.h
|
hle/service/ssl/ssl_backend.h
|
||||||
hle/service/time/clock_types.h
|
hle/service/time/clock_interfaces/steady_clock.cpp
|
||||||
hle/service/time/ephemeral_network_system_clock_context_writer.h
|
hle/service/time/clock_interfaces/steady_clock.h
|
||||||
hle/service/time/ephemeral_network_system_clock_core.h
|
hle/service/time/clock_interfaces/system_clock.cpp
|
||||||
hle/service/time/errors.h
|
hle/service/time/clock_interfaces/system_clock.h
|
||||||
hle/service/time/local_system_clock_context_writer.h
|
hle/service/time/clock_types/local_system_clock.cpp
|
||||||
hle/service/time/network_system_clock_context_writer.h
|
hle/service/time/clock_types/local_system_clock.h
|
||||||
hle/service/time/standard_local_system_clock_core.h
|
hle/service/time/clock_types/network_system_clock.cpp
|
||||||
hle/service/time/standard_network_system_clock_core.h
|
hle/service/time/clock_types/network_system_clock.h
|
||||||
hle/service/time/standard_steady_clock_core.cpp
|
hle/service/time/clock_types/steady_clock.cpp
|
||||||
hle/service/time/standard_steady_clock_core.h
|
hle/service/time/clock_types/steady_clock.h
|
||||||
hle/service/time/standard_user_system_clock_core.cpp
|
hle/service/time/clock_types/user_system_clock.cpp
|
||||||
hle/service/time/standard_user_system_clock_core.h
|
hle/service/time/clock_types/user_system_clock.h
|
||||||
hle/service/time/steady_clock_core.h
|
hle/service/time/time_zone/time_zone_service.cpp
|
||||||
hle/service/time/system_clock_context_update_callback.cpp
|
hle/service/time/time_zone/time_zone_service.h
|
||||||
hle/service/time/system_clock_context_update_callback.h
|
hle/service/time/time_zone/time_zone_types.h
|
||||||
hle/service/time/system_clock_core.cpp
|
|
||||||
hle/service/time/system_clock_core.h
|
|
||||||
hle/service/time/tick_based_steady_clock_core.cpp
|
|
||||||
hle/service/time/tick_based_steady_clock_core.h
|
|
||||||
hle/service/time/time.cpp
|
hle/service/time/time.cpp
|
||||||
hle/service/time/time.h
|
hle/service/time/time.h
|
||||||
hle/service/time/time_interface.cpp
|
|
||||||
hle/service/time/time_interface.h
|
|
||||||
hle/service/time/time_manager.cpp
|
hle/service/time/time_manager.cpp
|
||||||
hle/service/time/time_manager.h
|
hle/service/time/time_manager.h
|
||||||
hle/service/time/time_sharedmemory.cpp
|
hle/service/time/time_result.h
|
||||||
hle/service/time/time_sharedmemory.h
|
hle/service/time/time_types.h
|
||||||
hle/service/time/time_zone_content_manager.cpp
|
hle/service/time/time_util.h
|
||||||
hle/service/time/time_zone_content_manager.h
|
|
||||||
hle/service/time/time_zone_manager.cpp
|
|
||||||
hle/service/time/time_zone_manager.h
|
|
||||||
hle/service/time/time_zone_service.cpp
|
|
||||||
hle/service/time/time_zone_service.h
|
|
||||||
hle/service/time/time_zone_types.h
|
|
||||||
hle/service/usb/usb.cpp
|
hle/service/usb/usb.cpp
|
||||||
hle/service/usb/usb.h
|
hle/service/usb/usb.h
|
||||||
hle/service/vi/display/vi_display.cpp
|
hle/service/vi/display/vi_display.cpp
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
#include "core/hle/service/glue/glue_manager.h"
|
#include "core/hle/service/glue/glue_manager.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
#include "core/hle/service/time/time_manager.h"
|
|
||||||
#include "core/internal_network/network.h"
|
#include "core/internal_network/network.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
@ -133,7 +132,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
|||||||
struct System::Impl {
|
struct System::Impl {
|
||||||
explicit Impl(System& system)
|
explicit Impl(System& system)
|
||||||
: kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{},
|
: kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{},
|
||||||
cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system},
|
cpu_manager{system}, reporter{system}, applet_manager{system},
|
||||||
gpu_dirty_memory_write_manager{} {
|
gpu_dirty_memory_write_manager{} {
|
||||||
memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager);
|
memory.SetGPUDirtyManagers(gpu_dirty_memory_write_manager);
|
||||||
}
|
}
|
||||||
@ -148,8 +147,6 @@ struct System::Impl {
|
|||||||
core_timing.SetMulticore(is_multicore);
|
core_timing.SetMulticore(is_multicore);
|
||||||
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
|
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
|
||||||
|
|
||||||
RefreshTime();
|
|
||||||
|
|
||||||
// Create a default fs if one doesn't already exist.
|
// Create a default fs if one doesn't already exist.
|
||||||
if (virtual_filesystem == nullptr) {
|
if (virtual_filesystem == nullptr) {
|
||||||
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
|
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
|
||||||
@ -187,16 +184,6 @@ struct System::Impl {
|
|||||||
Initialize(system);
|
Initialize(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefreshTime() {
|
|
||||||
const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
|
|
||||||
const auto current_time =
|
|
||||||
std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
|
|
||||||
Settings::values.custom_rtc_differential =
|
|
||||||
(Settings::values.custom_rtc_enabled ? Settings::values.custom_rtc.GetValue()
|
|
||||||
: current_time) -
|
|
||||||
current_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||||
|
|
||||||
@ -270,9 +257,6 @@ struct System::Impl {
|
|||||||
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
|
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
|
||||||
services = std::make_unique<Service::Services>(service_manager, system);
|
services = std::make_unique<Service::Services>(service_manager, system);
|
||||||
|
|
||||||
// Initialize time manager, which must happen after kernel is created
|
|
||||||
time_manager.Initialize();
|
|
||||||
|
|
||||||
is_powered_on = true;
|
is_powered_on = true;
|
||||||
exit_locked = false;
|
exit_locked = false;
|
||||||
exit_requested = false;
|
exit_requested = false;
|
||||||
@ -425,7 +409,6 @@ struct System::Impl {
|
|||||||
service_manager.reset();
|
service_manager.reset();
|
||||||
cheat_engine.reset();
|
cheat_engine.reset();
|
||||||
telemetry_session.reset();
|
telemetry_session.reset();
|
||||||
time_manager.Shutdown();
|
|
||||||
core_timing.ClearPendingEvents();
|
core_timing.ClearPendingEvents();
|
||||||
app_loader.reset();
|
app_loader.reset();
|
||||||
audio_core.reset();
|
audio_core.reset();
|
||||||
@ -543,7 +526,6 @@ struct System::Impl {
|
|||||||
|
|
||||||
/// Service State
|
/// Service State
|
||||||
Service::Glue::ARPManager arp_manager;
|
Service::Glue::ARPManager arp_manager;
|
||||||
Service::Time::TimeManager time_manager;
|
|
||||||
|
|
||||||
/// Service manager
|
/// Service manager
|
||||||
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
||||||
@ -956,14 +938,6 @@ const Service::APM::Controller& System::GetAPMController() const {
|
|||||||
return impl->apm_controller;
|
return impl->apm_controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
Service::Time::TimeManager& System::GetTimeManager() {
|
|
||||||
return impl->time_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Service::Time::TimeManager& System::GetTimeManager() const {
|
|
||||||
return impl->time_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
void System::SetExitLocked(bool locked) {
|
void System::SetExitLocked(bool locked) {
|
||||||
impl->exit_locked = locked;
|
impl->exit_locked = locked;
|
||||||
}
|
}
|
||||||
@ -1075,13 +1049,7 @@ void System::Exit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void System::ApplySettings() {
|
void System::ApplySettings() {
|
||||||
impl->RefreshTime();
|
|
||||||
|
|
||||||
if (IsPoweredOn()) {
|
if (IsPoweredOn()) {
|
||||||
if (Settings::values.custom_rtc_enabled) {
|
|
||||||
const s64 posix_time{Settings::values.custom_rtc.GetValue()};
|
|
||||||
GetTimeManager().UpdateLocalSystemClockTime(posix_time);
|
|
||||||
}
|
|
||||||
Renderer().RefreshBaseSettings();
|
Renderer().RefreshBaseSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,10 +68,6 @@ namespace SM {
|
|||||||
class ServiceManager;
|
class ServiceManager;
|
||||||
} // namespace SM
|
} // namespace SM
|
||||||
|
|
||||||
namespace Time {
|
|
||||||
class TimeManager;
|
|
||||||
} // namespace Time
|
|
||||||
|
|
||||||
} // namespace Service
|
} // namespace Service
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
@ -405,9 +401,6 @@ public:
|
|||||||
[[nodiscard]] Service::APM::Controller& GetAPMController();
|
[[nodiscard]] Service::APM::Controller& GetAPMController();
|
||||||
[[nodiscard]] const Service::APM::Controller& GetAPMController() const;
|
[[nodiscard]] const Service::APM::Controller& GetAPMController() const;
|
||||||
|
|
||||||
[[nodiscard]] Service::Time::TimeManager& GetTimeManager();
|
|
||||||
[[nodiscard]] const Service::Time::TimeManager& GetTimeManager() const;
|
|
||||||
|
|
||||||
[[nodiscard]] Core::Debugger& GetDebugger();
|
[[nodiscard]] Core::Debugger& GetDebugger();
|
||||||
[[nodiscard]] const Core::Debugger& GetDebugger() const;
|
[[nodiscard]] const Core::Debugger& GetDebugger() const;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/file_sys/system_archive/time_zone_binary.h"
|
#include "core/file_sys/system_archive/time_zone_binary.h"
|
||||||
#include "core/file_sys/vfs_vector.h"
|
#include "core/file_sys/vfs_vector.h"
|
||||||
#include "core/hle/service/time/time_zone_types.h"
|
#include "core/hle/service/time/time_zone/time_zone_types.h"
|
||||||
|
|
||||||
#include "nx_tzdb.h"
|
#include "nx_tzdb.h"
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include "core/hle/service/nfc/common/device.h"
|
#include "core/hle/service/nfc/common/device.h"
|
||||||
#include "core/hle/service/nfc/mifare_result.h"
|
#include "core/hle/service/nfc/mifare_result.h"
|
||||||
#include "core/hle/service/nfc/nfc_result.h"
|
#include "core/hle/service/nfc/nfc_result.h"
|
||||||
#include "core/hle/service/time/time_manager.h"
|
|
||||||
|
|
||||||
namespace Service::NFC {
|
namespace Service::NFC {
|
||||||
NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
|
NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
|
||||||
@ -393,12 +392,12 @@ Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> paramet
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
|
//Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
|
||||||
std::span<const u8> command_data,
|
// std::span<const u8> command_data,
|
||||||
std::span<u8> out_data) {
|
// std::span<u8> out_data) {
|
||||||
// Not implemented
|
// // Not implemented
|
||||||
return ResultSuccess;
|
// return ResultSuccess;
|
||||||
}
|
//}
|
||||||
|
|
||||||
Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) {
|
Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target_) {
|
||||||
if (device_state != DeviceState::TagFound) {
|
if (device_state != DeviceState::TagFound) {
|
||||||
@ -1390,27 +1389,28 @@ void NfcDevice::SetAmiiboName(NFP::AmiiboSettings& settings,
|
|||||||
}
|
}
|
||||||
|
|
||||||
NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
|
NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
|
||||||
const auto& time_zone_manager =
|
//const auto& time_zone_manager =
|
||||||
system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager();
|
// system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager();
|
||||||
Time::TimeZone::CalendarInfo calendar_info{};
|
//Time::TimeZone::CalendarInfo calendar_info{};
|
||||||
NFP::AmiiboDate amiibo_date{};
|
NFP::AmiiboDate amiibo_date{};
|
||||||
|
|
||||||
amiibo_date.SetYear(2000);
|
amiibo_date.SetYear(2000);
|
||||||
amiibo_date.SetMonth(1);
|
amiibo_date.SetMonth(1);
|
||||||
amiibo_date.SetDay(1);
|
amiibo_date.SetDay(1);
|
||||||
|
|
||||||
if (time_zone_manager.ToCalendarTime({}, posix_time, calendar_info) == ResultSuccess) {
|
//if (time_zone_manager.ToCalendarTime({}, posix_time, calendar_info) == ResultSuccess) {
|
||||||
amiibo_date.SetYear(calendar_info.time.year);
|
// amiibo_date.SetYear(calendar_info.time.year);
|
||||||
amiibo_date.SetMonth(calendar_info.time.month);
|
// amiibo_date.SetMonth(calendar_info.time.month);
|
||||||
amiibo_date.SetDay(calendar_info.time.day);
|
// amiibo_date.SetDay(calendar_info.time.day);
|
||||||
}
|
//}
|
||||||
|
|
||||||
return amiibo_date;
|
return amiibo_date;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 NfcDevice::GetCurrentPosixTime() const {
|
u64 NfcDevice::GetCurrentPosixTime() const {
|
||||||
auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
//auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
||||||
return standard_steady_clock.GetCurrentTimePoint(system).time_point;
|
//return standard_steady_clock.GetCurrentTimePoint(system).time_point;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 NfcDevice::RemoveVersionByte(u64 application_id) const {
|
u64 NfcDevice::RemoveVersionByte(u64 application_id) const {
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include "core/hle/service/nfc/nfc_types.h"
|
#include "core/hle/service/nfc/nfc_types.h"
|
||||||
#include "core/hle/service/nfp/nfp_types.h"
|
#include "core/hle/service/nfp/nfp_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
class KEvent;
|
class KEvent;
|
||||||
@ -49,8 +48,8 @@ public:
|
|||||||
|
|
||||||
Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters);
|
Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters);
|
||||||
|
|
||||||
Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
|
//Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
|
||||||
std::span<const u8> command_data, std::span<u8> out_data);
|
// std::span<const u8> command_data, std::span<u8> out_data);
|
||||||
|
|
||||||
Result Mount(NFP::ModelType model_type, NFP::MountTarget mount_target);
|
Result Mount(NFP::ModelType model_type, NFP::MountTarget mount_target);
|
||||||
Result Unmount();
|
Result Unmount();
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
#include "core/hle/service/nfc/common/device.h"
|
#include "core/hle/service/nfc/common/device.h"
|
||||||
#include "core/hle/service/nfc/common/device_manager.h"
|
#include "core/hle/service/nfc/common/device_manager.h"
|
||||||
#include "core/hle/service/nfc/nfc_result.h"
|
#include "core/hle/service/nfc/nfc_result.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
#include "core/hle/service/time/time_manager.h"
|
|
||||||
|
|
||||||
namespace Service::NFC {
|
namespace Service::NFC {
|
||||||
|
|
||||||
@ -81,14 +79,14 @@ Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (skip_fatal_errors) {
|
if (skip_fatal_errors) {
|
||||||
constexpr u64 MinimumRecoveryTime = 60;
|
//constexpr u64 MinimumRecoveryTime = 60;
|
||||||
auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
//auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
||||||
const u64 elapsed_time = standard_steady_clock.GetCurrentTimePoint(system).time_point -
|
//const u64 elapsed_time = standard_steady_clock.GetCurrentTimePoint(system).time_point -
|
||||||
time_since_last_error;
|
// time_since_last_error;
|
||||||
|
|
||||||
if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) {
|
//if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
if (device->GetCurrentState() == DeviceState::Unavailable) {
|
if (device->GetCurrentState() == DeviceState::Unavailable) {
|
||||||
continue;
|
continue;
|
||||||
@ -249,22 +247,22 @@ Result DeviceManager::WriteMifare(u64 device_handle,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::SendCommandByPassThrough(u64 device_handle,
|
//Result DeviceManager::SendCommandByPassThrough(u64 device_handle,
|
||||||
const Time::Clock::TimeSpanType& timeout,
|
// const Time::Clock::TimeSpanType& timeout,
|
||||||
std::span<const u8> command_data,
|
// std::span<const u8> command_data,
|
||||||
std::span<u8> out_data) {
|
// std::span<u8> out_data) {
|
||||||
std::scoped_lock lock{mutex};
|
// std::scoped_lock lock{mutex};
|
||||||
|
//
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
// std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
auto result = GetDeviceHandle(device_handle, device);
|
// auto result = GetDeviceHandle(device_handle, device);
|
||||||
|
//
|
||||||
if (result.IsSuccess()) {
|
// if (result.IsSuccess()) {
|
||||||
result = device->SendCommandByPassThrough(timeout, command_data, out_data);
|
// result = device->SendCommandByPassThrough(timeout, command_data, out_data);
|
||||||
result = VerifyDeviceResult(device, result);
|
// result = VerifyDeviceResult(device, result);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return result;
|
// return result;
|
||||||
}
|
//}
|
||||||
|
|
||||||
Result DeviceManager::Mount(u64 device_handle, NFP::ModelType model_type,
|
Result DeviceManager::Mount(u64 device_handle, NFP::ModelType model_type,
|
||||||
NFP::MountTarget mount_target) {
|
NFP::MountTarget mount_target) {
|
||||||
@ -738,11 +736,11 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
|
|||||||
return device_state;
|
return device_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation_result == ResultUnknown112 || operation_result == ResultUnknown114 ||
|
//if (operation_result == ResultUnknown112 || operation_result == ResultUnknown114 ||
|
||||||
operation_result == ResultUnknown115) {
|
// operation_result == ResultUnknown115) {
|
||||||
auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
// auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
||||||
time_since_last_error = standard_steady_clock.GetCurrentTimePoint(system).time_point;
|
// time_since_last_error = standard_steady_clock.GetCurrentTimePoint(system).time_point;
|
||||||
}
|
//}
|
||||||
|
|
||||||
return operation_result;
|
return operation_result;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "core/hle/service/nfc/nfc_types.h"
|
#include "core/hle/service/nfc/nfc_types.h"
|
||||||
#include "core/hle/service/nfp/nfp_types.h"
|
#include "core/hle/service/nfp/nfp_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Service::NFC {
|
namespace Service::NFC {
|
||||||
class NfcDevice;
|
class NfcDevice;
|
||||||
@ -42,8 +41,8 @@ public:
|
|||||||
std::span<MifareReadBlockData> read_data);
|
std::span<MifareReadBlockData> read_data);
|
||||||
Result WriteMifare(u64 device_handle,
|
Result WriteMifare(u64 device_handle,
|
||||||
std::span<const MifareWriteBlockParameter> write_parameters);
|
std::span<const MifareWriteBlockParameter> write_parameters);
|
||||||
Result SendCommandByPassThrough(u64 device_handle, const Time::Clock::TimeSpanType& timeout,
|
//Result SendCommandByPassThrough(u64 device_handle, const Time::Clock::TimeSpanType& timeout,
|
||||||
std::span<const u8> command_data, std::span<u8> out_data);
|
// std::span<const u8> command_data, std::span<u8> out_data);
|
||||||
|
|
||||||
// Nfp device manager
|
// Nfp device manager
|
||||||
Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target);
|
Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target);
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "core/hle/service/nfc/nfc_result.h"
|
#include "core/hle/service/nfc/nfc_result.h"
|
||||||
#include "core/hle/service/nfc/nfc_types.h"
|
#include "core/hle/service/nfc/nfc_types.h"
|
||||||
#include "core/hle/service/nfp/nfp_result.h"
|
#include "core/hle/service/nfp/nfp_result.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Service::NFC {
|
namespace Service::NFC {
|
||||||
|
|
||||||
@ -261,14 +260,15 @@ void NfcInterface::WriteMifare(HLERequestContext& ctx) {
|
|||||||
void NfcInterface::SendCommandByPassThrough(HLERequestContext& ctx) {
|
void NfcInterface::SendCommandByPassThrough(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto device_handle{rp.Pop<u64>()};
|
const auto device_handle{rp.Pop<u64>()};
|
||||||
const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()};
|
//const auto timeout{rp.PopRaw<Time::Clock::TimeSpanType>()};
|
||||||
const auto command_data{ctx.ReadBuffer()};
|
const auto command_data{ctx.ReadBuffer()};
|
||||||
LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}",
|
LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, timeout={}, data_size={}",
|
||||||
device_handle, timeout.ToSeconds(), command_data.size());
|
device_handle, 0, command_data.size());
|
||||||
|
|
||||||
std::vector<u8> out_data(1);
|
std::vector<u8> out_data(1);
|
||||||
auto result =
|
//auto result =
|
||||||
GetManager()->SendCommandByPassThrough(device_handle, timeout, command_data, out_data);
|
// GetManager()->SendCommandByPassThrough(device_handle, timeout, command_data, out_data);
|
||||||
|
Result result = ResultSuccess;
|
||||||
result = TranslateResultToServiceError(result);
|
result = TranslateResultToServiceError(result);
|
||||||
|
|
||||||
if (result.IsError()) {
|
if (result.IsError()) {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "common/uuid.h"
|
#include "common/uuid.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
@ -254,7 +254,7 @@ private:
|
|||||||
struct InitialLaunchSettings {
|
struct InitialLaunchSettings {
|
||||||
InitialLaunchFlag flags;
|
InitialLaunchFlag flags;
|
||||||
INSERT_PADDING_BYTES(0x4);
|
INSERT_PADDING_BYTES(0x4);
|
||||||
Time::Clock::SteadyClockTimePoint timestamp;
|
Time::SteadyClockTimePoint timestamp;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size");
|
static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size");
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ private:
|
|||||||
EulaVersionClockType clock_type;
|
EulaVersionClockType clock_type;
|
||||||
INSERT_PADDING_BYTES(0x4);
|
INSERT_PADDING_BYTES(0x4);
|
||||||
s64 posix_time;
|
s64 posix_time;
|
||||||
Time::Clock::SteadyClockTimePoint timestamp;
|
Time::SteadyClockTimePoint timestamp;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size");
|
static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size");
|
||||||
|
|
||||||
|
40
src/core/hle/service/time/clock_interfaces/steady_clock.cpp
Normal file
40
src/core/hle/service/time/clock_interfaces/steady_clock.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/time/clock_types/steady_clock.h"
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
ISteadyClock::ISteadyClock(Core::System& system_) : ServiceFramework{system_, "ISteadyClock"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
|
||||||
|
{2, nullptr, "GetTestOffset"},
|
||||||
|
{3, nullptr, "SetTestOffset"},
|
||||||
|
{100, nullptr, "GetRtcValue"},
|
||||||
|
{101, nullptr, "IsRtcResetDetected"},
|
||||||
|
{102, nullptr, "GetSetupResultValue"},
|
||||||
|
{200, nullptr, "GetInternalOffset"},
|
||||||
|
{201, nullptr, "SetInternalOffset"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISteadyClock::~ISteadyClock() = default;
|
||||||
|
|
||||||
|
void ISteadyClock::GetCurrentTimePoint(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ISteadyClock::IsInitialized() {
|
||||||
|
return is_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
31
src/core/hle/service/time/clock_interfaces/steady_clock.h
Normal file
31
src/core/hle/service/time/clock_interfaces/steady_clock.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
class ISteadyClock : public ServiceFramework<ISteadyClock> {
|
||||||
|
public:
|
||||||
|
explicit ISteadyClock(Core::System& system_);
|
||||||
|
~ISteadyClock();
|
||||||
|
|
||||||
|
bool IsInitialized();
|
||||||
|
|
||||||
|
void UpdateTime();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetCurrentTimePoint(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
bool is_initialized{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
48
src/core/hle/service/time/clock_interfaces/system_clock.cpp
Normal file
48
src/core/hle/service/time/clock_interfaces/system_clock.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/time/clock_interfaces/system_clock.h"
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
ISystemClock::ISystemClock(Core::System& system_) : ServiceFramework{system_, "ISystemClock"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
|
||||||
|
{1, nullptr, "SetCurrentTime"},
|
||||||
|
{2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
|
||||||
|
{3, nullptr, "SetSystemClockContext"},
|
||||||
|
{4, nullptr, "GetOperationEventReadableHandle"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISystemClock::~ISystemClock() = default;
|
||||||
|
|
||||||
|
void ISystemClock::GetCurrentTime(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
|
s64 posix_time{};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<s64>(posix_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISystemClock::GetSystemClockContext(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemClock::GetClockContext(SystemClockContext& out_context) {
|
||||||
|
out_context = context;
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
33
src/core/hle/service/time/clock_interfaces/system_clock.h
Normal file
33
src/core/hle/service/time/clock_interfaces/system_clock.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
class ISystemClock : public ServiceFramework<ISystemClock> {
|
||||||
|
public:
|
||||||
|
explicit ISystemClock(Core::System& system_);
|
||||||
|
~ISystemClock();
|
||||||
|
|
||||||
|
Result GetClockContext(SystemClockContext& out_context);
|
||||||
|
bool IsStandardNetworkSystemClockAccuracySufficient();
|
||||||
|
|
||||||
|
void UpdateTime();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetCurrentTime(HLERequestContext& ctx);
|
||||||
|
void GetSystemClockContext(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
SystemClockContext context;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/time/clock_types/steady_clock.h"
|
||||||
|
|
||||||
|
namespace Service::Time {} // namespace Service::Time
|
21
src/core/hle/service/time/clock_types/local_system_clock.h
Normal file
21
src/core/hle/service/time/clock_types/local_system_clock.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/time/clock_interfaces/system_clock.h"
|
||||||
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
class LocalSystemClock : public ISystemClock {
|
||||||
|
public:
|
||||||
|
explicit LocalSystemClock();
|
||||||
|
~LocalSystemClock();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/time/clock_types/steady_clock.h"
|
||||||
|
|
||||||
|
namespace Service::Time {} // namespace Service::Time
|
21
src/core/hle/service/time/clock_types/network_system_clock.h
Normal file
21
src/core/hle/service/time/clock_types/network_system_clock.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/time/clock_interfaces/system_clock.h"
|
||||||
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
class NetworkSystemClock : public ISystemClock {
|
||||||
|
public:
|
||||||
|
explicit NetworkSystemClock();
|
||||||
|
~NetworkSystemClock();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
9
src/core/hle/service/time/clock_types/steady_clock.cpp
Normal file
9
src/core/hle/service/time/clock_types/steady_clock.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/time/clock_types/steady_clock.h"
|
||||||
|
#include "core/hle/service/time/clock_types/system_clock.h"
|
||||||
|
|
||||||
|
namespace Service::Time {} // namespace Service::Time
|
21
src/core/hle/service/time/clock_types/steady_clock.h
Normal file
21
src/core/hle/service/time/clock_types/steady_clock.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/time/clock_interfaces/steady_clock.h"
|
||||||
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
class SteadyClock : public ISteadyClock {
|
||||||
|
public:
|
||||||
|
explicit SteadyClock();
|
||||||
|
~SteadyClock();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/time/clock_types/steady_clock.h"
|
||||||
|
|
||||||
|
namespace Service::Time {} // namespace Service::Time
|
21
src/core/hle/service/time/clock_types/user_system_clock.h
Normal file
21
src/core/hle/service/time/clock_types/user_system_clock.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/time/clock_interfaces/system_clock.h"
|
||||||
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
class UserSystemClock : public ISystemClock {
|
||||||
|
public:
|
||||||
|
explicit UserSystemClock();
|
||||||
|
~UserSystemClock();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
@ -1,15 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class EphemeralNetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback {
|
|
||||||
public:
|
|
||||||
EphemeralNetworkSystemClockContextWriter() : SystemClockContextUpdateCallback{} {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,16 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/system_clock_core.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class EphemeralNetworkSystemClockCore final : public SystemClockCore {
|
|
||||||
public:
|
|
||||||
explicit EphemeralNetworkSystemClockCore(SteadyClockCore& steady_clock_core_)
|
|
||||||
: SystemClockCore{steady_clock_core_} {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,21 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/result.h"
|
|
||||||
|
|
||||||
namespace Service::Time {
|
|
||||||
|
|
||||||
constexpr Result ERROR_PERMISSION_DENIED{ErrorModule::Time, 1};
|
|
||||||
constexpr Result ERROR_TIME_MISMATCH{ErrorModule::Time, 102};
|
|
||||||
constexpr Result ERROR_UNINITIALIZED_CLOCK{ErrorModule::Time, 103};
|
|
||||||
constexpr Result ERROR_TIME_NOT_FOUND{ErrorModule::Time, 200};
|
|
||||||
constexpr Result ERROR_OVERFLOW{ErrorModule::Time, 201};
|
|
||||||
constexpr Result ERROR_LOCATION_NAME_TOO_LONG{ErrorModule::Time, 801};
|
|
||||||
constexpr Result ERROR_OUT_OF_RANGE{ErrorModule::Time, 902};
|
|
||||||
constexpr Result ERROR_TIME_ZONE_CONVERSION_FAILED{ErrorModule::Time, 903};
|
|
||||||
constexpr Result ERROR_TIME_ZONE_NOT_FOUND{ErrorModule::Time, 989};
|
|
||||||
constexpr Result ERROR_NOT_IMPLEMENTED{ErrorModule::Time, 990};
|
|
||||||
|
|
||||||
} // namespace Service::Time
|
|
@ -1,26 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
|
||||||
#include "core/hle/service/time/time_sharedmemory.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback {
|
|
||||||
public:
|
|
||||||
explicit LocalSystemClockContextWriter(SharedMemory& shared_memory_)
|
|
||||||
: SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Result Update() override {
|
|
||||||
shared_memory.UpdateLocalSystemClockContext(context);
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SharedMemory& shared_memory;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,27 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/errors.h"
|
|
||||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
|
||||||
#include "core/hle/service/time/time_sharedmemory.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback {
|
|
||||||
public:
|
|
||||||
explicit NetworkSystemClockContextWriter(SharedMemory& shared_memory_)
|
|
||||||
: SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Result Update() override {
|
|
||||||
shared_memory.UpdateNetworkSystemClockContext(context);
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SharedMemory& shared_memory;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,16 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/system_clock_core.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class StandardLocalSystemClockCore final : public SystemClockCore {
|
|
||||||
public:
|
|
||||||
explicit StandardLocalSystemClockCore(SteadyClockCore& steady_clock_core_)
|
|
||||||
: SystemClockCore{steady_clock_core_} {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,45 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
#include "core/hle/service/time/steady_clock_core.h"
|
|
||||||
#include "core/hle/service/time/system_clock_core.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class StandardNetworkSystemClockCore final : public SystemClockCore {
|
|
||||||
public:
|
|
||||||
explicit StandardNetworkSystemClockCore(SteadyClockCore& steady_clock_core_)
|
|
||||||
: SystemClockCore{steady_clock_core_} {}
|
|
||||||
|
|
||||||
void SetStandardNetworkClockSufficientAccuracy(TimeSpanType value) {
|
|
||||||
standard_network_clock_sufficient_accuracy = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) const {
|
|
||||||
SystemClockContext clock_ctx{};
|
|
||||||
if (GetClockContext(system, clock_ctx) != ResultSuccess) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
s64 span{};
|
|
||||||
if (clock_ctx.steady_time_point.GetSpanBetween(
|
|
||||||
GetSteadyClockCore().GetCurrentTimePoint(system), span) != ResultSuccess) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return TimeSpanType{span}.nanoseconds <
|
|
||||||
standard_network_clock_sufficient_accuracy.nanoseconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
TimeSpanType standard_network_clock_sufficient_accuracy{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,24 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/hardware_properties.h"
|
|
||||||
#include "core/hle/service/time/standard_steady_clock_core.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
|
|
||||||
const TimeSpanType ticks_time_span{
|
|
||||||
TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};
|
|
||||||
TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds};
|
|
||||||
|
|
||||||
if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) {
|
|
||||||
raw_time_point.nanoseconds = cached_raw_time_point.nanoseconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
cached_raw_time_point = raw_time_point;
|
|
||||||
return raw_time_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,41 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
#include "core/hle/service/time/steady_clock_core.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class StandardSteadyClockCore final : public SteadyClockCore {
|
|
||||||
public:
|
|
||||||
SteadyClockTimePoint GetTimePoint(Core::System& system) override {
|
|
||||||
return {GetCurrentRawTimePoint(system).ToSeconds(), GetClockSourceId()};
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeSpanType GetInternalOffset() const override {
|
|
||||||
return internal_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetInternalOffset(TimeSpanType value) override {
|
|
||||||
internal_offset = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeSpanType GetCurrentRawTimePoint(Core::System& system) override;
|
|
||||||
|
|
||||||
void SetSetupValue(TimeSpanType value) {
|
|
||||||
setup_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
TimeSpanType setup_value{};
|
|
||||||
TimeSpanType internal_offset{};
|
|
||||||
TimeSpanType cached_raw_time_point{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,81 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hle/kernel/k_event.h"
|
|
||||||
#include "core/hle/service/time/standard_local_system_clock_core.h"
|
|
||||||
#include "core/hle/service/time/standard_network_system_clock_core.h"
|
|
||||||
#include "core/hle/service/time/standard_user_system_clock_core.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
StandardUserSystemClockCore::StandardUserSystemClockCore(
|
|
||||||
StandardLocalSystemClockCore& local_system_clock_core_,
|
|
||||||
StandardNetworkSystemClockCore& network_system_clock_core_, Core::System& system_)
|
|
||||||
: SystemClockCore(local_system_clock_core_.GetSteadyClockCore()),
|
|
||||||
local_system_clock_core{local_system_clock_core_},
|
|
||||||
network_system_clock_core{network_system_clock_core_},
|
|
||||||
auto_correction_time{SteadyClockTimePoint::GetRandom()}, service_context{
|
|
||||||
system_,
|
|
||||||
"StandardUserSystemClockCore"} {
|
|
||||||
auto_correction_event =
|
|
||||||
service_context.CreateEvent("StandardUserSystemClockCore:AutoCorrectionEvent");
|
|
||||||
}
|
|
||||||
|
|
||||||
StandardUserSystemClockCore::~StandardUserSystemClockCore() {
|
|
||||||
service_context.CloseEvent(auto_correction_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
|
|
||||||
bool value) {
|
|
||||||
if (const Result result{ApplyAutomaticCorrection(system, value)}; result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto_correction_enabled = value;
|
|
||||||
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result StandardUserSystemClockCore::GetClockContext(Core::System& system,
|
|
||||||
SystemClockContext& ctx) const {
|
|
||||||
if (const Result result{ApplyAutomaticCorrection(system, false)}; result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return local_system_clock_core.GetClockContext(system, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result StandardUserSystemClockCore::Flush(const SystemClockContext&) {
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
return ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result StandardUserSystemClockCore::SetClockContext(const SystemClockContext&) {
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
return ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& system,
|
|
||||||
bool value) const {
|
|
||||||
if (auto_correction_enabled == value) {
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!network_system_clock_core.IsClockSetup(system)) {
|
|
||||||
return ERROR_UNINITIALIZED_CLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SystemClockContext ctx{};
|
|
||||||
if (const Result result{network_system_clock_core.GetClockContext(system, ctx)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
local_system_clock_core.SetClockContext(ctx);
|
|
||||||
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,63 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
#include "core/hle/service/time/system_clock_core.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
class KEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class StandardLocalSystemClockCore;
|
|
||||||
class StandardNetworkSystemClockCore;
|
|
||||||
|
|
||||||
class StandardUserSystemClockCore final : public SystemClockCore {
|
|
||||||
public:
|
|
||||||
StandardUserSystemClockCore(StandardLocalSystemClockCore& local_system_clock_core_,
|
|
||||||
StandardNetworkSystemClockCore& network_system_clock_core_,
|
|
||||||
Core::System& system_);
|
|
||||||
|
|
||||||
~StandardUserSystemClockCore() override;
|
|
||||||
|
|
||||||
Result SetAutomaticCorrectionEnabled(Core::System& system, bool value);
|
|
||||||
|
|
||||||
Result GetClockContext(Core::System& system, SystemClockContext& ctx) const override;
|
|
||||||
|
|
||||||
bool IsAutomaticCorrectionEnabled() const {
|
|
||||||
return auto_correction_enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint steady_clock_time_point) {
|
|
||||||
auto_correction_time = steady_clock_time_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Result Flush(const SystemClockContext&) override;
|
|
||||||
|
|
||||||
Result SetClockContext(const SystemClockContext&) override;
|
|
||||||
|
|
||||||
Result ApplyAutomaticCorrection(Core::System& system, bool value) const;
|
|
||||||
|
|
||||||
const SteadyClockTimePoint& GetAutomaticCorrectionUpdatedTime() const {
|
|
||||||
return auto_correction_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
StandardLocalSystemClockCore& local_system_clock_core;
|
|
||||||
StandardNetworkSystemClockCore& network_system_clock_core;
|
|
||||||
bool auto_correction_enabled{};
|
|
||||||
SteadyClockTimePoint auto_correction_time;
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
Kernel::KEvent* auto_correction_event;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,55 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "common/uuid.h"
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class SteadyClockCore {
|
|
||||||
public:
|
|
||||||
SteadyClockCore() = default;
|
|
||||||
virtual ~SteadyClockCore() = default;
|
|
||||||
|
|
||||||
const Common::UUID& GetClockSourceId() const {
|
|
||||||
return clock_source_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetClockSourceId(const Common::UUID& value) {
|
|
||||||
clock_source_id = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual TimeSpanType GetInternalOffset() const = 0;
|
|
||||||
|
|
||||||
virtual void SetInternalOffset(TimeSpanType internal_offset) = 0;
|
|
||||||
|
|
||||||
virtual SteadyClockTimePoint GetTimePoint(Core::System& system) = 0;
|
|
||||||
|
|
||||||
virtual TimeSpanType GetCurrentRawTimePoint(Core::System& system) = 0;
|
|
||||||
|
|
||||||
SteadyClockTimePoint GetCurrentTimePoint(Core::System& system) {
|
|
||||||
SteadyClockTimePoint result{GetTimePoint(system)};
|
|
||||||
result.time_point += GetInternalOffset().ToSeconds();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsInitialized() const {
|
|
||||||
return is_initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarkAsInitialized() {
|
|
||||||
is_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Common::UUID clock_source_id{Common::UUID::MakeRandom()};
|
|
||||||
bool is_initialized{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,54 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/kernel/k_event.h"
|
|
||||||
#include "core/hle/service/time/errors.h"
|
|
||||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
SystemClockContextUpdateCallback::SystemClockContextUpdateCallback() = default;
|
|
||||||
SystemClockContextUpdateCallback::~SystemClockContextUpdateCallback() = default;
|
|
||||||
|
|
||||||
bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& value) const {
|
|
||||||
if (has_context) {
|
|
||||||
return context.offset != value.offset ||
|
|
||||||
context.steady_time_point.clock_source_id != value.steady_time_point.clock_source_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemClockContextUpdateCallback::RegisterOperationEvent(
|
|
||||||
std::shared_ptr<Kernel::KEvent>&& event) {
|
|
||||||
operation_event_list.emplace_back(std::move(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemClockContextUpdateCallback::BroadcastOperationEvent() {
|
|
||||||
for (const auto& event : operation_event_list) {
|
|
||||||
event->Signal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SystemClockContextUpdateCallback::Update(const SystemClockContext& value) {
|
|
||||||
Result result{ResultSuccess};
|
|
||||||
|
|
||||||
if (NeedUpdate(value)) {
|
|
||||||
context = value;
|
|
||||||
has_context = true;
|
|
||||||
|
|
||||||
result = Update();
|
|
||||||
|
|
||||||
if (result == ResultSuccess) {
|
|
||||||
BroadcastOperationEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SystemClockContextUpdateCallback::Update() {
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,43 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
class KEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
|
|
||||||
// This code was released under public domain.
|
|
||||||
|
|
||||||
class SystemClockContextUpdateCallback {
|
|
||||||
public:
|
|
||||||
SystemClockContextUpdateCallback();
|
|
||||||
virtual ~SystemClockContextUpdateCallback();
|
|
||||||
|
|
||||||
bool NeedUpdate(const SystemClockContext& value) const;
|
|
||||||
|
|
||||||
void RegisterOperationEvent(std::shared_ptr<Kernel::KEvent>&& event);
|
|
||||||
|
|
||||||
void BroadcastOperationEvent();
|
|
||||||
|
|
||||||
Result Update(const SystemClockContext& value);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual Result Update();
|
|
||||||
|
|
||||||
SystemClockContext context{};
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool has_context{};
|
|
||||||
std::vector<std::shared_ptr<Kernel::KEvent>> operation_event_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,71 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/time/steady_clock_core.h"
|
|
||||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
|
||||||
#include "core/hle/service/time/system_clock_core.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core_)
|
|
||||||
: steady_clock_core{steady_clock_core_} {
|
|
||||||
context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId();
|
|
||||||
}
|
|
||||||
|
|
||||||
SystemClockCore::~SystemClockCore() = default;
|
|
||||||
|
|
||||||
Result SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time) const {
|
|
||||||
posix_time = 0;
|
|
||||||
|
|
||||||
const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
|
|
||||||
|
|
||||||
SystemClockContext clock_context{};
|
|
||||||
if (const Result result{GetClockContext(system, clock_context)}; result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_time_point.clock_source_id != clock_context.steady_time_point.clock_source_id) {
|
|
||||||
return ERROR_TIME_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
posix_time = clock_context.offset + current_time_point.time_point;
|
|
||||||
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SystemClockCore::SetCurrentTime(Core::System& system, s64 posix_time) {
|
|
||||||
const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
|
|
||||||
const SystemClockContext clock_context{posix_time - current_time_point.time_point,
|
|
||||||
current_time_point};
|
|
||||||
|
|
||||||
if (const Result result{SetClockContext(clock_context)}; result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return Flush(clock_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SystemClockCore::Flush(const SystemClockContext& clock_context) {
|
|
||||||
if (!system_clock_context_update_callback) {
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
return system_clock_context_update_callback->Update(clock_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SystemClockCore::SetSystemClockContext(const SystemClockContext& clock_context) {
|
|
||||||
if (const Result result{SetClockContext(clock_context)}; result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return Flush(clock_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SystemClockCore::IsClockSetup(Core::System& system) const {
|
|
||||||
SystemClockContext value{};
|
|
||||||
if (GetClockContext(system, value) == ResultSuccess) {
|
|
||||||
const SteadyClockTimePoint steady_clock_time_point{
|
|
||||||
steady_clock_core.GetCurrentTimePoint(system)};
|
|
||||||
return steady_clock_time_point.clock_source_id == value.steady_time_point.clock_source_id;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,72 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class SteadyClockCore;
|
|
||||||
class SystemClockContextUpdateCallback;
|
|
||||||
|
|
||||||
// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
|
|
||||||
// This code was released under public domain.
|
|
||||||
|
|
||||||
class SystemClockCore {
|
|
||||||
public:
|
|
||||||
explicit SystemClockCore(SteadyClockCore& steady_clock_core_);
|
|
||||||
virtual ~SystemClockCore();
|
|
||||||
|
|
||||||
SteadyClockCore& GetSteadyClockCore() const {
|
|
||||||
return steady_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result GetCurrentTime(Core::System& system, s64& posix_time) const;
|
|
||||||
|
|
||||||
Result SetCurrentTime(Core::System& system, s64 posix_time);
|
|
||||||
|
|
||||||
virtual Result GetClockContext([[maybe_unused]] Core::System& system,
|
|
||||||
SystemClockContext& value) const {
|
|
||||||
value = context;
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Result SetClockContext(const SystemClockContext& value) {
|
|
||||||
context = value;
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Result Flush(const SystemClockContext& clock_context);
|
|
||||||
|
|
||||||
void SetUpdateCallbackInstance(std::shared_ptr<SystemClockContextUpdateCallback> callback) {
|
|
||||||
system_clock_context_update_callback = std::move(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SetSystemClockContext(const SystemClockContext& context);
|
|
||||||
|
|
||||||
bool IsInitialized() const {
|
|
||||||
return is_initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarkAsInitialized() {
|
|
||||||
is_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsClockSetup(Core::System& system) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
SteadyClockCore& steady_clock_core;
|
|
||||||
SystemClockContext context{};
|
|
||||||
bool is_initialized{};
|
|
||||||
std::shared_ptr<SystemClockContextUpdateCallback> system_clock_context_update_callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,22 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/hardware_properties.h"
|
|
||||||
#include "core/hle/service/time/tick_based_steady_clock_core.h"
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) {
|
|
||||||
const TimeSpanType ticks_time_span{
|
|
||||||
TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};
|
|
||||||
|
|
||||||
return {ticks_time_span.ToSeconds(), GetClockSourceId()};
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeSpanType TickBasedSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
|
|
||||||
return TimeSpanType::FromSeconds(GetTimePoint(system).time_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -1,28 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
#include "core/hle/service/time/steady_clock_core.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
|
||||||
|
|
||||||
class TickBasedSteadyClockCore final : public SteadyClockCore {
|
|
||||||
public:
|
|
||||||
TimeSpanType GetInternalOffset() const override {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetInternalOffset(TimeSpanType internal_offset) override {}
|
|
||||||
|
|
||||||
SteadyClockTimePoint GetTimePoint(Core::System& system) override;
|
|
||||||
|
|
||||||
TimeSpanType GetCurrentRawTimePoint(Core::System& system) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
|
@ -4,29 +4,45 @@
|
|||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hardware_properties.h"
|
|
||||||
#include "core/hle/kernel/kernel.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/service.h"
|
||||||
|
#include "core/hle/service/time/clock_interfaces/steady_clock.h"
|
||||||
|
#include "core/hle/service/time/clock_interfaces/system_clock.h"
|
||||||
#include "core/hle/service/time/time.h"
|
#include "core/hle/service/time/time.h"
|
||||||
#include "core/hle/service/time/time_interface.h"
|
|
||||||
#include "core/hle/service/time/time_manager.h"
|
#include "core/hle/service/time/time_manager.h"
|
||||||
#include "core/hle/service/time/time_sharedmemory.h"
|
#include "core/hle/service/time/time_types.h"
|
||||||
#include "core/hle/service/time/time_zone_service.h"
|
#include "core/hle/service/time/time_util.h"
|
||||||
|
#include "core/hle/service/time/time_zone/time_zone_service.h"
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
|
||||||
class ISystemClock final : public ServiceFramework<ISystemClock> {
|
class IStaticService final : public ServiceFramework<IStaticService> {
|
||||||
public:
|
public:
|
||||||
explicit ISystemClock(Clock::SystemClockCore& clock_core_, Core::System& system_)
|
explicit IStaticService(const char* name, Core::System& system_)
|
||||||
: ServiceFramework{system_, "ISystemClock"}, clock_core{clock_core_} {
|
: ServiceFramework{system_, name} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
|
{0, &IStaticService::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||||
{1, nullptr, "SetCurrentTime"},
|
{1, &IStaticService::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
||||||
{2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
|
{2, &IStaticService::GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||||
{3, nullptr, "SetSystemClockContext"},
|
{3, &IStaticService::GetTimeZoneService, "GetTimeZoneService"},
|
||||||
{4, nullptr, "GetOperationEventReadableHandle"},
|
{4, &IStaticService::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||||
|
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
||||||
|
{20, &IStaticService::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
|
||||||
|
{30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"},
|
||||||
|
{31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
|
||||||
|
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
||||||
|
{51, nullptr, "GetStandardSteadyClockRtcValue"},
|
||||||
|
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||||
|
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||||
|
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
||||||
|
{200, &IStaticService::IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||||
|
{201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||||
|
{300, &IStaticService::CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||||
|
{400, &IStaticService::GetClockSnapshot, "GetClockSnapshot"},
|
||||||
|
{401, &IStaticService::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
|
||||||
|
{500, &IStaticService::CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||||
|
{501, &IStaticService::CalculateSpanBetween, "CalculateSpanBetween"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@ -34,378 +50,273 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetCurrentTime(HLERequestContext& ctx) {
|
void GetStandardUserSystemClock(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Time, "called");
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
if (!clock_core.IsInitialized()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s64 posix_time{};
|
|
||||||
if (const Result result{clock_core.GetCurrentTime(system, posix_time)}; result.IsError()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push<s64>(posix_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetSystemClockContext(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
if (!clock_core.IsInitialized()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::SystemClockContext system_clock_context{};
|
|
||||||
if (const Result result{clock_core.GetClockContext(system, system_clock_context)};
|
|
||||||
result.IsError()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, sizeof(Clock::SystemClockContext) / 4 + 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(system_clock_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::SystemClockCore& clock_core;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ISteadyClock final : public ServiceFramework<ISteadyClock> {
|
|
||||||
public:
|
|
||||||
explicit ISteadyClock(Clock::SteadyClockCore& clock_core_, Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "ISteadyClock"}, clock_core{clock_core_} {
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
|
|
||||||
{2, nullptr, "GetTestOffset"},
|
|
||||||
{3, nullptr, "SetTestOffset"},
|
|
||||||
{100, nullptr, "GetRtcValue"},
|
|
||||||
{101, nullptr, "IsRtcResetDetected"},
|
|
||||||
{102, nullptr, "GetSetupResultValue"},
|
|
||||||
{200, nullptr, "GetInternalOffset"},
|
|
||||||
{201, nullptr, "SetInternalOffset"},
|
|
||||||
};
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetCurrentTimePoint(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
if (!clock_core.IsInitialized()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Clock::SteadyClockTimePoint time_point{clock_core.GetCurrentTimePoint(system)};
|
|
||||||
IPC::ResponseBuilder rb{ctx, (sizeof(Clock::SteadyClockTimePoint) / 4) + 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(time_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::SteadyClockCore& clock_core;
|
|
||||||
};
|
|
||||||
|
|
||||||
Result Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
|
|
||||||
Kernel::KThread* thread, Clock::SystemClockContext user_context,
|
|
||||||
Clock::SystemClockContext network_context, Clock::TimeType type,
|
|
||||||
Clock::ClockSnapshot& clock_snapshot) {
|
|
||||||
|
|
||||||
auto& time_manager{system.GetTimeManager()};
|
|
||||||
|
|
||||||
clock_snapshot.steady_clock_time_point =
|
|
||||||
time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system);
|
|
||||||
clock_snapshot.is_automatic_correction_enabled =
|
|
||||||
time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled();
|
|
||||||
clock_snapshot.type = type;
|
|
||||||
|
|
||||||
if (const Result result{
|
|
||||||
time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName(
|
|
||||||
clock_snapshot.location_name)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_snapshot.user_context = user_context;
|
|
||||||
|
|
||||||
if (const Result result{Clock::ClockSnapshot::GetCurrentTime(
|
|
||||||
clock_snapshot.user_time, clock_snapshot.steady_clock_time_point,
|
|
||||||
clock_snapshot.user_context)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeZone::CalendarInfo userCalendarInfo{};
|
|
||||||
if (const Result result{
|
|
||||||
time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
|
|
||||||
clock_snapshot.user_time, userCalendarInfo)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_snapshot.user_calendar_time = userCalendarInfo.time;
|
|
||||||
clock_snapshot.user_calendar_additional_time = userCalendarInfo.additional_info;
|
|
||||||
|
|
||||||
clock_snapshot.network_context = network_context;
|
|
||||||
|
|
||||||
if (Clock::ClockSnapshot::GetCurrentTime(clock_snapshot.network_time,
|
|
||||||
clock_snapshot.steady_clock_time_point,
|
|
||||||
clock_snapshot.network_context) != ResultSuccess) {
|
|
||||||
clock_snapshot.network_time = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeZone::CalendarInfo networkCalendarInfo{};
|
|
||||||
if (const Result result{
|
|
||||||
time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
|
|
||||||
clock_snapshot.network_time, networkCalendarInfo)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_snapshot.network_calendar_time = networkCalendarInfo.time;
|
|
||||||
clock_snapshot.network_calendar_additional_time = networkCalendarInfo.additional_info;
|
|
||||||
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::GetStandardUserSystemClock(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardUserSystemClockCore(),
|
rb.PushIpcInterface<ISystemClock>(manager->GetStandardUserSystemClock());
|
||||||
system);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetStandardNetworkSystemClock(HLERequestContext& ctx) {
|
void GetStandardNetworkSystemClock(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Time, "called");
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardNetworkSystemClockCore(),
|
rb.PushIpcInterface<ISystemClock>(manager->GetStandardNetworkSystemClock());
|
||||||
system);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetStandardSteadyClock(HLERequestContext& ctx) {
|
void GetStandardSteadyClock(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Time, "called");
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ISteadyClock>(system.GetTimeManager().GetStandardSteadyClockCore(), system);
|
rb.PushIpcInterface<ISteadyClock>(manager->GetStandardSteadyClock());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetTimeZoneService(HLERequestContext& ctx) {
|
void GetTimeZoneService(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Time, "called");
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ITimeZoneService>(system,
|
rb.PushIpcInterface<ITimeZoneService>(manager->GetTimeZoneService());
|
||||||
system.GetTimeManager().GetTimeZoneContentManager());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetStandardLocalSystemClock(HLERequestContext& ctx) {
|
void GetStandardLocalSystemClock(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Time, "called");
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardLocalSystemClockCore(),
|
rb.PushIpcInterface<ISystemClock>(manager->GetStandardLocalSystemClock());
|
||||||
system);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
|
void GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
auto& clock_core{system.GetTimeManager().GetStandardNetworkSystemClockCore()};
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
auto& steady_clock_core{system.GetTimeManager().GetStandardSteadyClockCore()};
|
|
||||||
if (!steady_clock_core.IsInitialized()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto context{rp.PopRaw<Clock::SystemClockContext>()};
|
|
||||||
const auto current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
|
|
||||||
|
|
||||||
if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) {
|
|
||||||
const auto ticks{Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(
|
|
||||||
system.CoreTiming().GetClockTicks())};
|
|
||||||
const s64 base_time_point{context.offset + current_time_point.time_point -
|
|
||||||
ticks.ToSeconds()};
|
|
||||||
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(base_time_point);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ERROR_TIME_MISMATCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::GetClockSnapshot(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto type{rp.PopEnum<Clock::TimeType>()};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_Time, "called, type={}", type);
|
|
||||||
|
|
||||||
Clock::SystemClockContext user_context{};
|
|
||||||
if (const Result result{
|
|
||||||
system.GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(system,
|
|
||||||
user_context)};
|
|
||||||
result.IsError()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::SystemClockContext network_context{};
|
|
||||||
if (const Result result{
|
|
||||||
system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
|
|
||||||
system, network_context)};
|
|
||||||
result.IsError()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::ClockSnapshot clock_snapshot{};
|
|
||||||
if (const Result result{GetClockSnapshotFromSystemClockContextInternal(
|
|
||||||
&ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
|
|
||||||
result.IsError()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.WriteBuffer(clock_snapshot);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto type{rp.PopEnum<Clock::TimeType>()};
|
|
||||||
|
|
||||||
rp.Skip(1, false);
|
|
||||||
|
|
||||||
const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()};
|
|
||||||
const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_Time, "called, type={}", type);
|
|
||||||
|
|
||||||
Clock::ClockSnapshot clock_snapshot{};
|
|
||||||
if (const Result result{GetClockSnapshotFromSystemClockContextInternal(
|
|
||||||
&ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.WriteBuffer(clock_snapshot);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
Clock::ClockSnapshot snapshot_a;
|
|
||||||
Clock::ClockSnapshot snapshot_b;
|
|
||||||
|
|
||||||
const auto snapshot_a_data = ctx.ReadBuffer(0);
|
|
||||||
const auto snapshot_b_data = ctx.ReadBuffer(1);
|
|
||||||
|
|
||||||
std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(Clock::ClockSnapshot));
|
|
||||||
std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(Clock::ClockSnapshot));
|
|
||||||
|
|
||||||
auto time_span_type{Clock::TimeSpanType::FromSeconds(snapshot_b.user_context.offset -
|
|
||||||
snapshot_a.user_context.offset)};
|
|
||||||
|
|
||||||
if ((snapshot_b.user_context.steady_time_point.clock_source_id !=
|
|
||||||
snapshot_a.user_context.steady_time_point.clock_source_id) ||
|
|
||||||
(snapshot_b.is_automatic_correction_enabled &&
|
|
||||||
snapshot_a.is_automatic_correction_enabled)) {
|
|
||||||
time_span_type.nanoseconds = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(time_span_type.nanoseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::CalculateSpanBetween(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
Clock::ClockSnapshot snapshot_a;
|
|
||||||
Clock::ClockSnapshot snapshot_b;
|
|
||||||
|
|
||||||
const auto snapshot_a_data = ctx.ReadBuffer(0);
|
|
||||||
const auto snapshot_b_data = ctx.ReadBuffer(1);
|
|
||||||
|
|
||||||
std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(Clock::ClockSnapshot));
|
|
||||||
std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(Clock::ClockSnapshot));
|
|
||||||
|
|
||||||
Clock::TimeSpanType time_span_type{};
|
|
||||||
s64 span{};
|
|
||||||
|
|
||||||
if (const Result result{snapshot_a.steady_clock_time_point.GetSpanBetween(
|
|
||||||
snapshot_b.steady_clock_time_point, span)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
if (snapshot_a.network_time && snapshot_b.network_time) {
|
|
||||||
time_span_type =
|
|
||||||
Clock::TimeSpanType::FromSeconds(snapshot_b.network_time - snapshot_a.network_time);
|
|
||||||
} else {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ERROR_TIME_NOT_FOUND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
time_span_type = Clock::TimeSpanType::FromSeconds(span);
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(time_span_type.nanoseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(&system.Kernel().GetTimeSharedMem());
|
rb.PushCopyObjects(&system.Kernel().GetTimeSharedMem());
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_,
|
void IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
|
||||||
const char* name)
|
LOG_DEBUG(Service_Time, "called");
|
||||||
: ServiceFramework{system_, name}, module{std::move(module_)} {}
|
auto& clock_core{manager->GetStandardNetworkSystemClock()};
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient());
|
||||||
|
}
|
||||||
|
|
||||||
Module::Interface::~Interface() = default;
|
void CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto context{rp.PopRaw<SystemClockContext>()};
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
|
Result result = ResultSuccess;
|
||||||
|
u64 base_time_point{};
|
||||||
|
SteadyClockTimePoint current_time_point{};
|
||||||
|
auto& steady_clock_core{manager->GetStandardSteadyClock()};
|
||||||
|
if (!steady_clock_core.IsInitialized()) {
|
||||||
|
result = ResultUnitializedClock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
result = manager->GetCurrentTimePoint(current_time_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
if (current_time_point.clock_source_id != context.steady_time_point.clock_source_id) {
|
||||||
|
result = ResultTimeMismatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
const auto ticks{TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(
|
||||||
|
system.CoreTiming().GetClockTicks())};
|
||||||
|
base_time_point = context.offset + current_time_point.time_point - ticks.ToSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(result);
|
||||||
|
rb.PushRaw(base_time_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetClockSnapshotFromSystemClockContextImpl(ClockSnapshot& out_clock_snapshot,
|
||||||
|
const SystemClockContext& user_context,
|
||||||
|
const SystemClockContext& network_context,
|
||||||
|
TimeType type) {
|
||||||
|
Result result = ResultSuccess;
|
||||||
|
out_clock_snapshot.user_context = user_context;
|
||||||
|
out_clock_snapshot.network_context = network_context;
|
||||||
|
|
||||||
|
result = manager->GetCurrentTimePoint(out_clock_snapshot.steady_clock_time_point);
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
out_clock_snapshot.is_automatic_correction_enabled =
|
||||||
|
manager->IsAutomaticCorrectionEnabled();
|
||||||
|
result = manager->GetLocationName(out_clock_snapshot.location_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
result = TimeUtil::GetCurrentTime(out_clock_snapshot.user_time,
|
||||||
|
out_clock_snapshot.steady_clock_time_point,
|
||||||
|
out_clock_snapshot.user_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
result = manager->GetCalendarTime(out_clock_snapshot.user_calendar_time,
|
||||||
|
out_clock_snapshot.user_calendar_additional_time,
|
||||||
|
out_clock_snapshot.user_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
const Result time_result = TimeUtil::GetCurrentTime(
|
||||||
|
out_clock_snapshot.network_time, out_clock_snapshot.steady_clock_time_point,
|
||||||
|
out_clock_snapshot.network_context);
|
||||||
|
if (time_result.IsError()) {
|
||||||
|
out_clock_snapshot.network_time = 0;
|
||||||
|
}
|
||||||
|
result = manager->GetCalendarTime(out_clock_snapshot.network_calendar_time,
|
||||||
|
out_clock_snapshot.network_calendar_additional_time,
|
||||||
|
out_clock_snapshot.network_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
out_clock_snapshot.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetClockSnapshot(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto type{rp.PopEnum<TimeType>()};
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_Time, "called, type={}", type);
|
||||||
|
|
||||||
|
Result result = ResultSuccess;
|
||||||
|
SystemClockContext user_context{};
|
||||||
|
SystemClockContext network_context{};
|
||||||
|
ClockSnapshot clock_snapshot{};
|
||||||
|
|
||||||
|
result = manager->GetStandardUserSystemClock().GetClockContext(user_context);
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
result = manager->GetStandardNetworkSystemClock().GetClockContext(user_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
result = GetClockSnapshotFromSystemClockContextImpl(clock_snapshot, user_context,
|
||||||
|
network_context, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
ctx.WriteBuffer(clock_snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) {
|
||||||
|
struct params {
|
||||||
|
TimeType type;
|
||||||
|
};
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto type{rp.PopEnum<TimeType>()};
|
||||||
|
rp.Skip(1, false);
|
||||||
|
const SystemClockContext user_context{rp.PopRaw<SystemClockContext>()};
|
||||||
|
const SystemClockContext network_context{rp.PopRaw<SystemClockContext>()};
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_Time, "called, type={}", type);
|
||||||
|
|
||||||
|
ClockSnapshot clock_snapshot{};
|
||||||
|
const auto result = GetClockSnapshotFromSystemClockContextImpl(clock_snapshot, user_context,
|
||||||
|
network_context, type);
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
ctx.WriteBuffer(clock_snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx) {
|
||||||
|
const auto snapshot_a_data = ctx.ReadBuffer(0);
|
||||||
|
const auto snapshot_b_data = ctx.ReadBuffer(1);
|
||||||
|
|
||||||
|
ClockSnapshot snapshot_a;
|
||||||
|
ClockSnapshot snapshot_b;
|
||||||
|
std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(ClockSnapshot));
|
||||||
|
std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(ClockSnapshot));
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
|
auto time_span = TimeSpanType::FromSeconds(snapshot_b.user_context.offset -
|
||||||
|
snapshot_a.user_context.offset);
|
||||||
|
|
||||||
|
if (snapshot_a.user_context.steady_time_point.clock_source_id !=
|
||||||
|
snapshot_b.user_context.steady_time_point.clock_source_id) {
|
||||||
|
time_span = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot_a.is_automatic_correction_enabled &&
|
||||||
|
snapshot_b.is_automatic_correction_enabled) {
|
||||||
|
if (snapshot_a.network_context.steady_time_point.clock_source_id ==
|
||||||
|
snapshot_a.steady_clock_time_point.clock_source_id) {
|
||||||
|
time_span = {};
|
||||||
|
}
|
||||||
|
if (snapshot_b.network_context.steady_time_point.clock_source_id ==
|
||||||
|
snapshot_b.steady_clock_time_point.clock_source_id) {
|
||||||
|
time_span = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(time_span.nanoseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalculateSpanBetween(HLERequestContext& ctx) {
|
||||||
|
const auto snapshot_a_data = ctx.ReadBuffer(0);
|
||||||
|
const auto snapshot_b_data = ctx.ReadBuffer(1);
|
||||||
|
|
||||||
|
ClockSnapshot snapshot_a;
|
||||||
|
ClockSnapshot snapshot_b;
|
||||||
|
std::memcpy(&snapshot_a, snapshot_a_data.data(), sizeof(ClockSnapshot));
|
||||||
|
std::memcpy(&snapshot_b, snapshot_b_data.data(), sizeof(ClockSnapshot));
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_Time, "called");
|
||||||
|
|
||||||
|
TimeSpanType time_span{};
|
||||||
|
Result result = TimeUtil::GetSpanBetween(time_span, snapshot_a.steady_clock_time_point,
|
||||||
|
snapshot_b.steady_clock_time_point);
|
||||||
|
|
||||||
|
if (result.IsError()) {
|
||||||
|
result = ResultTimeNotFound;
|
||||||
|
if (snapshot_a.network_time != 0 && snapshot_b.network_time != 0) {
|
||||||
|
time_span = {snapshot_b.network_time - snapshot_a.network_time};
|
||||||
|
result = ResultSuccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(result);
|
||||||
|
rb.PushRaw(time_span.nanoseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<TimeManager> manager;
|
||||||
|
};
|
||||||
|
|
||||||
void LoopProcess(Core::System& system) {
|
void LoopProcess(Core::System& system) {
|
||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
auto module{std::make_shared<Module>()};
|
|
||||||
|
|
||||||
server_manager->RegisterNamedService("time:a",
|
server_manager->RegisterNamedService("time:a",
|
||||||
std::make_shared<Time>(module, system, "time:a"));
|
std::make_shared<IStaticService>("time:a", system));
|
||||||
server_manager->RegisterNamedService("time:s",
|
server_manager->RegisterNamedService("time:s",
|
||||||
std::make_shared<Time>(module, system, "time:s"));
|
std::make_shared<IStaticService>("time:s", system));
|
||||||
server_manager->RegisterNamedService("time:u",
|
server_manager->RegisterNamedService("time:u",
|
||||||
std::make_shared<Time>(module, system, "time:u"));
|
std::make_shared<IStaticService>("time:u", system));
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,49 +3,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
|
||||||
class Module final {
|
|
||||||
public:
|
|
||||||
Module() = default;
|
|
||||||
|
|
||||||
class Interface : public ServiceFramework<Interface> {
|
|
||||||
public:
|
|
||||||
explicit Interface(std::shared_ptr<Module> module_, Core::System& system_,
|
|
||||||
const char* name);
|
|
||||||
~Interface() override;
|
|
||||||
|
|
||||||
void GetStandardUserSystemClock(HLERequestContext& ctx);
|
|
||||||
void GetStandardNetworkSystemClock(HLERequestContext& ctx);
|
|
||||||
void GetStandardSteadyClock(HLERequestContext& ctx);
|
|
||||||
void GetTimeZoneService(HLERequestContext& ctx);
|
|
||||||
void GetStandardLocalSystemClock(HLERequestContext& ctx);
|
|
||||||
void IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
|
|
||||||
void CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
|
|
||||||
void GetClockSnapshot(HLERequestContext& ctx);
|
|
||||||
void GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
|
|
||||||
void CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
|
|
||||||
void CalculateSpanBetween(HLERequestContext& ctx);
|
|
||||||
void GetSharedMemoryNativeHandle(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Result GetClockSnapshotFromSystemClockContextInternal(
|
|
||||||
Kernel::KThread* thread, Clock::SystemClockContext user_context,
|
|
||||||
Clock::SystemClockContext network_context, Clock::TimeType type,
|
|
||||||
Clock::ClockSnapshot& cloc_snapshot);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::shared_ptr<Module> module;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
void LoopProcess(Core::System& system);
|
void LoopProcess(Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::Time
|
} // namespace Service::Time
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/time/time_interface.h"
|
|
||||||
|
|
||||||
namespace Service::Time {
|
|
||||||
|
|
||||||
Time::Time(std::shared_ptr<Module> module_, Core::System& system_, const char* name_)
|
|
||||||
: Interface{std::move(module_), system_, name_} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
|
||||||
{1, &Time::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
|
||||||
{2, &Time::GetStandardSteadyClock, "GetStandardSteadyClock"},
|
|
||||||
{3, &Time::GetTimeZoneService, "GetTimeZoneService"},
|
|
||||||
{4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
|
||||||
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
|
||||||
{20, &Time::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
|
|
||||||
{30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"},
|
|
||||||
{31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
|
|
||||||
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
|
||||||
{51, nullptr, "GetStandardSteadyClockRtcValue"},
|
|
||||||
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
|
||||||
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
|
||||||
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
|
||||||
{200, &Time::IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
|
|
||||||
{201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
|
||||||
{300, &Time::CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
|
|
||||||
{400, &Time::GetClockSnapshot, "GetClockSnapshot"},
|
|
||||||
{401, &Time::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
|
|
||||||
{500, &Time::CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
|
|
||||||
{501, &Time::CalculateSpanBetween, "CalculateSpanBetween"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
Time::~Time() = default;
|
|
||||||
|
|
||||||
} // namespace Service::Time
|
|
@ -1,20 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/time/time.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time {
|
|
||||||
|
|
||||||
class Time final : public Module::Interface {
|
|
||||||
public:
|
|
||||||
explicit Time(std::shared_ptr<Module> time, Core::System& system_, const char* name_);
|
|
||||||
~Time() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time
|
|
@ -1,293 +1,99 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <chrono>
|
#include "common/logging/log.h"
|
||||||
#include <ctime>
|
#include "core/core.h"
|
||||||
|
|
||||||
#include "common/settings.h"
|
|
||||||
#include "common/time_zone.h"
|
|
||||||
#include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h"
|
|
||||||
#include "core/hle/service/time/ephemeral_network_system_clock_core.h"
|
|
||||||
#include "core/hle/service/time/local_system_clock_context_writer.h"
|
|
||||||
#include "core/hle/service/time/network_system_clock_context_writer.h"
|
|
||||||
#include "core/hle/service/time/tick_based_steady_clock_core.h"
|
|
||||||
#include "core/hle/service/time/time_manager.h"
|
#include "core/hle/service/time/time_manager.h"
|
||||||
|
#include "core/core_timing.h"
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
namespace {
|
constexpr auto time_update_ns =
|
||||||
constexpr Clock::TimeSpanType standard_network_clock_accuracy{0x0009356907420000ULL};
|
std::chrono::nanoseconds{5ull * 60 * 1000 * 1000 * 1000}; // (5 minutes)
|
||||||
|
|
||||||
s64 GetSecondsSinceEpoch() {
|
TimeManager::TimeManager(Core::System& system_) : time_zone_service{system_}, system{system_} {
|
||||||
const auto time_since_epoch = std::chrono::system_clock::now().time_since_epoch();
|
|
||||||
return std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch).count() +
|
|
||||||
Settings::values.custom_rtc_differential;
|
|
||||||
}
|
|
||||||
} // Anonymous namespace
|
|
||||||
|
|
||||||
struct TimeManager::Impl final {
|
// Register update callbacks
|
||||||
explicit Impl(Core::System& system)
|
time_update_event = Core::Timing::CreateEvent(
|
||||||
: shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core},
|
"HID::UpdatePadCallback",
|
||||||
standard_network_system_clock_core{standard_steady_clock_core},
|
[this](std::uintptr_t user_data, s64 time,
|
||||||
standard_user_system_clock_core{standard_local_system_clock_core,
|
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||||
standard_network_system_clock_core, system},
|
UpdateTime();
|
||||||
ephemeral_network_system_clock_core{tick_based_steady_clock_core},
|
return std::nullopt;
|
||||||
local_system_clock_context_writer{
|
});
|
||||||
std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)},
|
|
||||||
network_system_clock_context_writer{
|
|
||||||
std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)},
|
|
||||||
ephemeral_network_system_clock_context_writer{
|
|
||||||
std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
|
|
||||||
time_zone_content_manager{system} {
|
|
||||||
|
|
||||||
const auto system_time{Clock::TimeSpanType::FromSeconds(GetSecondsSinceEpoch())};
|
system.CoreTiming().ScheduleLoopingEvent(time_update_ns, time_update_ns, time_update_event);
|
||||||
SetupStandardSteadyClock(system, Common::UUID::MakeRandom(), system_time, {}, {});
|
|
||||||
SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
|
|
||||||
|
|
||||||
Clock::SystemClockContext clock_context{};
|
|
||||||
standard_local_system_clock_core.GetClockContext(system, clock_context);
|
|
||||||
|
|
||||||
SetupStandardNetworkSystemClock(clock_context, standard_network_clock_accuracy);
|
|
||||||
SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
|
|
||||||
SetupEphemeralNetworkSystemClock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl() = default;
|
TimeManager::~TimeManager() {
|
||||||
|
system.CoreTiming().UnscheduleEvent(time_update_event, 0);
|
||||||
Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() {
|
|
||||||
return standard_steady_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const {
|
|
||||||
return standard_steady_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() {
|
|
||||||
return standard_local_system_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const {
|
|
||||||
return standard_local_system_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() {
|
|
||||||
return standard_network_system_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const {
|
|
||||||
return standard_network_system_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() {
|
|
||||||
return standard_user_system_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const {
|
|
||||||
return standard_user_system_clock_core;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() {
|
|
||||||
return time_zone_content_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const {
|
|
||||||
return time_zone_content_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedMemory& GetSharedMemory() {
|
|
||||||
return shared_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SharedMemory& GetSharedMemory() const {
|
|
||||||
return shared_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupTimeZoneManager(std::string location_name,
|
|
||||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
|
||||||
std::vector<std::string> location_names, u128 time_zone_rule_version,
|
|
||||||
FileSys::VirtualFile& vfs_file) {
|
|
||||||
if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
|
|
||||||
location_name, vfs_file) != ResultSuccess) {
|
|
||||||
ASSERT(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
|
|
||||||
location_names.size());
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().SetLocationNames(location_names);
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(
|
|
||||||
time_zone_rule_version);
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupStandardSteadyClock(Core::System& system_, Common::UUID clock_source_id,
|
|
||||||
Clock::TimeSpanType setup_value,
|
|
||||||
Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) {
|
|
||||||
standard_steady_clock_core.SetClockSourceId(clock_source_id);
|
|
||||||
standard_steady_clock_core.SetSetupValue(setup_value);
|
|
||||||
standard_steady_clock_core.SetInternalOffset(internal_offset);
|
|
||||||
standard_steady_clock_core.MarkAsInitialized();
|
|
||||||
|
|
||||||
const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system_)};
|
|
||||||
shared_memory.SetupStandardSteadyClock(clock_source_id, current_time_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupStandardLocalSystemClock(Core::System& system_,
|
|
||||||
Clock::SystemClockContext clock_context, s64 posix_time) {
|
|
||||||
standard_local_system_clock_core.SetUpdateCallbackInstance(
|
|
||||||
local_system_clock_context_writer);
|
|
||||||
|
|
||||||
const auto current_time_point{
|
|
||||||
standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system_)};
|
|
||||||
if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) {
|
|
||||||
standard_local_system_clock_core.SetSystemClockContext(clock_context);
|
|
||||||
} else {
|
|
||||||
if (standard_local_system_clock_core.SetCurrentTime(system_, posix_time) !=
|
|
||||||
ResultSuccess) {
|
|
||||||
ASSERT(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
standard_local_system_clock_core.MarkAsInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
|
|
||||||
Clock::TimeSpanType sufficient_accuracy) {
|
|
||||||
standard_network_system_clock_core.SetUpdateCallbackInstance(
|
|
||||||
network_system_clock_context_writer);
|
|
||||||
|
|
||||||
if (standard_network_system_clock_core.SetSystemClockContext(clock_context) !=
|
|
||||||
ResultSuccess) {
|
|
||||||
ASSERT(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy(
|
|
||||||
sufficient_accuracy);
|
|
||||||
standard_network_system_clock_core.MarkAsInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupStandardUserSystemClock(Core::System& system_, bool is_automatic_correction_enabled,
|
|
||||||
Clock::SteadyClockTimePoint steady_clock_time_point) {
|
|
||||||
if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled(
|
|
||||||
system_, is_automatic_correction_enabled) != ResultSuccess) {
|
|
||||||
ASSERT(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point);
|
|
||||||
standard_user_system_clock_core.MarkAsInitialized();
|
|
||||||
shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupEphemeralNetworkSystemClock() {
|
|
||||||
ephemeral_network_system_clock_core.SetUpdateCallbackInstance(
|
|
||||||
ephemeral_network_system_clock_context_writer);
|
|
||||||
ephemeral_network_system_clock_core.MarkAsInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateLocalSystemClockTime(Core::System& system_, s64 posix_time) {
|
|
||||||
const auto timespan{Clock::TimeSpanType::FromSeconds(posix_time)};
|
|
||||||
if (GetStandardLocalSystemClockCore()
|
|
||||||
.SetCurrentTime(system_, timespan.ToSeconds())
|
|
||||||
.IsError()) {
|
|
||||||
ASSERT(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedMemory shared_memory;
|
|
||||||
|
|
||||||
Clock::StandardSteadyClockCore standard_steady_clock_core;
|
|
||||||
Clock::TickBasedSteadyClockCore tick_based_steady_clock_core;
|
|
||||||
Clock::StandardLocalSystemClockCore standard_local_system_clock_core;
|
|
||||||
Clock::StandardNetworkSystemClockCore standard_network_system_clock_core;
|
|
||||||
Clock::StandardUserSystemClockCore standard_user_system_clock_core;
|
|
||||||
Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core;
|
|
||||||
|
|
||||||
std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer;
|
|
||||||
std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer;
|
|
||||||
std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter>
|
|
||||||
ephemeral_network_system_clock_context_writer;
|
|
||||||
|
|
||||||
TimeZone::TimeZoneContentManager time_zone_content_manager;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TimeManager::TimeManager(Core::System& system_) : system{system_} {}
|
void TimeManager::UpdateTime() {
|
||||||
|
steady_clock.UpdateTime();
|
||||||
TimeManager::~TimeManager() = default;
|
local_system_clock.UpdateTime();
|
||||||
|
network_system_clock.UpdateTime();
|
||||||
void TimeManager::Initialize() {
|
user_system_clock.UpdateTime();
|
||||||
impl = std::make_unique<Impl>(system);
|
time_zone_service.UpdateTime();
|
||||||
|
|
||||||
// Time zones can only be initialized after impl is valid
|
|
||||||
impl->time_zone_content_manager.Initialize(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() {
|
bool TimeManager::IsAutomaticCorrectionEnabled() const {
|
||||||
return impl->standard_steady_clock_core;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() const {
|
Result TimeManager::GetCurrentTimePoint(SteadyClockTimePoint& out_steady_time_point) const {
|
||||||
return impl->standard_steady_clock_core;
|
|
||||||
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() {
|
Result TimeManager::GetLocationName(TimeZone::LocationName& out_name) const {
|
||||||
return impl->standard_local_system_clock_core;
|
|
||||||
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() const {
|
Result TimeManager::GetCalendarTime(TimeZone::CalendarTime& out_calendar_time,
|
||||||
return impl->standard_local_system_clock_core;
|
TimeZone::CalendarAdditionalInfo& out_calendar_aditional_info,
|
||||||
|
s64 time) const {
|
||||||
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore() {
|
SteadyClock& TimeManager::GetStandardSteadyClock() {
|
||||||
return impl->standard_network_system_clock_core;
|
return steady_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore()
|
const SteadyClock& TimeManager::GetStandardSteadyClock() const {
|
||||||
const {
|
return steady_clock;
|
||||||
return impl->standard_network_system_clock_core;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() {
|
LocalSystemClock& TimeManager::GetStandardLocalSystemClock() {
|
||||||
return impl->standard_user_system_clock_core;
|
return local_system_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() const {
|
const LocalSystemClock& TimeManager::GetStandardLocalSystemClock() const {
|
||||||
return impl->standard_user_system_clock_core;
|
return local_system_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() {
|
NetworkSystemClock& TimeManager::GetStandardNetworkSystemClock() {
|
||||||
return impl->time_zone_content_manager;
|
return network_system_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() const {
|
const NetworkSystemClock& TimeManager::GetStandardNetworkSystemClock() const {
|
||||||
return impl->time_zone_content_manager;
|
return network_system_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedMemory& TimeManager::GetSharedMemory() {
|
UserSystemClock& TimeManager::GetStandardUserSystemClock() {
|
||||||
return impl->shared_memory;
|
return user_system_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SharedMemory& TimeManager::GetSharedMemory() const {
|
const UserSystemClock& TimeManager::GetStandardUserSystemClock() const {
|
||||||
return impl->shared_memory;
|
return user_system_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeManager::Shutdown() {
|
ITimeZoneService& TimeManager::GetTimeZoneService() {
|
||||||
impl.reset();
|
return time_zone_service;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) {
|
const ITimeZoneService& TimeManager::GetTimeZoneService() const {
|
||||||
impl->UpdateLocalSystemClockTime(system, posix_time);
|
return time_zone_service;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeManager::SetupTimeZoneManager(std::string location_name,
|
|
||||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
|
||||||
std::vector<std::string> location_names,
|
|
||||||
u128 time_zone_rule_version,
|
|
||||||
FileSys::VirtualFile& vfs_file) {
|
|
||||||
impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, location_names,
|
|
||||||
time_zone_rule_version, vfs_file);
|
|
||||||
}
|
|
||||||
} // namespace Service::Time
|
} // namespace Service::Time
|
||||||
|
@ -1,74 +1,60 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "core/hle/service/time/clock_types/local_system_clock.h"
|
||||||
#include "core/file_sys/vfs_types.h"
|
#include "core/hle/service/time/clock_types/network_system_clock.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
#include "core/hle/service/time/clock_types/steady_clock.h"
|
||||||
#include "core/hle/service/time/standard_local_system_clock_core.h"
|
#include "core/hle/service/time/clock_types/user_system_clock.h"
|
||||||
#include "core/hle/service/time/standard_network_system_clock_core.h"
|
#include "core/hle/service/time/time_types.h"
|
||||||
#include "core/hle/service/time/standard_steady_clock_core.h"
|
#include "core/hle/service/time/time_zone/time_zone_service.h"
|
||||||
#include "core/hle/service/time/standard_user_system_clock_core.h"
|
|
||||||
#include "core/hle/service/time/time_sharedmemory.h"
|
namespace Core {
|
||||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
|
||||||
namespace Clock {
|
class TimeManager {
|
||||||
class EphemeralNetworkSystemClockContextWriter;
|
|
||||||
class LocalSystemClockContextWriter;
|
|
||||||
class NetworkSystemClockContextWriter;
|
|
||||||
} // namespace Clock
|
|
||||||
|
|
||||||
// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
|
|
||||||
// This code was released under public domain.
|
|
||||||
|
|
||||||
class TimeManager final {
|
|
||||||
public:
|
public:
|
||||||
explicit TimeManager(Core::System& system_);
|
explicit TimeManager(Core::System& system_);
|
||||||
~TimeManager();
|
~TimeManager();
|
||||||
|
|
||||||
void Initialize();
|
bool IsAutomaticCorrectionEnabled() const;
|
||||||
|
|
||||||
Clock::StandardSteadyClockCore& GetStandardSteadyClockCore();
|
Result GetCurrentTimePoint(SteadyClockTimePoint& out_steady_time_point) const;
|
||||||
|
Result GetLocationName(TimeZone::LocationName& out_name) const;
|
||||||
|
Result GetCalendarTime(TimeZone::CalendarTime& out_calendar_time,
|
||||||
|
TimeZone::CalendarAdditionalInfo& out_calendar_aditional_info,
|
||||||
|
s64 time) const;
|
||||||
|
|
||||||
const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const;
|
SteadyClock& GetStandardSteadyClock();
|
||||||
|
const SteadyClock& GetStandardSteadyClock() const;
|
||||||
|
|
||||||
Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore();
|
LocalSystemClock& GetStandardLocalSystemClock();
|
||||||
|
const LocalSystemClock& GetStandardLocalSystemClock() const;
|
||||||
|
|
||||||
const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const;
|
NetworkSystemClock& GetStandardNetworkSystemClock();
|
||||||
|
const NetworkSystemClock& GetStandardNetworkSystemClock() const;
|
||||||
|
|
||||||
Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore();
|
UserSystemClock& GetStandardUserSystemClock();
|
||||||
|
const UserSystemClock& GetStandardUserSystemClock() const;
|
||||||
|
|
||||||
const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const;
|
ITimeZoneService& GetTimeZoneService();
|
||||||
|
const ITimeZoneService& GetTimeZoneService() const;
|
||||||
Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore();
|
|
||||||
|
|
||||||
const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const;
|
|
||||||
|
|
||||||
TimeZone::TimeZoneContentManager& GetTimeZoneContentManager();
|
|
||||||
|
|
||||||
const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const;
|
|
||||||
|
|
||||||
void UpdateLocalSystemClockTime(s64 posix_time);
|
|
||||||
|
|
||||||
SharedMemory& GetSharedMemory();
|
|
||||||
|
|
||||||
const SharedMemory& GetSharedMemory() const;
|
|
||||||
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void SetupTimeZoneManager(std::string location_name,
|
|
||||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
|
||||||
std::vector<std::string> location_names, u128 time_zone_rule_version,
|
|
||||||
FileSys::VirtualFile& vfs_file);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& system;
|
void UpdateTime();
|
||||||
|
|
||||||
struct Impl;
|
std::shared_ptr<Core::Timing::EventType> time_update_event;
|
||||||
std::unique_ptr<Impl> impl;
|
|
||||||
|
SteadyClock steady_clock;
|
||||||
|
LocalSystemClock local_system_clock;
|
||||||
|
NetworkSystemClock network_system_clock;
|
||||||
|
UserSystemClock user_system_clock;
|
||||||
|
ITimeZoneService time_zone_service;
|
||||||
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Time
|
} // namespace Service::Time
|
||||||
|
21
src/core/hle/service/time/time_result.h
Normal file
21
src/core/hle/service/time/time_result.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
|
||||||
|
constexpr Result ResultPermissionDenied{ErrorModule::Time, 1};
|
||||||
|
constexpr Result ResultTimeMismatch{ErrorModule::Time, 102};
|
||||||
|
constexpr Result ResultUnitializedClock{ErrorModule::Time, 103};
|
||||||
|
constexpr Result ResultTimeNotFound{ErrorModule::Time, 200};
|
||||||
|
constexpr Result ResultOverflow{ErrorModule::Time, 201};
|
||||||
|
constexpr Result ResultLocationNameTooLong{ErrorModule::Time, 801};
|
||||||
|
constexpr Result ResultOutOfRange{ErrorModule::Time, 902};
|
||||||
|
constexpr Result ResutTimeConversionFailed{ErrorModule::Time, 903};
|
||||||
|
constexpr Result ResultTimezoneNotFound{ErrorModule::Time, 989};
|
||||||
|
constexpr Result ResultNotImplemented{ErrorModule::Time, 990};
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
@ -1,69 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/hardware_properties.h"
|
|
||||||
#include "core/hle/kernel/kernel.h"
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
#include "core/hle/service/time/steady_clock_core.h"
|
|
||||||
#include "core/hle/service/time/time_sharedmemory.h"
|
|
||||||
|
|
||||||
namespace Service::Time {
|
|
||||||
|
|
||||||
static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000};
|
|
||||||
|
|
||||||
SharedMemory::SharedMemory(Core::System& system_) : system(system_) {
|
|
||||||
std::memset(system.Kernel().GetTimeSharedMem().GetPointer(), 0, SHARED_MEMORY_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedMemory::~SharedMemory() = default;
|
|
||||||
|
|
||||||
void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id,
|
|
||||||
Clock::TimeSpanType current_time_point) {
|
|
||||||
const Clock::TimeSpanType ticks_time_span{
|
|
||||||
Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(
|
|
||||||
system.CoreTiming().GetClockTicks())};
|
|
||||||
const Clock::SteadyClockContext context{
|
|
||||||
static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),
|
|
||||||
clock_source_id};
|
|
||||||
StoreToLockFreeAtomicType(&GetFormat()->standard_steady_clock_timepoint, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) {
|
|
||||||
// lower and upper are related to the measurement point for the steady time point,
|
|
||||||
// and compare equal on boot
|
|
||||||
const s64 time_point_ns = context.steady_time_point.time_point * 1'000'000'000LL;
|
|
||||||
|
|
||||||
// This adjusts for some sort of time skew
|
|
||||||
// Both 0 on boot
|
|
||||||
const s64 diff_scale = 0;
|
|
||||||
const u32 shift_amount = 0;
|
|
||||||
|
|
||||||
const Clock::ContinuousAdjustmentTimePoint adjustment{
|
|
||||||
.measurement_offset = system.CoreTiming().GetGlobalTimeNs().count(),
|
|
||||||
.diff_scale = diff_scale,
|
|
||||||
.shift_amount = shift_amount,
|
|
||||||
.lower = time_point_ns,
|
|
||||||
.upper = time_point_ns,
|
|
||||||
.clock_source_id = context.steady_time_point.clock_source_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
StoreToLockFreeAtomicType(&GetFormat()->continuous_adjustment_timepoint, adjustment);
|
|
||||||
StoreToLockFreeAtomicType(&GetFormat()->standard_local_system_clock_context, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemory::UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context) {
|
|
||||||
StoreToLockFreeAtomicType(&GetFormat()->standard_network_system_clock_context, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SharedMemory::SetAutomaticCorrectionEnabled(bool is_enabled) {
|
|
||||||
StoreToLockFreeAtomicType(
|
|
||||||
&GetFormat()->is_standard_user_system_clock_automatic_correction_enabled, is_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedMemory::Format* SharedMemory::GetFormat() {
|
|
||||||
return reinterpret_cast<SharedMemory::Format*>(system.Kernel().GetTimeSharedMem().GetPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time
|
|
@ -1,89 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "common/uuid.h"
|
|
||||||
#include "core/hle/kernel/k_shared_memory.h"
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
|
|
||||||
namespace Service::Time {
|
|
||||||
|
|
||||||
// Note: this type is not safe for concurrent writes.
|
|
||||||
template <typename T>
|
|
||||||
struct LockFreeAtomicType {
|
|
||||||
u32 counter_;
|
|
||||||
std::array<T, 2> value_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static inline void StoreToLockFreeAtomicType(LockFreeAtomicType<T>* p, const T& value) {
|
|
||||||
// Get the current counter.
|
|
||||||
auto counter = p->counter_;
|
|
||||||
|
|
||||||
// Increment the counter.
|
|
||||||
++counter;
|
|
||||||
|
|
||||||
// Store the updated value.
|
|
||||||
p->value_[counter % 2] = value;
|
|
||||||
|
|
||||||
// Fence memory.
|
|
||||||
std::atomic_thread_fence(std::memory_order_release);
|
|
||||||
|
|
||||||
// Set the updated counter.
|
|
||||||
p->counter_ = counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static inline T LoadFromLockFreeAtomicType(const LockFreeAtomicType<T>* p) {
|
|
||||||
while (true) {
|
|
||||||
// Get the counter.
|
|
||||||
auto counter = p->counter_;
|
|
||||||
|
|
||||||
// Get the value.
|
|
||||||
auto value = p->value_[counter % 2];
|
|
||||||
|
|
||||||
// Fence memory.
|
|
||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
|
||||||
|
|
||||||
// Check that the counter matches.
|
|
||||||
if (counter == p->counter_) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SharedMemory final {
|
|
||||||
public:
|
|
||||||
explicit SharedMemory(Core::System& system_);
|
|
||||||
~SharedMemory();
|
|
||||||
|
|
||||||
// Shared memory format
|
|
||||||
struct Format {
|
|
||||||
LockFreeAtomicType<Clock::StandardSteadyClockTimePointType> standard_steady_clock_timepoint;
|
|
||||||
LockFreeAtomicType<Clock::SystemClockContext> standard_local_system_clock_context;
|
|
||||||
LockFreeAtomicType<Clock::SystemClockContext> standard_network_system_clock_context;
|
|
||||||
LockFreeAtomicType<bool> is_standard_user_system_clock_automatic_correction_enabled;
|
|
||||||
LockFreeAtomicType<Clock::ContinuousAdjustmentTimePoint> continuous_adjustment_timepoint;
|
|
||||||
};
|
|
||||||
static_assert(offsetof(Format, standard_steady_clock_timepoint) == 0x0);
|
|
||||||
static_assert(offsetof(Format, standard_local_system_clock_context) == 0x38);
|
|
||||||
static_assert(offsetof(Format, standard_network_system_clock_context) == 0x80);
|
|
||||||
static_assert(offsetof(Format, is_standard_user_system_clock_automatic_correction_enabled) ==
|
|
||||||
0xc8);
|
|
||||||
static_assert(offsetof(Format, continuous_adjustment_timepoint) == 0xd0);
|
|
||||||
static_assert(sizeof(Format) == 0x148, "Format is an invalid size");
|
|
||||||
|
|
||||||
void SetupStandardSteadyClock(const Common::UUID& clock_source_id,
|
|
||||||
Clock::TimeSpanType current_time_point);
|
|
||||||
void UpdateLocalSystemClockContext(const Clock::SystemClockContext& context);
|
|
||||||
void UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context);
|
|
||||||
void SetAutomaticCorrectionEnabled(bool is_enabled);
|
|
||||||
Format* GetFormat();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Core::System& system;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time
|
|
@ -8,10 +8,10 @@
|
|||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/uuid.h"
|
#include "common/uuid.h"
|
||||||
#include "core/hle/service/time/errors.h"
|
#include "core/hle/service/time/time_result.h"
|
||||||
#include "core/hle/service/time/time_zone_types.h"
|
#include "core/hle/service/time/time_zone/time_zone_types.h"
|
||||||
|
|
||||||
namespace Service::Time::Clock {
|
namespace Service::Time {
|
||||||
|
|
||||||
enum class TimeType : u8 {
|
enum class TimeType : u8 {
|
||||||
UserSystemClock,
|
UserSystemClock,
|
||||||
@ -24,18 +24,6 @@ struct SteadyClockTimePoint {
|
|||||||
s64 time_point;
|
s64 time_point;
|
||||||
Common::UUID clock_source_id;
|
Common::UUID clock_source_id;
|
||||||
|
|
||||||
Result GetSpanBetween(SteadyClockTimePoint other, s64& span) const {
|
|
||||||
span = 0;
|
|
||||||
|
|
||||||
if (clock_source_id != other.clock_source_id) {
|
|
||||||
return ERROR_TIME_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
span = other.time_point - time_point;
|
|
||||||
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SteadyClockTimePoint GetRandom() {
|
static SteadyClockTimePoint GetRandom() {
|
||||||
return {0, Common::UUID::MakeRandom()};
|
return {0, Common::UUID::MakeRandom()};
|
||||||
}
|
}
|
||||||
@ -107,18 +95,7 @@ struct ClockSnapshot {
|
|||||||
u8 is_automatic_correction_enabled;
|
u8 is_automatic_correction_enabled;
|
||||||
TimeType type;
|
TimeType type;
|
||||||
INSERT_PADDING_BYTES_NOINIT(0x2);
|
INSERT_PADDING_BYTES_NOINIT(0x2);
|
||||||
|
|
||||||
static Result GetCurrentTime(s64& current_time,
|
|
||||||
const SteadyClockTimePoint& steady_clock_time_point,
|
|
||||||
const SystemClockContext& context) {
|
|
||||||
if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) {
|
|
||||||
current_time = 0;
|
|
||||||
return ERROR_TIME_MISMATCH;
|
|
||||||
}
|
|
||||||
current_time = steady_clock_time_point.time_point + context.offset;
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ClockSnapshot) == 0xD0, "ClockSnapshot is incorrect size");
|
static_assert(sizeof(ClockSnapshot) == 0xD0, "ClockSnapshot is incorrect size");
|
||||||
|
|
||||||
} // namespace Service::Time::Clock
|
} // namespace Service::Time
|
41
src/core/hle/service/time/time_util.h
Normal file
41
src/core/hle/service/time/time_util.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/time/time_result.h"
|
||||||
|
#include "core/hle/service/time/time_types.h"
|
||||||
|
|
||||||
|
namespace Service::Time::TimeUtil {
|
||||||
|
|
||||||
|
bool IsSubstractionOverflow(const SteadyClockTimePoint& a, const SteadyClockTimePoint& b) {
|
||||||
|
return (b.time_point < 0) && (a.time_point > std::numeric_limits<s64>::max() + b.time_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetSpanBetween(TimeSpanType& out_time_span, const SteadyClockTimePoint& time_point_a,
|
||||||
|
const SteadyClockTimePoint& time_point_b) {
|
||||||
|
|
||||||
|
if (time_point_a.clock_source_id != time_point_b.clock_source_id) {
|
||||||
|
return ResultTimeNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSubstractionOverflow(time_point_a, time_point_b)) {
|
||||||
|
return ResultOverflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_time_span = {time_point_b.time_point - time_point_a.time_point};
|
||||||
|
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetCurrentTime(s64& out_current_time, const SteadyClockTimePoint& steady_clock_time_point,
|
||||||
|
const SystemClockContext& context) {
|
||||||
|
if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) {
|
||||||
|
out_current_time = 0;
|
||||||
|
return ResultTimeMismatch;
|
||||||
|
}
|
||||||
|
out_current_time = steady_clock_time_point.time_point + context.offset;
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Time::TimeUtil
|
32
src/core/hle/service/time/time_zone/time_zone_service.cpp
Normal file
32
src/core/hle/service/time/time_zone/time_zone_service.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/time/time_zone/time_zone_service.h"
|
||||||
|
|
||||||
|
namespace Service::Time {
|
||||||
|
ITimeZoneService::ITimeZoneService(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "ITimeZoneService"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
|
||||||
|
{1, nullptr, "SetDeviceLocationName"},
|
||||||
|
{2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
|
||||||
|
{3, &ITimeZoneService::LoadLocationNameList, "LoadLocationNameList"},
|
||||||
|
{4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
|
||||||
|
{5, &ITimeZoneService::GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
|
||||||
|
{6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
|
||||||
|
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
|
||||||
|
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
||||||
|
{201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
|
||||||
|
{202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ITimeZoneService::~ITimeZoneService() = default;
|
||||||
|
|
||||||
|
} // namespace Service::Time
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -11,14 +11,12 @@ class System;
|
|||||||
|
|
||||||
namespace Service::Time {
|
namespace Service::Time {
|
||||||
|
|
||||||
namespace TimeZone {
|
class ITimeZoneService : public ServiceFramework<ITimeZoneService> {
|
||||||
class TimeZoneContentManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
|
|
||||||
public:
|
public:
|
||||||
explicit ITimeZoneService(Core::System& system_,
|
explicit ITimeZoneService(Core::System& system_);
|
||||||
TimeZone::TimeZoneContentManager& time_zone_manager_);
|
~ITimeZoneService();
|
||||||
|
|
||||||
|
void UpdateTime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetDeviceLocationName(HLERequestContext& ctx);
|
void GetDeviceLocationName(HLERequestContext& ctx);
|
||||||
@ -30,9 +28,6 @@ private:
|
|||||||
void ToCalendarTimeWithMyRule(HLERequestContext& ctx);
|
void ToCalendarTimeWithMyRule(HLERequestContext& ctx);
|
||||||
void ToPosixTime(HLERequestContext& ctx);
|
void ToPosixTime(HLERequestContext& ctx);
|
||||||
void ToPosixTimeWithMyRule(HLERequestContext& ctx);
|
void ToPosixTimeWithMyRule(HLERequestContext& ctx);
|
||||||
|
|
||||||
private:
|
|
||||||
TimeZone::TimeZoneContentManager& time_zone_content_manager;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Time
|
} // namespace Service::Time
|
@ -1,151 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <sstream>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "common/settings.h"
|
|
||||||
#include "common/time_zone.h"
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/file_sys/content_archive.h"
|
|
||||||
#include "core/file_sys/nca_metadata.h"
|
|
||||||
#include "core/file_sys/registered_cache.h"
|
|
||||||
#include "core/file_sys/romfs.h"
|
|
||||||
#include "core/file_sys/system_archive/system_archive.h"
|
|
||||||
#include "core/file_sys/vfs.h"
|
|
||||||
#include "core/file_sys/vfs_types.h"
|
|
||||||
#include "core/hle/result.h"
|
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
|
||||||
#include "core/hle/service/time/errors.h"
|
|
||||||
#include "core/hle/service/time/time_manager.h"
|
|
||||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
|
||||||
|
|
||||||
namespace Service::Time::TimeZone {
|
|
||||||
|
|
||||||
constexpr u64 time_zone_binary_titleid{0x010000000000080E};
|
|
||||||
|
|
||||||
static FileSys::VirtualDir GetTimeZoneBinary(Core::System& system) {
|
|
||||||
const auto* nand{system.GetFileSystemController().GetSystemNANDContents()};
|
|
||||||
const auto nca{nand->GetEntry(time_zone_binary_titleid, FileSys::ContentRecordType::Data)};
|
|
||||||
|
|
||||||
FileSys::VirtualFile romfs;
|
|
||||||
if (nca) {
|
|
||||||
romfs = nca->GetRomFS();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!romfs) {
|
|
||||||
romfs = FileSys::SystemArchive::SynthesizeSystemArchive(time_zone_binary_titleid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!romfs) {
|
|
||||||
LOG_ERROR(Service_Time, "Failed to find or synthesize {:016X!}", time_zone_binary_titleid);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return FileSys::ExtractRomFS(romfs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<std::string> BuildLocationNameCache(
|
|
||||||
const FileSys::VirtualDir& time_zone_binary) {
|
|
||||||
if (!time_zone_binary) {
|
|
||||||
LOG_ERROR(Service_Time, "Failed to extract RomFS for {:016X}!", time_zone_binary_titleid);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileSys::VirtualFile binary_list{time_zone_binary->GetFile("binaryList.txt")};
|
|
||||||
if (!binary_list) {
|
|
||||||
LOG_ERROR(Service_Time, "{:016X} has no file binaryList.txt!", time_zone_binary_titleid);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<char> raw_data(binary_list->GetSize() + 1);
|
|
||||||
binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize());
|
|
||||||
|
|
||||||
std::stringstream data_stream{raw_data.data()};
|
|
||||||
std::string name;
|
|
||||||
std::vector<std::string> location_name_cache;
|
|
||||||
while (std::getline(data_stream, name)) {
|
|
||||||
name.pop_back(); // Remove carriage return
|
|
||||||
location_name_cache.emplace_back(std::move(name));
|
|
||||||
}
|
|
||||||
return location_name_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeZoneContentManager::TimeZoneContentManager(Core::System& system_)
|
|
||||||
: system{system_}, time_zone_binary{GetTimeZoneBinary(system)},
|
|
||||||
location_name_cache{BuildLocationNameCache(time_zone_binary)} {}
|
|
||||||
|
|
||||||
void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
|
|
||||||
const auto timezone_setting =
|
|
||||||
Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
|
|
||||||
|
|
||||||
if (FileSys::VirtualFile vfs_file;
|
|
||||||
GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) {
|
|
||||||
const auto time_point{
|
|
||||||
time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
|
|
||||||
time_manager.SetupTimeZoneManager(timezone_setting, time_point, location_name_cache, {},
|
|
||||||
vfs_file);
|
|
||||||
} else {
|
|
||||||
time_zone_manager.MarkAsInitialized();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result TimeZoneContentManager::LoadTimeZoneRule(TimeZoneRule& rules,
|
|
||||||
const std::string& location_name) const {
|
|
||||||
FileSys::VirtualFile vfs_file;
|
|
||||||
if (const Result result{GetTimeZoneInfoFile(location_name, vfs_file)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return time_zone_manager.ParseTimeZoneRuleBinary(rules, vfs_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimeZoneContentManager::IsLocationNameValid(const std::string& location_name) const {
|
|
||||||
return std::find(location_name_cache.begin(), location_name_cache.end(), location_name) !=
|
|
||||||
location_name_cache.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_name,
|
|
||||||
FileSys::VirtualFile& vfs_file) const {
|
|
||||||
if (!IsLocationNameValid(location_name)) {
|
|
||||||
return ERROR_TIME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!time_zone_binary) {
|
|
||||||
LOG_ERROR(Service_Time, "Failed to extract RomFS for {:016X}!", time_zone_binary_titleid);
|
|
||||||
return ERROR_TIME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileSys::VirtualDir zoneinfo_dir{time_zone_binary->GetSubdirectory("zoneinfo")};
|
|
||||||
if (!zoneinfo_dir) {
|
|
||||||
LOG_ERROR(Service_Time, "{:016X} has no directory zoneinfo!", time_zone_binary_titleid);
|
|
||||||
return ERROR_TIME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfs_file = zoneinfo_dir->GetFileRelative(location_name);
|
|
||||||
if (!vfs_file) {
|
|
||||||
LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using system timezone.",
|
|
||||||
time_zone_binary_titleid, location_name);
|
|
||||||
const std::string system_time_zone{Common::TimeZone::FindSystemTimeZone()};
|
|
||||||
vfs_file = zoneinfo_dir->GetFile(system_time_zone);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vfs_file) {
|
|
||||||
LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
|
|
||||||
time_zone_binary_titleid, location_name);
|
|
||||||
vfs_file = zoneinfo_dir->GetFile(Common::TimeZone::GetDefaultTimeZone());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vfs_file) {
|
|
||||||
LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"!", time_zone_binary_titleid,
|
|
||||||
location_name);
|
|
||||||
return ERROR_TIME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time::TimeZone
|
|
@ -1,49 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "core/file_sys/vfs_types.h"
|
|
||||||
#include "core/hle/service/time/time_zone_manager.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time {
|
|
||||||
class TimeManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::Time::TimeZone {
|
|
||||||
|
|
||||||
class TimeZoneContentManager final {
|
|
||||||
public:
|
|
||||||
explicit TimeZoneContentManager(Core::System& system_);
|
|
||||||
|
|
||||||
void Initialize(TimeManager& time_manager);
|
|
||||||
|
|
||||||
TimeZoneManager& GetTimeZoneManager() {
|
|
||||||
return time_zone_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TimeZoneManager& GetTimeZoneManager() const {
|
|
||||||
return time_zone_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result LoadTimeZoneRule(TimeZoneRule& rules, const std::string& location_name) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool IsLocationNameValid(const std::string& location_name) const;
|
|
||||||
Result GetTimeZoneInfoFile(const std::string& location_name,
|
|
||||||
FileSys::VirtualFile& vfs_file) const;
|
|
||||||
|
|
||||||
Core::System& system;
|
|
||||||
TimeZoneManager time_zone_manager;
|
|
||||||
const FileSys::VirtualDir time_zone_binary;
|
|
||||||
const std::vector<std::string> location_name_cache;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::TimeZone
|
|
File diff suppressed because it is too large
Load Diff
@ -1,61 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "core/file_sys/vfs_types.h"
|
|
||||||
#include "core/hle/service/time/clock_types.h"
|
|
||||||
#include "core/hle/service/time/time_zone_types.h"
|
|
||||||
|
|
||||||
namespace Service::Time::TimeZone {
|
|
||||||
|
|
||||||
class TimeZoneManager final {
|
|
||||||
public:
|
|
||||||
TimeZoneManager();
|
|
||||||
~TimeZoneManager();
|
|
||||||
|
|
||||||
void SetTotalLocationNameCount(std::size_t value) {
|
|
||||||
total_location_name_count = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetLocationNames(std::vector<std::string> location_names) {
|
|
||||||
total_location_names = location_names;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTimeZoneRuleVersion(const u128& value) {
|
|
||||||
time_zone_rule_version = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarkAsInitialized() {
|
|
||||||
is_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name,
|
|
||||||
FileSys::VirtualFile& vfs_file);
|
|
||||||
Result SetUpdatedTime(const Clock::SteadyClockTimePoint& value);
|
|
||||||
Result GetDeviceLocationName(TimeZone::LocationName& value) const;
|
|
||||||
Result GetTotalLocationNameCount(s32& count) const;
|
|
||||||
Result GetTimeZoneRuleVersion(u128& version) const;
|
|
||||||
Result LoadLocationNameList(std::vector<TimeZone::LocationName>& values) const;
|
|
||||||
Result ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const;
|
|
||||||
Result ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const;
|
|
||||||
Result ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const;
|
|
||||||
Result ToPosixTime(const TimeZoneRule& rules, const CalendarTime& calendar_time,
|
|
||||||
s64& posix_time) const;
|
|
||||||
Result ToPosixTimeWithMyRule(const CalendarTime& calendar_time, s64& posix_time) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool is_initialized{};
|
|
||||||
TimeZoneRule time_zone_rule{};
|
|
||||||
std::string device_location_name{"GMT"};
|
|
||||||
u128 time_zone_rule_version{};
|
|
||||||
std::size_t total_location_name_count{};
|
|
||||||
std::vector<std::string> total_location_names{};
|
|
||||||
Clock::SteadyClockTimePoint time_zone_update_time_point{
|
|
||||||
Clock::SteadyClockTimePoint::GetRandom()};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Time::TimeZone
|
|
@ -1,217 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
|
||||||
#include "core/hle/service/time/time_zone_service.h"
|
|
||||||
#include "core/hle/service/time/time_zone_types.h"
|
|
||||||
|
|
||||||
namespace Service::Time {
|
|
||||||
|
|
||||||
ITimeZoneService::ITimeZoneService(Core::System& system_,
|
|
||||||
TimeZone::TimeZoneContentManager& time_zone_manager_)
|
|
||||||
: ServiceFramework{system_, "ITimeZoneService"}, time_zone_content_manager{time_zone_manager_} {
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
|
|
||||||
{1, nullptr, "SetDeviceLocationName"},
|
|
||||||
{2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
|
|
||||||
{3, &ITimeZoneService::LoadLocationNameList, "LoadLocationNameList"},
|
|
||||||
{4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
|
|
||||||
{5, &ITimeZoneService::GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
|
|
||||||
{6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
|
|
||||||
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
|
|
||||||
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
|
||||||
{201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
|
|
||||||
{202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
|
|
||||||
};
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::GetDeviceLocationName(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
TimeZone::LocationName location_name{};
|
|
||||||
if (const Result result{
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().GetDeviceLocationName(location_name)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, (sizeof(location_name) / 4) + 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(location_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::GetTotalLocationNameCount(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
s32 count{};
|
|
||||||
if (const Result result{
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().GetTotalLocationNameCount(count)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::LoadLocationNameList(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
std::vector<TimeZone::LocationName> location_names{};
|
|
||||||
if (const Result result{
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().LoadLocationNameList(location_names)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.WriteBuffer(location_names);
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(static_cast<s32>(location_names.size()));
|
|
||||||
}
|
|
||||||
void ITimeZoneService::GetTimeZoneRuleVersion(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
u128 rule_version{};
|
|
||||||
if (const Result result{
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().GetTimeZoneRuleVersion(rule_version)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(rule_version);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::LoadTimeZoneRule(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()};
|
|
||||||
|
|
||||||
std::string location_name;
|
|
||||||
for (const auto& byte : raw_location_name) {
|
|
||||||
// Strip extra bytes
|
|
||||||
if (byte == '\0') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
location_name.push_back(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_Time, "called, location_name={}", location_name);
|
|
||||||
|
|
||||||
TimeZone::TimeZoneRule time_zone_rule{};
|
|
||||||
const Result result{time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)};
|
|
||||||
|
|
||||||
std::vector<u8> time_zone_rule_outbuffer(sizeof(TimeZone::TimeZoneRule));
|
|
||||||
std::memcpy(time_zone_rule_outbuffer.data(), &time_zone_rule, sizeof(TimeZone::TimeZoneRule));
|
|
||||||
ctx.WriteBuffer(time_zone_rule_outbuffer);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::ToCalendarTime(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto posix_time{rp.Pop<s64>()};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time);
|
|
||||||
|
|
||||||
TimeZone::TimeZoneRule time_zone_rule{};
|
|
||||||
const auto buffer{ctx.ReadBuffer()};
|
|
||||||
std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
|
|
||||||
|
|
||||||
TimeZone::CalendarInfo calendar_info{};
|
|
||||||
if (const Result result{time_zone_content_manager.GetTimeZoneManager().ToCalendarTime(
|
|
||||||
time_zone_rule, posix_time, calendar_info)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(calendar_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto posix_time{rp.Pop<s64>()};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time);
|
|
||||||
|
|
||||||
TimeZone::CalendarInfo calendar_info{};
|
|
||||||
if (const Result result{
|
|
||||||
time_zone_content_manager.GetTimeZoneManager().ToCalendarTimeWithMyRules(
|
|
||||||
posix_time, calendar_info)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(calendar_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::ToPosixTime(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()};
|
|
||||||
TimeZone::TimeZoneRule time_zone_rule{};
|
|
||||||
std::memcpy(&time_zone_rule, ctx.ReadBuffer().data(), sizeof(TimeZone::TimeZoneRule));
|
|
||||||
|
|
||||||
s64 posix_time{};
|
|
||||||
if (const Result result{time_zone_content_manager.GetTimeZoneManager().ToPosixTime(
|
|
||||||
time_zone_rule, calendar_time, posix_time)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.WriteBuffer(posix_time);
|
|
||||||
|
|
||||||
// TODO(bunnei): Handle multiple times
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw<u32>(1); // Number of times we're returning
|
|
||||||
}
|
|
||||||
|
|
||||||
void ITimeZoneService::ToPosixTimeWithMyRule(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_Time, "called");
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()};
|
|
||||||
|
|
||||||
s64 posix_time{};
|
|
||||||
if (const Result result{time_zone_content_manager.GetTimeZoneManager().ToPosixTimeWithMyRule(
|
|
||||||
calendar_time, posix_time)};
|
|
||||||
result != ResultSuccess) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.WriteBuffer(posix_time);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw<u32>(1); // Number of times we're returning
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::Time
|
|
@ -14,7 +14,6 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/service/time/time_manager.h"
|
|
||||||
#include "ui_configure_system.h"
|
#include "ui_configure_system.h"
|
||||||
#include "yuzu/configuration/config.h"
|
#include "yuzu/configuration/config.h"
|
||||||
#include "yuzu/configuration/configuration_shared.h"
|
#include "yuzu/configuration/configuration_shared.h"
|
||||||
|
Reference in New Issue
Block a user