mirror of
https://github.com/yuzu-emu/yuzu-android
synced 2025-08-11 16:52:34 -07:00
Move time services to new IPC.
Add some fixes/improvements to usage with the new IPC
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/intrusive_list.h"
|
||||
@@ -21,8 +22,14 @@ class System;
|
||||
namespace Service::PSC::Time {
|
||||
using ClockSourceId = Common::UUID;
|
||||
|
||||
enum class TimeType : u8 {
|
||||
UserSystemClock = 0,
|
||||
NetworkSystemClock = 1,
|
||||
LocalSystemClock = 2,
|
||||
};
|
||||
|
||||
struct SteadyClockTimePoint {
|
||||
constexpr bool IdMatches(SteadyClockTimePoint& other) {
|
||||
constexpr bool IdMatches(const SteadyClockTimePoint& other) const {
|
||||
return clock_source_id == other.clock_source_id;
|
||||
}
|
||||
bool operator==(const SteadyClockTimePoint& other) const = default;
|
||||
@@ -42,12 +49,6 @@ struct SystemClockContext {
|
||||
static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext has the wrong size!");
|
||||
static_assert(std::is_trivial_v<SystemClockContext>);
|
||||
|
||||
enum class TimeType : u8 {
|
||||
UserSystemClock,
|
||||
NetworkSystemClock,
|
||||
LocalSystemClock,
|
||||
};
|
||||
|
||||
struct CalendarTime {
|
||||
s16 year;
|
||||
s8 month;
|
||||
@@ -67,14 +68,10 @@ struct CalendarAdditionalInfo {
|
||||
};
|
||||
static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo has the wrong size!");
|
||||
|
||||
struct LocationName {
|
||||
std::array<char, 36> name;
|
||||
};
|
||||
using LocationName = std::array<char, 0x24>;
|
||||
static_assert(sizeof(LocationName) == 0x24, "LocationName has the wrong size!");
|
||||
|
||||
struct RuleVersion {
|
||||
std::array<char, 16> version;
|
||||
};
|
||||
using RuleVersion = std::array<char, 0x10>;
|
||||
static_assert(sizeof(RuleVersion) == 0x10, "RuleVersion has the wrong size!");
|
||||
|
||||
struct ClockSnapshot {
|
||||
@@ -152,8 +149,8 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) {
|
||||
return std::chrono::nanoseconds(a + b);
|
||||
}
|
||||
|
||||
constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTimePoint& a,
|
||||
SteadyClockTimePoint& b) {
|
||||
constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyClockTimePoint& a,
|
||||
const SteadyClockTimePoint& b) {
|
||||
R_UNLESS(out_seconds, ResultInvalidArgument);
|
||||
R_UNLESS(a.IdMatches(b), ResultInvalidArgument);
|
||||
R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits<s64>::max(),
|
||||
@@ -166,3 +163,111 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, SteadyClockTi
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::TimeType> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(Service::PSC::Time::TimeType type, FormatContext& ctx) {
|
||||
const string_view name = [type] {
|
||||
using Service::PSC::Time::TimeType;
|
||||
switch (type) {
|
||||
case TimeType::UserSystemClock:
|
||||
return "UserSystemClock";
|
||||
case TimeType::NetworkSystemClock:
|
||||
return "NetworkSystemClock";
|
||||
case TimeType::LocalSystemClock:
|
||||
return "LocalSystemClock";
|
||||
}
|
||||
return "Invalid";
|
||||
}();
|
||||
return formatter<string_view>::format(name, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "time_point={}", time_point.time_point);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "offset={} steady_time_point={}", context.offset,
|
||||
context.steady_time_point.time_point);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "{}/{}/{} {}:{}:{}", calendar.day, calendar.month,
|
||||
calendar.year, calendar.hour, calendar.minute, calendar.second);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo>
|
||||
: fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "weekday={} yearday={} name={} is_dst={} ut_offset={}",
|
||||
additional.day_of_week, additional.day_of_year,
|
||||
additional.name.data(), additional.is_dst, additional.ut_offset);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const {
|
||||
std::string_view n{name.data(), name.size()};
|
||||
return formatter<string_view>::format(n, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const {
|
||||
std::string_view v{version.data(), version.size()};
|
||||
return formatter<string_view>::format(v, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const {
|
||||
return fmt::format_to(
|
||||
ctx.out(),
|
||||
"user_context={} network_context={} user_time={} network_time={} user_calendar_time={} "
|
||||
"network_calendar_time={} user_calendar_additional_time={} "
|
||||
"network_calendar_additional_time={} steady_clock_time_point={} location={} "
|
||||
"is_automatic_correction_enabled={} type={}",
|
||||
snapshot.user_context, snapshot.network_context, snapshot.user_time,
|
||||
snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time,
|
||||
snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time,
|
||||
snapshot.steady_clock_time_point, snapshot.location_name,
|
||||
snapshot.is_automatic_correction_enabled, snapshot.type);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint>
|
||||
: fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(),
|
||||
"rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}",
|
||||
time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount,
|
||||
time_point.lower, time_point.upper);
|
||||
}
|
||||
};
|
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/power_state_service.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@@ -11,39 +12,34 @@ IPowerStateRequestHandler::IPowerStateRequestHandler(
|
||||
power_state_request_manager} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle, "GetPowerStateRequestEventReadableHandle"},
|
||||
{1, &IPowerStateRequestHandler::GetAndClearPowerStateRequest, "GetAndClearPowerStateRequest"},
|
||||
{0, D<&IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle>, "GetPowerStateRequestEventReadableHandle"},
|
||||
{1, D<&IPowerStateRequestHandler::GetAndClearPowerStateRequest>, "GetAndClearPowerStateRequest"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx) {
|
||||
Result IPowerStateRequestHandler::GetPowerStateRequestEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(m_power_state_request_manager.GetReadableEvent());
|
||||
*out_event = &m_power_state_request_manager.GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IPowerStateRequestHandler::GetAndClearPowerStateRequest(HLERequestContext& ctx) {
|
||||
Result IPowerStateRequestHandler::GetAndClearPowerStateRequest(Out<bool> out_cleared,
|
||||
Out<u32> out_priority) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
u32 priority{};
|
||||
auto cleared = m_power_state_request_manager.GetAndClearPowerStateRequest(priority);
|
||||
*out_cleared = cleared;
|
||||
|
||||
if (cleared) {
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(priority);
|
||||
rb.Push(cleared);
|
||||
return;
|
||||
*out_priority = priority;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(cleared);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/power_state_request_manager.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
@@ -21,10 +22,10 @@ public:
|
||||
|
||||
~IPowerStateRequestHandler() override = default;
|
||||
|
||||
private:
|
||||
void GetPowerStateRequestEventReadableHandle(HLERequestContext& ctx);
|
||||
void GetAndClearPowerStateRequest(HLERequestContext& ctx);
|
||||
Result GetPowerStateRequestEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetAndClearPowerStateRequest(Out<bool> out_cleared, Out<u32> out_priority);
|
||||
|
||||
private:
|
||||
Core::System& m_system;
|
||||
PowerStateRequestManager& m_power_state_request_manager;
|
||||
};
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/power_state_service.h"
|
||||
#include "core/hle/service/psc/time/service_manager.h"
|
||||
#include "core/hle/service/psc/time/static.h"
|
||||
@@ -25,24 +26,24 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
|
||||
m_local_operation{m_system}, m_network_operation{m_system}, m_ephemeral_operation{m_system} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ServiceManager::Handle_GetStaticServiceAsUser, "GetStaticServiceAsUser"},
|
||||
{5, &ServiceManager::Handle_GetStaticServiceAsAdmin, "GetStaticServiceAsAdmin"},
|
||||
{6, &ServiceManager::Handle_GetStaticServiceAsRepair, "GetStaticServiceAsRepair"},
|
||||
{9, &ServiceManager::Handle_GetStaticServiceAsServiceManager, "GetStaticServiceAsServiceManager"},
|
||||
{10, &ServiceManager::Handle_SetupStandardSteadyClockCore, "SetupStandardSteadyClockCore"},
|
||||
{11, &ServiceManager::Handle_SetupStandardLocalSystemClockCore, "SetupStandardLocalSystemClockCore"},
|
||||
{12, &ServiceManager::Handle_SetupStandardNetworkSystemClockCore, "SetupStandardNetworkSystemClockCore"},
|
||||
{13, &ServiceManager::Handle_SetupStandardUserSystemClockCore, "SetupStandardUserSystemClockCore"},
|
||||
{14, &ServiceManager::Handle_SetupTimeZoneServiceCore, "SetupTimeZoneServiceCore"},
|
||||
{15, &ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore, "SetupEphemeralNetworkSystemClockCore"},
|
||||
{50, &ServiceManager::Handle_GetStandardLocalClockOperationEvent, "GetStandardLocalClockOperationEvent"},
|
||||
{51, &ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager, "GetStandardNetworkClockOperationEventForServiceManager"},
|
||||
{52, &ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager, "GetEphemeralNetworkClockOperationEventForServiceManager"},
|
||||
{60, &ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
|
||||
{100, &ServiceManager::Handle_SetStandardSteadyClockBaseTime, "SetStandardSteadyClockBaseTime"},
|
||||
{200, &ServiceManager::Handle_GetClosestAlarmUpdatedEvent, "GetClosestAlarmUpdatedEvent"},
|
||||
{201, &ServiceManager::Handle_CheckAndSignalAlarms, "CheckAndSignalAlarms"},
|
||||
{202, &ServiceManager::Handle_GetClosestAlarmInfo, "GetClosestAlarmInfo "},
|
||||
{0, D<&ServiceManager::GetStaticServiceAsUser>, "GetStaticServiceAsUser"},
|
||||
{5, D<&ServiceManager::GetStaticServiceAsAdmin>, "GetStaticServiceAsAdmin"},
|
||||
{6, D<&ServiceManager::GetStaticServiceAsRepair>, "GetStaticServiceAsRepair"},
|
||||
{9, D<&ServiceManager::GetStaticServiceAsServiceManager>, "GetStaticServiceAsServiceManager"},
|
||||
{10, D<&ServiceManager::SetupStandardSteadyClockCore>, "SetupStandardSteadyClockCore"},
|
||||
{11, D<&ServiceManager::SetupStandardLocalSystemClockCore>, "SetupStandardLocalSystemClockCore"},
|
||||
{12, D<&ServiceManager::SetupStandardNetworkSystemClockCore>, "SetupStandardNetworkSystemClockCore"},
|
||||
{13, D<&ServiceManager::SetupStandardUserSystemClockCore>, "SetupStandardUserSystemClockCore"},
|
||||
{14, D<&ServiceManager::SetupTimeZoneServiceCore>, "SetupTimeZoneServiceCore"},
|
||||
{15, D<&ServiceManager::SetupEphemeralNetworkSystemClockCore>, "SetupEphemeralNetworkSystemClockCore"},
|
||||
{50, D<&ServiceManager::GetStandardLocalClockOperationEvent>, "GetStandardLocalClockOperationEvent"},
|
||||
{51, D<&ServiceManager::GetStandardNetworkClockOperationEventForServiceManager>, "GetStandardNetworkClockOperationEventForServiceManager"},
|
||||
{52, D<&ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager>, "GetEphemeralNetworkClockOperationEventForServiceManager"},
|
||||
{60, D<&ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent"},
|
||||
{100, D<&ServiceManager::SetStandardSteadyClockBaseTime>, "SetStandardSteadyClockBaseTime"},
|
||||
{200, D<&ServiceManager::GetClosestAlarmUpdatedEvent>, "GetClosestAlarmUpdatedEvent"},
|
||||
{201, D<&ServiceManager::CheckAndSignalAlarms>, "CheckAndSignalAlarms"},
|
||||
{202, D<&ServiceManager::GetClosestAlarmInfo>, "GetClosestAlarmInfo "},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
@@ -52,302 +53,39 @@ ServiceManager::ServiceManager(Core::System& system_, std::shared_ptr<TimeManage
|
||||
m_ephemeral_system_context_writer.Link(m_ephemeral_operation);
|
||||
}
|
||||
|
||||
void ServiceManager::SetupSAndP() {
|
||||
if (!m_is_s_and_p_setup) {
|
||||
m_is_s_and_p_setup = true;
|
||||
m_server_manager.RegisterNamedService(
|
||||
"time:s", std::make_shared<StaticService>(
|
||||
m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
|
||||
m_server_manager.RegisterNamedService("time:p",
|
||||
std::make_shared<IPowerStateRequestHandler>(
|
||||
m_system, m_time->m_power_state_request_manager));
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceManager::CheckAndSetupServicesSAndP() {
|
||||
if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
|
||||
m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
|
||||
m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
|
||||
SetupSAndP();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsUser(HLERequestContext& ctx) {
|
||||
Result ServiceManager::GetStaticServiceAsUser(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsUser(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsAdmin(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsRepair(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsRepair(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<StaticService> service{};
|
||||
auto res = GetStaticServiceAsServiceManager(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<StaticService>(std::move(service));
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
struct Parameters {
|
||||
bool reset_detected;
|
||||
Common::UUID clock_source_id;
|
||||
s64 rtc_offset;
|
||||
s64 internal_offset;
|
||||
s64 test_offset;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x30);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto params{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto res = SetupStandardSteadyClockCore(params.clock_source_id, params.rtc_offset,
|
||||
params.internal_offset, params.test_offset,
|
||||
params.reset_detected);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetupStandardLocalSystemClockCore(context, time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
auto accuracy{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetupStandardNetworkSystemClockCore(context, accuracy);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
struct Parameters {
|
||||
bool automatic_correction;
|
||||
SteadyClockTimePoint time_point;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x20);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto params{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto res = SetupStandardUserSystemClockCore(params.time_point, params.automatic_correction);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
struct Parameters {
|
||||
u32 location_count;
|
||||
LocationName name;
|
||||
SteadyClockTimePoint time_point;
|
||||
RuleVersion rule_version;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x50);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto params{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto rule_buffer{ctx.ReadBuffer()};
|
||||
|
||||
auto res = SetupTimeZoneServiceCore(params.name, params.time_point, params.rule_version,
|
||||
params.location_count, rule_buffer);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
auto res = SetupEphemeralNetworkSystemClockCore();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetStandardLocalClockOperationEvent(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStandardNetworkClockOperationEventForServiceManager(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetStandardNetworkClockOperationEventForServiceManager(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetEphemeralNetworkClockOperationEventForServiceManager(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetEphemeralNetworkClockOperationEventForServiceManager(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto base_time{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetStandardSteadyClockBaseTime(base_time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetClosestAlarmUpdatedEvent(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_CheckAndSignalAlarms(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
auto res = CheckAndSignalAlarms();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void ServiceManager::Handle_GetClosestAlarmInfo(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
AlarmInfo alarm_info{};
|
||||
bool is_valid{};
|
||||
s64 time{};
|
||||
auto res = GetClosestAlarmInfo(is_valid, alarm_info, time);
|
||||
|
||||
struct OutParameters {
|
||||
bool is_valid;
|
||||
AlarmInfo alarm_info;
|
||||
s64 time;
|
||||
};
|
||||
static_assert(sizeof(OutParameters) == 0x20);
|
||||
|
||||
OutParameters out_params{
|
||||
.is_valid = is_valid,
|
||||
.alarm_info = alarm_info,
|
||||
.time = time,
|
||||
};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(OutParameters) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<OutParameters>(out_params);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result ServiceManager::GetStaticService(std::shared_ptr<StaticService>& out_service,
|
||||
StaticServiceSetupInfo setup_info, const char* name) {
|
||||
out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service) {
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 0, 0}, "time:u"));
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service) {
|
||||
Result ServiceManager::GetStaticServiceAsAdmin(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 0, 1, 0, 0}, "time:a"));
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service) {
|
||||
Result ServiceManager::GetStaticServiceAsRepair(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{0, 0, 0, 0, 1, 0}, "time:r"));
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticServiceAsServiceManager(
|
||||
std::shared_ptr<StaticService>& out_service) {
|
||||
Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(GetStaticService(out_service, StaticServiceSetupInfo{1, 1, 1, 1, 1, 0}, "time:sm"));
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
|
||||
s64 internal_offset, s64 test_offset,
|
||||
bool is_rtc_reset_detected) {
|
||||
Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected,
|
||||
Common::UUID& clock_source_id, s64 rtc_offset,
|
||||
s64 internal_offset, s64 test_offset) {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. is_rtc_reset_detected={} clock_source_id={} rtc_offset={} "
|
||||
"internal_offset={} test_offset={}",
|
||||
is_rtc_reset_detected, clock_source_id.RawString(), rtc_offset, internal_offset,
|
||||
test_offset);
|
||||
|
||||
m_steady_clock.Initialize(clock_source_id, rtc_offset, internal_offset, test_offset,
|
||||
is_rtc_reset_detected);
|
||||
auto time = m_steady_clock.GetRawTime();
|
||||
@@ -365,6 +103,10 @@ Result ServiceManager::SetupStandardSteadyClockCore(Common::UUID& clock_source_i
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. context={} context.steady_time_point.clock_source_id={} time={}", context,
|
||||
context.steady_time_point.clock_source_id.RawString(), time);
|
||||
|
||||
m_local_system_clock.SetContextWriter(m_local_system_context_writer);
|
||||
m_local_system_clock.Initialize(context, time);
|
||||
|
||||
@@ -374,6 +116,9 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con
|
||||
|
||||
Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context,
|
||||
s64 accuracy) {
|
||||
LOG_DEBUG(Service_Time, "called. context={} steady_time_point.clock_source_id={} accuracy={}",
|
||||
context, context.steady_time_point.clock_source_id.RawString(), accuracy);
|
||||
|
||||
// TODO this is a hack! The network clock should be updated independently, from the ntc service
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
||||
// to avoid it being stuck at 0.
|
||||
@@ -388,8 +133,11 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
|
||||
bool automatic_correction) {
|
||||
Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction,
|
||||
SteadyClockTimePoint& time_point) {
|
||||
LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}",
|
||||
automatic_correction, time_point, time_point.clock_source_id.RawString());
|
||||
|
||||
// TODO this is a hack! The user clock should be updated independently, from the ntc service
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
||||
// to avoid it being stuck at 0.
|
||||
@@ -406,10 +154,16 @@ Result ServiceManager::SetupStandardUserSystemClockCore(SteadyClockTimePoint& ti
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
|
||||
Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
|
||||
u32 location_count,
|
||||
SteadyClockTimePoint& time_point,
|
||||
RuleVersion& rule_version, u32 location_count,
|
||||
std::span<const u8> rule_buffer) {
|
||||
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) {
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. name={} rule_version={} location_count={} time_point={} "
|
||||
"clock_source_id={}",
|
||||
name, rule_version, location_count, time_point,
|
||||
time_point.clock_source_id.RawString());
|
||||
|
||||
if (m_time_zone.ParseBinary(name, rule_buffer) != ResultSuccess) {
|
||||
LOG_ERROR(Service_Time, "Failed to parse time zone binary!");
|
||||
}
|
||||
@@ -424,6 +178,8 @@ Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name,
|
||||
}
|
||||
|
||||
Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
m_ephemeral_network_clock.SetContextWriter(m_ephemeral_system_context_writer);
|
||||
m_ephemeral_network_clock.SetInitialized();
|
||||
|
||||
@@ -431,30 +187,41 @@ Result ServiceManager::SetupEphemeralNetworkSystemClockCore() {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event) {
|
||||
*out_event = m_local_operation.m_event;
|
||||
Result ServiceManager::GetStandardLocalClockOperationEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_local_operation.m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStandardNetworkClockOperationEventForServiceManager(
|
||||
Kernel::KEvent** out_event) {
|
||||
*out_event = m_network_operation.m_event;
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_network_operation.m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetEphemeralNetworkClockOperationEventForServiceManager(
|
||||
Kernel::KEvent** out_event) {
|
||||
*out_event = m_ephemeral_operation.m_event;
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_ephemeral_operation.m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
|
||||
Kernel::KEvent** out_event) {
|
||||
*out_event = &m_user_system_clock.GetEvent();
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_user_system_clock.GetEvent().GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
|
||||
LOG_DEBUG(Service_Time, "called. base_time={}", base_time);
|
||||
|
||||
m_steady_clock.SetRtcOffset(base_time);
|
||||
auto time = m_steady_clock.GetRawTime();
|
||||
auto ticks = m_system.CoreTiming().GetClockTicks();
|
||||
@@ -468,26 +235,63 @@ Result ServiceManager::SetStandardSteadyClockBaseTime(s64 base_time) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event) {
|
||||
*out_event = &m_alarms.GetEvent();
|
||||
Result ServiceManager::GetClosestAlarmUpdatedEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_event = &m_alarms.GetEvent().GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::CheckAndSignalAlarms() {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
m_alarms.CheckAndSignal();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ServiceManager::GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time) {
|
||||
Result ServiceManager::GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info,
|
||||
Out<s64> out_time) {
|
||||
Alarm* alarm{nullptr};
|
||||
out_is_valid = m_alarms.GetClosestAlarm(&alarm);
|
||||
if (out_is_valid) {
|
||||
out_info = {
|
||||
*out_is_valid = m_alarms.GetClosestAlarm(&alarm);
|
||||
if (*out_is_valid) {
|
||||
*out_info = {
|
||||
.alert_time = alarm->GetAlertTime(),
|
||||
.priority = alarm->GetPriority(),
|
||||
};
|
||||
out_time = m_alarms.GetRawTime();
|
||||
*out_time = m_alarms.GetRawTime();
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. out_is_valid={} out_info.alert_time={} out_info.priority={}, out_time={}",
|
||||
*out_is_valid, out_info->alert_time, out_info->priority, *out_time);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void ServiceManager::CheckAndSetupServicesSAndP() {
|
||||
if (m_local_system_clock.IsInitialized() && m_user_system_clock.IsInitialized() &&
|
||||
m_network_system_clock.IsInitialized() && m_steady_clock.IsInitialized() &&
|
||||
m_time_zone.IsInitialized() && m_ephemeral_network_clock.IsInitialized()) {
|
||||
SetupSAndP();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceManager::SetupSAndP() {
|
||||
if (!m_is_s_and_p_setup) {
|
||||
m_is_s_and_p_setup = true;
|
||||
m_server_manager.RegisterNamedService(
|
||||
"time:s", std::make_shared<StaticService>(
|
||||
m_system, StaticServiceSetupInfo{0, 0, 1, 0, 0, 0}, m_time, "time:s"));
|
||||
m_server_manager.RegisterNamedService("time:p",
|
||||
std::make_shared<IPowerStateRequestHandler>(
|
||||
m_system, m_time->m_power_state_request_manager));
|
||||
}
|
||||
}
|
||||
|
||||
Result ServiceManager::GetStaticService(OutInterface<StaticService> out_service,
|
||||
StaticServiceSetupInfo setup_info, const char* name) {
|
||||
*out_service = std::make_shared<StaticService>(m_system, setup_info, m_time, name);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@@ -29,55 +30,38 @@ public:
|
||||
ServerManager* server_manager);
|
||||
~ServiceManager() override = default;
|
||||
|
||||
Result GetStaticServiceAsUser(std::shared_ptr<StaticService>& out_service);
|
||||
Result GetStaticServiceAsAdmin(std::shared_ptr<StaticService>& out_service);
|
||||
Result GetStaticServiceAsRepair(std::shared_ptr<StaticService>& out_service);
|
||||
Result GetStaticServiceAsServiceManager(std::shared_ptr<StaticService>& out_service);
|
||||
Result SetupStandardSteadyClockCore(Common::UUID& clock_source_id, s64 rtc_offset,
|
||||
s64 internal_offset, s64 test_offset,
|
||||
bool is_rtc_reset_detected);
|
||||
Result GetStaticServiceAsUser(OutInterface<StaticService> out_service);
|
||||
Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service);
|
||||
Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service);
|
||||
Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service);
|
||||
Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id,
|
||||
s64 rtc_offset, s64 internal_offset, s64 test_offset);
|
||||
Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time);
|
||||
Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy);
|
||||
Result SetupStandardUserSystemClockCore(SteadyClockTimePoint& time_point,
|
||||
bool automatic_correction);
|
||||
Result SetupTimeZoneServiceCore(LocationName& name, SteadyClockTimePoint& time_point,
|
||||
RuleVersion& rule_version, u32 location_count,
|
||||
std::span<const u8> rule_buffer);
|
||||
Result SetupStandardUserSystemClockCore(bool automatic_correction,
|
||||
SteadyClockTimePoint& time_point);
|
||||
Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version,
|
||||
u32 location_count, SteadyClockTimePoint& time_point,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> rule_buffer);
|
||||
Result SetupEphemeralNetworkSystemClockCore();
|
||||
Result GetStandardLocalClockOperationEvent(Kernel::KEvent** out_event);
|
||||
Result GetStandardNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
|
||||
Result GetEphemeralNetworkClockOperationEventForServiceManager(Kernel::KEvent** out_event);
|
||||
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(Kernel::KEvent** out_event);
|
||||
Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetStandardNetworkClockOperationEventForServiceManager(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetEphemeralNetworkClockOperationEventForServiceManager(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result SetStandardSteadyClockBaseTime(s64 base_time);
|
||||
Result GetClosestAlarmUpdatedEvent(Kernel::KEvent** out_event);
|
||||
Result GetClosestAlarmUpdatedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result CheckAndSignalAlarms();
|
||||
Result GetClosestAlarmInfo(bool& out_is_valid, AlarmInfo& out_info, s64& out_time);
|
||||
Result GetClosestAlarmInfo(Out<bool> out_is_valid, Out<AlarmInfo> out_info, Out<s64> out_time);
|
||||
|
||||
private:
|
||||
void CheckAndSetupServicesSAndP();
|
||||
void SetupSAndP();
|
||||
Result GetStaticService(std::shared_ptr<StaticService>& out_service,
|
||||
Result GetStaticService(OutInterface<StaticService> out_service,
|
||||
StaticServiceSetupInfo setup_info, const char* name);
|
||||
|
||||
void Handle_GetStaticServiceAsUser(HLERequestContext& ctx);
|
||||
void Handle_GetStaticServiceAsAdmin(HLERequestContext& ctx);
|
||||
void Handle_GetStaticServiceAsRepair(HLERequestContext& ctx);
|
||||
void Handle_GetStaticServiceAsServiceManager(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardLocalSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardNetworkSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx);
|
||||
void Handle_SetupEphemeralNetworkSystemClockCore(HLERequestContext& ctx);
|
||||
void Handle_GetStandardLocalClockOperationEvent(HLERequestContext& ctx);
|
||||
void Handle_GetStandardNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
|
||||
void Handle_GetEphemeralNetworkClockOperationEventForServiceManager(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedEvent(HLERequestContext& ctx);
|
||||
void Handle_SetStandardSteadyClockBaseTime(HLERequestContext& ctx);
|
||||
void Handle_GetClosestAlarmUpdatedEvent(HLERequestContext& ctx);
|
||||
void Handle_CheckAndSignalAlarms(HLERequestContext& ctx);
|
||||
void Handle_GetClosestAlarmInfo(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
std::shared_ptr<TimeManager> m_time;
|
||||
ServerManager& m_server_manager;
|
||||
|
@@ -1,9 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/clocks/ephemeral_network_system_clock_core.h"
|
||||
#include "core/hle/service/psc/time/clocks/standard_local_system_clock_core.h"
|
||||
#include "core/hle/service/psc/time/clocks/standard_network_system_clock_core.h"
|
||||
@@ -39,358 +41,122 @@ StaticService::StaticService(Core::System& system_, StaticServiceSetupInfo setup
|
||||
m_time->m_shared_memory} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &StaticService::Handle_GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||
{1, &StaticService::Handle_GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
|
||||
{2, &StaticService::Handle_GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &StaticService::Handle_GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &StaticService::Handle_GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{5, &StaticService::Handle_GetEphemeralNetworkSystemClock, "GetEphemeralNetworkSystemClock"},
|
||||
{20, &StaticService::Handle_GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
|
||||
{50, &StaticService::Handle_SetStandardSteadyClockInternalOffset, "SetStandardSteadyClockInternalOffset"},
|
||||
{51, &StaticService::Handle_GetStandardSteadyClockRtcValue, "GetStandardSteadyClockRtcValue"},
|
||||
{100, &StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, &StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, &StaticService::Handle_GetStandardUserSystemClockInitialYear, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, &StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{201, &StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||
{300, &StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, &StaticService::Handle_GetClockSnapshot, "GetClockSnapshot"},
|
||||
{401, &StaticService::Handle_GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, &StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, &StaticService::Handle_CalculateSpanBetween, "CalculateSpanBetween"},
|
||||
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
|
||||
{1, D<&StaticService::GetStandardNetworkSystemClock>, "GetStandardNetworkSystemClock"},
|
||||
{2, D<&StaticService::GetStandardSteadyClock>, "GetStandardSteadyClock"},
|
||||
{3, D<&StaticService::GetTimeZoneService>, "GetTimeZoneService"},
|
||||
{4, D<&StaticService::GetStandardLocalSystemClock>, "GetStandardLocalSystemClock"},
|
||||
{5, D<&StaticService::GetEphemeralNetworkSystemClock>, "GetEphemeralNetworkSystemClock"},
|
||||
{20, D<&StaticService::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
|
||||
{50, D<&StaticService::SetStandardSteadyClockInternalOffset>, "SetStandardSteadyClockInternalOffset"},
|
||||
{51, D<&StaticService::GetStandardSteadyClockRtcValue>, "GetStandardSteadyClockRtcValue"},
|
||||
{100, D<&StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled>, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, D<&StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled>, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, D<&StaticService::GetStandardUserSystemClockInitialYear>, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, D<&StaticService::IsStandardNetworkSystemClockAccuracySufficient>, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{201, D<&StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime>, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||
{300, D<&StaticService::CalculateMonotonicSystemClockBaseTimePoint>, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, D<&StaticService::GetClockSnapshot>, "GetClockSnapshot"},
|
||||
{401, D<&StaticService::GetClockSnapshotFromSystemClockContext>, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, D<&StaticService::CalculateStandardUserSystemClockDifferenceByUser>, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, D<&StaticService::CalculateSpanBetween>, "CalculateSpanBetween"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshotImpl(ClockSnapshot& out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context, TimeType type) {
|
||||
out_snapshot.user_context = user_context;
|
||||
out_snapshot.network_context = network_context;
|
||||
Result StaticService::GetStandardUserSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_TRY(
|
||||
m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot.steady_clock_time_point));
|
||||
|
||||
out_snapshot.is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
|
||||
R_TRY(m_time_zone.GetLocationName(out_snapshot.location_name));
|
||||
|
||||
R_TRY(GetTimeFromTimePointAndContext(
|
||||
&out_snapshot.user_time, out_snapshot.steady_clock_time_point, out_snapshot.user_context));
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.user_calendar_time,
|
||||
out_snapshot.user_calendar_additional_time,
|
||||
out_snapshot.user_time));
|
||||
|
||||
if (GetTimeFromTimePointAndContext(&out_snapshot.network_time,
|
||||
out_snapshot.steady_clock_time_point,
|
||||
out_snapshot.network_context) != ResultSuccess) {
|
||||
out_snapshot.network_time = 0;
|
||||
}
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot.network_calendar_time,
|
||||
out_snapshot.network_calendar_additional_time,
|
||||
out_snapshot.network_time));
|
||||
out_snapshot.type = type;
|
||||
out_snapshot.unk_CE = 0;
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
|
||||
m_setup_info.can_write_user_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClock(HLERequestContext& ctx) {
|
||||
Result StaticService::GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetStandardUserSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetStandardNetworkSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardSteadyClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SteadyClock> service{};
|
||||
auto res = GetStandardSteadyClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetTimeZoneService(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<TimeZoneService> service{};
|
||||
auto res = GetTimeZoneService(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardLocalSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetStandardLocalSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
std::shared_ptr<SystemClock> service{};
|
||||
auto res = GetEphemeralNetworkSystemClock(service);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(res);
|
||||
rb.PushIpcInterface<SystemClock>(std::move(service));
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KSharedMemory* shared_memory{};
|
||||
auto res = GetSharedMemoryNativeHandle(&shared_memory);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(shared_memory);
|
||||
}
|
||||
|
||||
void StaticService::Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(m_setup_info.can_write_steady_clock ? ResultNotImplemented : ResultPermissionDenied);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void StaticService::Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool is_enabled{};
|
||||
auto res = IsStandardUserSystemClockAutomaticCorrectionEnabled(is_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push<bool>(is_enabled);
|
||||
}
|
||||
|
||||
void StaticService::Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto automatic_correction{rp.Pop<bool>()};
|
||||
|
||||
auto res = SetStandardUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void StaticService::Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool is_sufficient{};
|
||||
auto res = IsStandardNetworkSystemClockAccuracySufficient(is_sufficient);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push<bool>(is_sufficient);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
SteadyClockTimePoint time_point{};
|
||||
auto res = GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<SteadyClockTimePoint>(time_point);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
|
||||
s64 time{};
|
||||
auto res = CalculateMonotonicSystemClockBaseTimePoint(time, context);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push<s64>(time);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetClockSnapshot(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto type{rp.PopEnum<TimeType>()};
|
||||
|
||||
ClockSnapshot snapshot{};
|
||||
auto res = GetClockSnapshot(snapshot, type);
|
||||
|
||||
ctx.WriteBuffer(snapshot);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto clock_type{rp.PopEnum<TimeType>()};
|
||||
[[maybe_unused]] auto alignment{rp.Pop<u32>()};
|
||||
auto user_context{rp.PopRaw<SystemClockContext>()};
|
||||
auto network_context{rp.PopRaw<SystemClockContext>()};
|
||||
|
||||
ClockSnapshot snapshot{};
|
||||
auto res =
|
||||
GetClockSnapshotFromSystemClockContext(snapshot, user_context, network_context, clock_type);
|
||||
|
||||
ctx.WriteBuffer(snapshot);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateStandardUserSystemClockDifferenceByUser(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
ClockSnapshot a{};
|
||||
ClockSnapshot b{};
|
||||
|
||||
auto a_buffer{ctx.ReadBuffer(0)};
|
||||
auto b_buffer{ctx.ReadBuffer(1)};
|
||||
|
||||
std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
|
||||
std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
|
||||
|
||||
s64 difference{};
|
||||
auto res = CalculateStandardUserSystemClockDifferenceByUser(difference, a, b);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(difference);
|
||||
}
|
||||
|
||||
void StaticService::Handle_CalculateSpanBetween(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
ClockSnapshot a{};
|
||||
ClockSnapshot b{};
|
||||
|
||||
auto a_buffer{ctx.ReadBuffer(0)};
|
||||
auto b_buffer{ctx.ReadBuffer(1)};
|
||||
|
||||
std::memcpy(&a, a_buffer.data(), sizeof(ClockSnapshot));
|
||||
std::memcpy(&b, b_buffer.data(), sizeof(ClockSnapshot));
|
||||
|
||||
s64 time{};
|
||||
auto res = CalculateSpanBetween(time, a, b);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(time);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result StaticService::GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_user_system_clock,
|
||||
m_setup_info.can_write_user_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_network_system_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
Result StaticService::GetStandardSteadyClock(OutInterface<SteadyClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Result StaticService::GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service) {
|
||||
out_service =
|
||||
*out_service =
|
||||
std::make_shared<SteadyClock>(m_system, m_time, m_setup_info.can_write_steady_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service) {
|
||||
out_service =
|
||||
Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_service =
|
||||
std::make_shared<TimeZoneService>(m_system, m_time->m_standard_steady_clock, m_time_zone,
|
||||
m_setup_info.can_write_timezone_device_location);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock,
|
||||
m_setup_info.can_write_local_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
Result StaticService::GetStandardLocalSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_local_system_clock,
|
||||
m_setup_info.can_write_local_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service) {
|
||||
out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
Result StaticService::GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_service = std::make_shared<SystemClock>(m_system, m_ephemeral_network_clock,
|
||||
m_setup_info.can_write_network_clock,
|
||||
m_setup_info.can_write_uninitialized_clock);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory) {
|
||||
Result StaticService::GetSharedMemoryNativeHandle(
|
||||
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
*out_shared_memory = &m_shared_memory.GetKSharedMemory();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled) {
|
||||
Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_UNLESS(m_setup_info.can_write_steady_clock, ResultPermissionDenied);
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
Out<bool> out_is_enabled) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); });
|
||||
|
||||
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
|
||||
|
||||
out_is_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
*out_is_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
bool automatic_correction) {
|
||||
LOG_DEBUG(Service_Time, "called. automatic_correction={}", automatic_correction);
|
||||
|
||||
R_UNLESS(m_user_system_clock.IsInitialized() && m_time->m_standard_steady_clock.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
R_UNLESS(m_setup_info.can_write_user_clock, ResultPermissionDenied);
|
||||
@@ -407,22 +173,35 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient) {
|
||||
out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
|
||||
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); });
|
||||
|
||||
*out_is_sufficient = m_network_system_clock.IsAccuracySufficient();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
SteadyClockTimePoint& out_time_point) {
|
||||
Out<SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
|
||||
|
||||
R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized);
|
||||
|
||||
m_user_system_clock.GetTimePoint(out_time_point);
|
||||
m_user_system_clock.GetTimePoint(*out_time_point);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
|
||||
Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
|
||||
SystemClockContext& context) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); });
|
||||
|
||||
R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized);
|
||||
|
||||
SteadyClockTimePoint time_point{};
|
||||
@@ -433,12 +212,16 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(s64& out_time,
|
||||
auto one_second_ns{
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()};
|
||||
auto ticks{m_system.CoreTiming().GetClockTicks()};
|
||||
auto current_time{ConvertToTimeSpan(ticks).count()};
|
||||
out_time = ((context.offset + time_point.time_point) - (current_time / one_second_ns));
|
||||
auto current_time_ns{ConvertToTimeSpan(ticks).count()};
|
||||
*out_time = ((context.offset + time_point.time_point) - (current_time_ns / one_second_ns));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type) {
|
||||
Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) {
|
||||
SCOPE_EXIT(
|
||||
{ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); });
|
||||
|
||||
SystemClockContext user_context{};
|
||||
R_TRY(m_user_system_clock.GetContext(user_context));
|
||||
|
||||
@@ -448,53 +231,101 @@ Result StaticService::GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType typ
|
||||
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
|
||||
Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type,
|
||||
OutClockSnapshot out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context,
|
||||
TimeType type) {
|
||||
SystemClockContext& network_context) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. type={} user_context={} network_context={} out_snapshot={}", type,
|
||||
user_context, network_context, *out_snapshot);
|
||||
});
|
||||
|
||||
R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type));
|
||||
}
|
||||
|
||||
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(s64& out_time,
|
||||
ClockSnapshot& a,
|
||||
ClockSnapshot& b) {
|
||||
Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
|
||||
InClockSnapshot a,
|
||||
InClockSnapshot b) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference);
|
||||
});
|
||||
|
||||
auto diff_s =
|
||||
std::chrono::seconds(b.user_context.offset) - std::chrono::seconds(a.user_context.offset);
|
||||
std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset);
|
||||
|
||||
if (a.user_context == b.user_context ||
|
||||
!a.user_context.steady_time_point.IdMatches(b.user_context.steady_time_point)) {
|
||||
out_time = 0;
|
||||
if (a->user_context == b->user_context ||
|
||||
!a->user_context.steady_time_point.IdMatches(b->user_context.steady_time_point)) {
|
||||
*out_difference = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
if (!a.is_automatic_correction_enabled || !b.is_automatic_correction_enabled) {
|
||||
out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
if (!a->is_automatic_correction_enabled || !b->is_automatic_correction_enabled) {
|
||||
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
if (a.network_context.steady_time_point.IdMatches(a.steady_clock_time_point) ||
|
||||
b.network_context.steady_time_point.IdMatches(b.steady_clock_time_point)) {
|
||||
out_time = 0;
|
||||
if (a->network_context.steady_time_point.IdMatches(a->steady_clock_time_point) ||
|
||||
b->network_context.steady_time_point.IdMatches(b->steady_clock_time_point)) {
|
||||
*out_difference = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
out_time = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
*out_difference = std::chrono::duration_cast<std::chrono::nanoseconds>(diff_s).count();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b) {
|
||||
Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a,
|
||||
InClockSnapshot b) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); });
|
||||
|
||||
s64 time_s{};
|
||||
auto res =
|
||||
GetSpanBetweenTimePoints(&time_s, a.steady_clock_time_point, b.steady_clock_time_point);
|
||||
GetSpanBetweenTimePoints(&time_s, a->steady_clock_time_point, b->steady_clock_time_point);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
R_UNLESS(a.network_time != 0 && b.network_time != 0, ResultTimeNotFound);
|
||||
time_s = b.network_time - a.network_time;
|
||||
R_UNLESS(a->network_time != 0 && b->network_time != 0, ResultTimeNotFound);
|
||||
time_s = b->network_time - a->network_time;
|
||||
}
|
||||
|
||||
out_time =
|
||||
*out_time =
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(time_s)).count();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StaticService::GetClockSnapshotImpl(OutClockSnapshot out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context, TimeType type) {
|
||||
out_snapshot->user_context = user_context;
|
||||
out_snapshot->network_context = network_context;
|
||||
|
||||
R_TRY(
|
||||
m_time->m_standard_steady_clock.GetCurrentTimePoint(out_snapshot->steady_clock_time_point));
|
||||
|
||||
out_snapshot->is_automatic_correction_enabled = m_user_system_clock.GetAutomaticCorrection();
|
||||
|
||||
R_TRY(m_time_zone.GetLocationName(out_snapshot->location_name));
|
||||
|
||||
R_TRY(GetTimeFromTimePointAndContext(&out_snapshot->user_time,
|
||||
out_snapshot->steady_clock_time_point,
|
||||
out_snapshot->user_context));
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->user_calendar_time,
|
||||
out_snapshot->user_calendar_additional_time,
|
||||
out_snapshot->user_time));
|
||||
|
||||
if (GetTimeFromTimePointAndContext(&out_snapshot->network_time,
|
||||
out_snapshot->steady_clock_time_point,
|
||||
out_snapshot->network_context) != ResultSuccess) {
|
||||
out_snapshot->network_time = 0;
|
||||
}
|
||||
|
||||
R_TRY(m_time_zone.ToCalendarTimeWithMyRule(out_snapshot->network_calendar_time,
|
||||
out_snapshot->network_calendar_additional_time,
|
||||
out_snapshot->network_time));
|
||||
out_snapshot->type = type;
|
||||
out_snapshot->unk_CE = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
@@ -29,58 +30,44 @@ class EphemeralNetworkSystemClockCore;
|
||||
class SharedMemory;
|
||||
|
||||
class StaticService final : public ServiceFramework<StaticService> {
|
||||
using InClockSnapshot = InLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
|
||||
using OutClockSnapshot = OutLargeData<ClockSnapshot, BufferAttr_HipcPointer>;
|
||||
|
||||
public:
|
||||
explicit StaticService(Core::System& system, StaticServiceSetupInfo setup_info,
|
||||
std::shared_ptr<TimeManager> time, const char* name);
|
||||
|
||||
~StaticService() override = default;
|
||||
|
||||
Result GetStandardUserSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetStandardNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetStandardSteadyClock(std::shared_ptr<SteadyClock>& out_service);
|
||||
Result GetTimeZoneService(std::shared_ptr<TimeZoneService>& out_service);
|
||||
Result GetStandardLocalSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetEphemeralNetworkSystemClock(std::shared_ptr<SystemClock>& out_service);
|
||||
Result GetSharedMemoryNativeHandle(Kernel::KSharedMemory** out_shared_memory);
|
||||
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(bool& out_is_enabled);
|
||||
Result GetStandardUserSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetStandardNetworkSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetStandardSteadyClock(OutInterface<SteadyClock> out_service);
|
||||
Result GetTimeZoneService(OutInterface<TimeZoneService> out_service);
|
||||
Result GetStandardLocalSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetEphemeralNetworkSystemClock(OutInterface<SystemClock> out_service);
|
||||
Result GetSharedMemoryNativeHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory);
|
||||
Result SetStandardSteadyClockInternalOffset(s64 offset_ns);
|
||||
Result GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value);
|
||||
Result IsStandardUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_is_enabled);
|
||||
Result SetStandardUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction);
|
||||
Result IsStandardNetworkSystemClockAccuracySufficient(bool& out_is_sufficient);
|
||||
Result GetStandardUserSystemClockInitialYear(Out<s32> out_year);
|
||||
Result IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient);
|
||||
Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(
|
||||
SteadyClockTimePoint& out_time_point);
|
||||
Result CalculateMonotonicSystemClockBaseTimePoint(s64& out_time, SystemClockContext& context);
|
||||
Result GetClockSnapshot(ClockSnapshot& out_snapshot, TimeType type);
|
||||
Result GetClockSnapshotFromSystemClockContext(ClockSnapshot& out_snapshot,
|
||||
Out<SteadyClockTimePoint> out_time_point);
|
||||
Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time,
|
||||
SystemClockContext& context);
|
||||
Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type);
|
||||
Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot,
|
||||
SystemClockContext& user_context,
|
||||
SystemClockContext& network_context,
|
||||
TimeType type);
|
||||
Result CalculateStandardUserSystemClockDifferenceByUser(s64& out_time, ClockSnapshot& a,
|
||||
ClockSnapshot& b);
|
||||
Result CalculateSpanBetween(s64& out_time, ClockSnapshot& a, ClockSnapshot& b);
|
||||
SystemClockContext& network_context);
|
||||
Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference,
|
||||
InClockSnapshot a, InClockSnapshot b);
|
||||
Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b);
|
||||
|
||||
private:
|
||||
Result GetClockSnapshotImpl(ClockSnapshot& out_snapshot, SystemClockContext& user_context,
|
||||
Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context,
|
||||
SystemClockContext& network_context, TimeType type);
|
||||
|
||||
void Handle_GetStandardUserSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetStandardNetworkSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetStandardSteadyClock(HLERequestContext& ctx);
|
||||
void Handle_GetTimeZoneService(HLERequestContext& ctx);
|
||||
void Handle_GetStandardLocalSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetEphemeralNetworkSystemClock(HLERequestContext& ctx);
|
||||
void Handle_GetSharedMemoryNativeHandle(HLERequestContext& ctx);
|
||||
void Handle_SetStandardSteadyClockInternalOffset(HLERequestContext& ctx);
|
||||
void Handle_GetStandardSteadyClockRtcValue(HLERequestContext& ctx);
|
||||
void Handle_IsStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
|
||||
void Handle_SetStandardUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockInitialYear(HLERequestContext& ctx);
|
||||
void Handle_IsStandardNetworkSystemClockAccuracySufficient(HLERequestContext& ctx);
|
||||
void Handle_GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
|
||||
void Handle_CalculateMonotonicSystemClockBaseTimePoint(HLERequestContext& ctx);
|
||||
void Handle_GetClockSnapshot(HLERequestContext& ctx);
|
||||
void Handle_GetClockSnapshotFromSystemClockContext(HLERequestContext& ctx);
|
||||
void Handle_CalculateStandardUserSystemClockDifferenceByUser(HLERequestContext& ctx);
|
||||
void Handle_CalculateSpanBetween(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
StaticServiceSetupInfo m_setup_info;
|
||||
std::shared_ptr<TimeManager> m_time;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/steady_clock.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@@ -14,114 +16,40 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
|
||||
can_write_uninitialized_clock} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"},
|
||||
{2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"},
|
||||
{3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"},
|
||||
{100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"},
|
||||
{101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"},
|
||||
{102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"},
|
||||
{200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"},
|
||||
{0, D<&SteadyClock::GetCurrentTimePoint>, "GetCurrentTimePoint"},
|
||||
{2, D<&SteadyClock::GetTestOffset>, "GetTestOffset"},
|
||||
{3, D<&SteadyClock::SetTestOffset>, "SetTestOffset"},
|
||||
{100, D<&SteadyClock::GetRtcValue>, "GetRtcValue"},
|
||||
{101, D<&SteadyClock::IsRtcResetDetected>, "IsRtcResetDetected"},
|
||||
{102, D<&SteadyClock::GetSetupResultValue>, "GetSetupResultValue"},
|
||||
{200, D<&SteadyClock::GetInternalOffset>, "GetInternalOffset"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetCurrentTimePoint(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); });
|
||||
|
||||
SteadyClockTimePoint time_point{};
|
||||
auto res = GetCurrentTimePoint(time_point);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SteadyClockTimePoint) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<SteadyClockTimePoint>(time_point);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetTestOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s64 test_offset{};
|
||||
auto res = GetTestOffset(test_offset);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(test_offset);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_SetTestOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto test_offset{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetTestOffset(test_offset);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetRtcValue(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s64 rtc_value{};
|
||||
auto res = GetRtcValue(rtc_value);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(rtc_value);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_IsRtcResetDetected(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
bool reset_detected{false};
|
||||
auto res = IsRtcResetDetected(reset_detected);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(reset_detected);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetSetupResultValue(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Result result_value{ResultSuccess};
|
||||
auto res = GetSetupResultValue(result_value);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(result_value);
|
||||
}
|
||||
|
||||
void SteadyClock::Handle_GetInternalOffset(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
s64 internal_offset{};
|
||||
auto res = GetInternalOffset(internal_offset);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push(internal_offset);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result SteadyClock::GetCurrentTimePoint(SteadyClockTimePoint& out_time_point) {
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetCurrentTimePoint(out_time_point));
|
||||
R_RETURN(m_clock_core.GetCurrentTimePoint(*out_time_point));
|
||||
}
|
||||
|
||||
Result SteadyClock::GetTestOffset(s64& out_test_offset) {
|
||||
Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_test_offset = m_clock_core.GetTestOffset();
|
||||
*out_test_offset = m_clock_core.GetTestOffset();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::SetTestOffset(s64 test_offset) {
|
||||
LOG_DEBUG(Service_Time, "called. test_offset={}", test_offset);
|
||||
|
||||
R_UNLESS(m_can_write_steady_clock, ResultPermissionDenied);
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
@@ -130,34 +58,43 @@ Result SteadyClock::SetTestOffset(s64 test_offset) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::GetRtcValue(s64& out_rtc_value) {
|
||||
Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetRtcValue(out_rtc_value));
|
||||
R_RETURN(m_clock_core.GetRtcValue(*out_rtc_value));
|
||||
}
|
||||
|
||||
Result SteadyClock::IsRtcResetDetected(bool& out_is_detected) {
|
||||
Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_is_detected = m_clock_core.IsResetDetected();
|
||||
*out_is_detected = m_clock_core.IsResetDetected();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::GetSetupResultValue(Result& out_result) {
|
||||
Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_result = m_clock_core.GetSetupResultValue();
|
||||
*out_result = m_clock_core.GetSetupResultValue();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result SteadyClock::GetInternalOffset(s64& out_internal_offset) {
|
||||
Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) {
|
||||
SCOPE_EXIT(
|
||||
{ LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
out_internal_offset = m_clock_core.GetInternalOffset();
|
||||
*out_internal_offset = m_clock_core.GetInternalOffset();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@@ -22,23 +23,15 @@ public:
|
||||
|
||||
~SteadyClock() override = default;
|
||||
|
||||
Result GetCurrentTimePoint(SteadyClockTimePoint& out_time_point);
|
||||
Result GetTestOffset(s64& out_test_offset);
|
||||
Result GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point);
|
||||
Result GetTestOffset(Out<s64> out_test_offset);
|
||||
Result SetTestOffset(s64 test_offset);
|
||||
Result GetRtcValue(s64& out_rtc_value);
|
||||
Result IsRtcResetDetected(bool& out_is_detected);
|
||||
Result GetSetupResultValue(Result& out_result);
|
||||
Result GetInternalOffset(s64& out_internal_offset);
|
||||
Result GetRtcValue(Out<s64> out_rtc_value);
|
||||
Result IsRtcResetDetected(Out<bool> out_is_detected);
|
||||
Result GetSetupResultValue(Out<Result> out_result);
|
||||
Result GetInternalOffset(Out<s64> out_internal_offset);
|
||||
|
||||
private:
|
||||
void Handle_GetCurrentTimePoint(HLERequestContext& ctx);
|
||||
void Handle_GetTestOffset(HLERequestContext& ctx);
|
||||
void Handle_SetTestOffset(HLERequestContext& ctx);
|
||||
void Handle_GetRtcValue(HLERequestContext& ctx);
|
||||
void Handle_IsRtcResetDetected(HLERequestContext& ctx);
|
||||
void Handle_GetSetupResultValue(HLERequestContext& ctx);
|
||||
void Handle_GetInternalOffset(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
StandardSteadyClockCore& m_clock_core;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/system_clock.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@@ -13,83 +15,28 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo
|
||||
can_write_uninitialized_clock} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &SystemClock::Handle_GetCurrentTime, "GetCurrentTime"},
|
||||
{1, &SystemClock::Handle_SetCurrentTime, "SetCurrentTime"},
|
||||
{2, &SystemClock::Handle_GetSystemClockContext, "GetSystemClockContext"},
|
||||
{3, &SystemClock::Handle_SetSystemClockContext, "SetSystemClockContext"},
|
||||
{4, &SystemClock::Handle_GetOperationEventReadableHandle, "GetOperationEventReadableHandle"},
|
||||
{0, D<&SystemClock::GetCurrentTime>, "GetCurrentTime"},
|
||||
{1, D<&SystemClock::SetCurrentTime>, "SetCurrentTime"},
|
||||
{2, D<&SystemClock::GetSystemClockContext>, "GetSystemClockContext"},
|
||||
{3, D<&SystemClock::SetSystemClockContext>, "SetSystemClockContext"},
|
||||
{4, D<&SystemClock::GetOperationEventReadableHandle>, "GetOperationEventReadableHandle"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_GetCurrentTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result SystemClock::GetCurrentTime(Out<s64> out_time) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); });
|
||||
|
||||
s64 time{};
|
||||
auto res = GetCurrentTime(time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(res);
|
||||
rb.Push<s64>(time);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_SetCurrentTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
auto res = SetCurrentTime(time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_GetSystemClockContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
SystemClockContext context{};
|
||||
auto res = GetSystemClockContext(context);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(SystemClockContext) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<SystemClockContext>(context);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_SetSystemClockContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto context{rp.PopRaw<SystemClockContext>()};
|
||||
|
||||
auto res = SetSystemClockContext(context);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void SystemClock::Handle_GetOperationEventReadableHandle(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
Kernel::KEvent* event{};
|
||||
auto res = GetOperationEventReadableHandle(&event);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(res);
|
||||
rb.PushCopyObjects(event->GetReadableEvent());
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result SystemClock::GetCurrentTime(s64& out_time) {
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetCurrentTime(&out_time));
|
||||
R_RETURN(m_clock_core.GetCurrentTime(out_time.Get()));
|
||||
}
|
||||
|
||||
Result SystemClock::SetCurrentTime(s64 time) {
|
||||
LOG_DEBUG(Service_Time, "called. time={}", time);
|
||||
|
||||
R_UNLESS(m_can_write_clock, ResultPermissionDenied);
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
@@ -97,14 +44,18 @@ Result SystemClock::SetCurrentTime(s64 time) {
|
||||
R_RETURN(m_clock_core.SetCurrentTime(time));
|
||||
}
|
||||
|
||||
Result SystemClock::GetSystemClockContext(SystemClockContext& out_context) {
|
||||
Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); });
|
||||
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
|
||||
R_RETURN(m_clock_core.GetContext(out_context));
|
||||
R_RETURN(m_clock_core.GetContext(*out_context));
|
||||
}
|
||||
|
||||
Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
|
||||
LOG_DEBUG(Service_Time, "called. context={}", context);
|
||||
|
||||
R_UNLESS(m_can_write_clock, ResultPermissionDenied);
|
||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||
ResultClockUninitialized);
|
||||
@@ -112,7 +63,10 @@ Result SystemClock::SetSystemClockContext(SystemClockContext& context) {
|
||||
R_RETURN(m_clock_core.SetContextAndWrite(context));
|
||||
}
|
||||
|
||||
Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event) {
|
||||
Result SystemClock::GetOperationEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
if (!m_operation_event) {
|
||||
m_operation_event = std::make_unique<OperationEvent>(m_system);
|
||||
R_UNLESS(m_operation_event != nullptr, ResultFailed);
|
||||
@@ -120,7 +74,7 @@ Result SystemClock::GetOperationEventReadableHandle(Kernel::KEvent** out_event)
|
||||
m_clock_core.LinkOperationEvent(*m_operation_event);
|
||||
}
|
||||
|
||||
*out_event = m_operation_event->m_event;
|
||||
*out_event = &m_operation_event->m_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@@ -22,19 +23,13 @@ public:
|
||||
|
||||
~SystemClock() override = default;
|
||||
|
||||
Result GetCurrentTime(s64& out_time);
|
||||
Result GetCurrentTime(Out<s64> out_time);
|
||||
Result SetCurrentTime(s64 time);
|
||||
Result GetSystemClockContext(SystemClockContext& out_context);
|
||||
Result GetSystemClockContext(Out<SystemClockContext> out_context);
|
||||
Result SetSystemClockContext(SystemClockContext& context);
|
||||
Result GetOperationEventReadableHandle(Kernel::KEvent** out_event);
|
||||
Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
|
||||
private:
|
||||
void Handle_GetCurrentTime(HLERequestContext& ctx);
|
||||
void Handle_SetCurrentTime(HLERequestContext& ctx);
|
||||
void Handle_GetSystemClockContext(HLERequestContext& ctx);
|
||||
void Handle_SetSystemClockContext(HLERequestContext& ctx);
|
||||
void Handle_GetOperationEventReadableHandle(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
SystemClockCore& m_clock_core;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
namespace {
|
||||
constexpr Result ValidateRule(Tz::Rule& rule) {
|
||||
constexpr Result ValidateRule(const Tz::Rule& rule) {
|
||||
if (rule.typecnt > static_cast<s32>(Tz::TZ_MAX_TYPES) ||
|
||||
rule.timecnt > static_cast<s32>(Tz::TZ_MAX_TIMES) ||
|
||||
rule.charcnt > static_cast<s32>(Tz::TZ_MAX_CHARS)) {
|
||||
@@ -26,7 +26,7 @@ constexpr Result ValidateRule(Tz::Rule& rule) {
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
constexpr bool GetTimeZoneTime(s64& out_time, Tz::Rule& rule, s64 time, s32 index,
|
||||
constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s32 index,
|
||||
s32 index_offset) {
|
||||
s32 found_idx{};
|
||||
s32 expected_index{index + index_offset};
|
||||
@@ -107,7 +107,7 @@ Result TimeZone::GetTimePoint(SteadyClockTimePoint& out_time_point) {
|
||||
|
||||
Result TimeZone::ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule) {
|
||||
const Tz::Rule& rule) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
R_RETURN(ToCalendarTimeImpl(out_calendar_time, out_additional_info, time, rule));
|
||||
}
|
||||
@@ -140,8 +140,8 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary)
|
||||
R_RETURN(ParseBinaryImpl(out_rule, binary));
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule) {
|
||||
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1);
|
||||
@@ -157,7 +157,7 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 ou
|
||||
R_RETURN(res);
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
|
||||
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
||||
u32 out_times_count, CalendarTime& calendar) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
|
||||
@@ -183,7 +183,7 @@ Result TimeZone::ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary)
|
||||
|
||||
Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule) {
|
||||
const Tz::Rule& rule) {
|
||||
R_TRY(ValidateRule(rule));
|
||||
|
||||
Tz::CalendarTimeInternal calendar_internal{};
|
||||
@@ -212,8 +212,8 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule, s32 is_dst) {
|
||||
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst) {
|
||||
R_TRY(ValidateRule(rule));
|
||||
|
||||
calendar.month -= 1;
|
||||
|
@@ -32,23 +32,24 @@ public:
|
||||
Result GetTimePoint(SteadyClockTimePoint& out_time_point);
|
||||
|
||||
Result ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
const Tz::Rule& rule);
|
||||
Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time,
|
||||
CalendarAdditionalInfo& calendar_additional, s64 time);
|
||||
Result ParseBinary(LocationName& name, std::span<const u8> binary);
|
||||
Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
Result ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar);
|
||||
|
||||
private:
|
||||
Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule);
|
||||
Result ToPosixTimeImpl(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, Tz::Rule& rule, s32 is_dst);
|
||||
const Tz::Rule& rule);
|
||||
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
|
||||
|
||||
bool m_initialized{};
|
||||
std::recursive_mutex m_mutex;
|
||||
|
@@ -2,7 +2,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <tz/tz.h>
|
||||
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/psc/time/time_zone_service.h"
|
||||
|
||||
namespace Service::PSC::Time {
|
||||
@@ -14,240 +17,78 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore&
|
||||
can_write_timezone_device_location} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &TimeZoneService::Handle_GetDeviceLocationName, "GetDeviceLocationName"},
|
||||
{1, &TimeZoneService::Handle_SetDeviceLocationName, "SetDeviceLocationName"},
|
||||
{2, &TimeZoneService::Handle_GetTotalLocationNameCount, "GetTotalLocationNameCount"},
|
||||
{3, &TimeZoneService::Handle_LoadLocationNameList, "LoadLocationNameList"},
|
||||
{4, &TimeZoneService::Handle_LoadTimeZoneRule, "LoadTimeZoneRule"},
|
||||
{5, &TimeZoneService::Handle_GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
|
||||
{6, &TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{7, &TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule, "SetDeviceLocationNameWithTimeZoneRule"},
|
||||
{8, &TimeZoneService::Handle_ParseTimeZoneBinary, "ParseTimeZoneBinary"},
|
||||
{20, &TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle, "GetDeviceLocationNameOperationEventReadableHandle"},
|
||||
{100, &TimeZoneService::Handle_ToCalendarTime, "ToCalendarTime"},
|
||||
{101, &TimeZoneService::Handle_ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
||||
{201, &TimeZoneService::Handle_ToPosixTime, "ToPosixTime"},
|
||||
{202, &TimeZoneService::Handle_ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
|
||||
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
||||
{1, D<&TimeZoneService::SetDeviceLocationName>, "SetDeviceLocationName"},
|
||||
{2, D<&TimeZoneService::GetTotalLocationNameCount>, "GetTotalLocationNameCount"},
|
||||
{3, D<&TimeZoneService::LoadLocationNameList>, "LoadLocationNameList"},
|
||||
{4, D<&TimeZoneService::LoadTimeZoneRule>, "LoadTimeZoneRule"},
|
||||
{5, D<&TimeZoneService::GetTimeZoneRuleVersion>, "GetTimeZoneRuleVersion"},
|
||||
{6, D<&TimeZoneService::GetDeviceLocationNameAndUpdatedTime>, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{7, D<&TimeZoneService::SetDeviceLocationNameWithTimeZoneRule>, "SetDeviceLocationNameWithTimeZoneRule"},
|
||||
{8, D<&TimeZoneService::ParseTimeZoneBinary>, "ParseTimeZoneBinary"},
|
||||
{20, D<&TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle>, "GetDeviceLocationNameOperationEventReadableHandle"},
|
||||
{100, D<&TimeZoneService::ToCalendarTime>, "ToCalendarTime"},
|
||||
{101, D<&TimeZoneService::ToCalendarTimeWithMyRule>, "ToCalendarTimeWithMyRule"},
|
||||
{201, D<&TimeZoneService::ToPosixTime>, "ToPosixTime"},
|
||||
{202, D<&TimeZoneService::ToPosixTimeWithMyRule>, "ToPosixTimeWithMyRule"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); });
|
||||
|
||||
LocationName name{};
|
||||
auto res = GetDeviceLocationName(name);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(LocationName) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<LocationName>(name);
|
||||
R_RETURN(m_time_zone.GetLocationName(*out_location_name));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_SetDeviceLocationName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
[[maybe_unused]] auto name{rp.PopRaw<LocationName>()};
|
||||
|
||||
if (!m_can_write_timezone_device_location) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultPermissionDenied);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetTotalLocationNameCount(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); });
|
||||
|
||||
u32 count{};
|
||||
auto res = GetTotalLocationNameCount(count);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
R_RETURN(m_time_zone.GetTotalLocationCount(*out_count));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_LoadLocationNameList(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::LoadLocationNameList(
|
||||
Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_LoadTimeZoneRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) {
|
||||
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); });
|
||||
|
||||
RuleVersion rule_version{};
|
||||
auto res = GetTimeZoneRuleVersion(rule_version);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(RuleVersion) / sizeof(u32)};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<RuleVersion>(rule_version);
|
||||
R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(
|
||||
Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}",
|
||||
*out_location_name, *out_time_point);
|
||||
});
|
||||
|
||||
LocationName name{};
|
||||
SteadyClockTimePoint time_point{};
|
||||
auto res = GetDeviceLocationNameAndUpdatedTime(time_point, name);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(LocationName) / sizeof(u32)) +
|
||||
(sizeof(SteadyClockTimePoint) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<LocationName>(name);
|
||||
rb.PushRaw<SteadyClockTimePoint>(time_point);
|
||||
R_TRY(m_time_zone.GetLocationName(*out_location_name));
|
||||
R_RETURN(m_time_zone.GetTimePoint(*out_time_point));
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(
|
||||
LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) {
|
||||
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto name{rp.PopRaw<LocationName>()};
|
||||
|
||||
auto binary{ctx.ReadBuffer()};
|
||||
auto res = SetDeviceLocationNameWithTimeZoneRule(name, binary);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ParseTimeZoneBinary(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
auto binary{ctx.ReadBuffer()};
|
||||
|
||||
Tz::Rule rule{};
|
||||
auto res = ParseTimeZoneBinary(rule, binary);
|
||||
|
||||
ctx.WriteBuffer(rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_GetDeviceLocationNameOperationEventReadableHandle(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNotImplemented);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToCalendarTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
auto rule_buffer{ctx.ReadBuffer()};
|
||||
Tz::Rule rule{};
|
||||
std::memcpy(&rule, rule_buffer.data(), sizeof(Tz::Rule));
|
||||
|
||||
CalendarTime calendar_time{};
|
||||
CalendarAdditionalInfo additional_info{};
|
||||
auto res = ToCalendarTime(calendar_time, additional_info, time, rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) +
|
||||
(sizeof(CalendarAdditionalInfo) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<CalendarTime>(calendar_time);
|
||||
rb.PushRaw<CalendarAdditionalInfo>(additional_info);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto time{rp.Pop<s64>()};
|
||||
|
||||
CalendarTime calendar_time{};
|
||||
CalendarAdditionalInfo additional_info{};
|
||||
auto res = ToCalendarTimeWithMyRule(calendar_time, additional_info, time);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(CalendarTime) / sizeof(u32)) +
|
||||
(sizeof(CalendarAdditionalInfo) / sizeof(u32))};
|
||||
rb.Push(res);
|
||||
rb.PushRaw<CalendarTime>(calendar_time);
|
||||
rb.PushRaw<CalendarAdditionalInfo>(additional_info);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToPosixTime(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar{rp.PopRaw<CalendarTime>()};
|
||||
|
||||
auto binary{ctx.ReadBuffer()};
|
||||
|
||||
Tz::Rule rule{};
|
||||
std::memcpy(&rule, binary.data(), sizeof(Tz::Rule));
|
||||
|
||||
u32 count{};
|
||||
std::array<s64, 2> times{};
|
||||
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
|
||||
|
||||
auto res = ToPosixTime(count, times, times_count, calendar, rule);
|
||||
|
||||
ctx.WriteBuffer(times);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
void TimeZoneService::Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar{rp.PopRaw<CalendarTime>()};
|
||||
|
||||
u32 count{};
|
||||
std::array<s64, 2> times{};
|
||||
u32 times_count{static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(s64))};
|
||||
|
||||
auto res = ToPosixTimeWithMyRule(count, times, times_count, calendar);
|
||||
|
||||
ctx.WriteBuffer(times);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(res);
|
||||
rb.Push(count);
|
||||
}
|
||||
|
||||
// =============================== Implementations ===========================
|
||||
|
||||
Result TimeZoneService::GetDeviceLocationName(LocationName& out_location_name) {
|
||||
R_RETURN(m_time_zone.GetLocationName(out_location_name));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetTotalLocationNameCount(u32& out_count) {
|
||||
R_RETURN(m_time_zone.GetTotalLocationCount(out_count));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetTimeZoneRuleVersion(RuleVersion& out_rule_version) {
|
||||
R_RETURN(m_time_zone.GetRuleVersion(out_rule_version));
|
||||
}
|
||||
|
||||
Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
|
||||
LocationName& location_name) {
|
||||
R_TRY(m_time_zone.GetLocationName(location_name));
|
||||
R_RETURN(m_time_zone.GetTimePoint(out_time_point));
|
||||
}
|
||||
|
||||
Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
|
||||
std::span<const u8> binary) {
|
||||
R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied);
|
||||
R_TRY(m_time_zone.ParseBinary(location_name, binary));
|
||||
|
||||
@@ -258,32 +99,71 @@ Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule(LocationName& loca
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TimeZoneService::ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary) {
|
||||
R_RETURN(m_time_zone.ParseBinaryInto(out_rule, binary));
|
||||
Result TimeZoneService::ParseTimeZoneBinary(OutRule out_rule,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> binary) {
|
||||
LOG_DEBUG(Service_Time, "called.");
|
||||
|
||||
R_RETURN(m_time_zone.ParseBinaryInto(*out_rule, binary));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
Tz::Rule& rule) {
|
||||
R_RETURN(m_time_zone.ToCalendarTime(out_calendar_time, out_additional_info, time, rule));
|
||||
Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_Time, "called. This function is not implemented!");
|
||||
|
||||
R_RETURN(ResultNotImplemented);
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info,
|
||||
s64 time) {
|
||||
R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time));
|
||||
}
|
||||
Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time,
|
||||
InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
|
||||
*out_calendar_time, *out_additional_info);
|
||||
});
|
||||
|
||||
Result TimeZoneService::ToPosixTime(u32& out_count, std::span<s64, 2> out_times,
|
||||
u32 out_times_count, CalendarTime& calendar_time,
|
||||
Tz::Rule& rule) {
|
||||
R_RETURN(m_time_zone.ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times,
|
||||
u32 out_times_count, CalendarTime& calendar_time) {
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTimeWithMyRule(out_count, out_times, out_times_count, calendar_time));
|
||||
m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get()));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info,
|
||||
s64 time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time,
|
||||
*out_calendar_time, *out_additional_info);
|
||||
});
|
||||
|
||||
R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count, CalendarTime& calendar_time,
|
||||
InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
||||
"out_times_count={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTime(*out_count, out_times, *out_times_count, calendar_time, *rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count,
|
||||
CalendarTime& calendar_time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
||||
"out_times_count={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, *out_times_count, calendar_time));
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/psc/time/common.h"
|
||||
#include "core/hle/service/psc/time/manager.h"
|
||||
@@ -20,45 +21,41 @@ struct Rule;
|
||||
namespace Service::PSC::Time {
|
||||
|
||||
class TimeZoneService final : public ServiceFramework<TimeZoneService> {
|
||||
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
||||
using OutRule = OutLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
||||
|
||||
public:
|
||||
explicit TimeZoneService(Core::System& system, StandardSteadyClockCore& clock_core,
|
||||
TimeZone& time_zone, bool can_write_timezone_device_location);
|
||||
|
||||
~TimeZoneService() override = default;
|
||||
|
||||
Result GetDeviceLocationName(LocationName& out_location_name);
|
||||
Result GetTotalLocationNameCount(u32& out_count);
|
||||
Result GetTimeZoneRuleVersion(RuleVersion& out_rule_version);
|
||||
Result GetDeviceLocationNameAndUpdatedTime(SteadyClockTimePoint& out_time_point,
|
||||
LocationName& location_name);
|
||||
Result GetDeviceLocationName(Out<LocationName> out_location_name);
|
||||
Result SetDeviceLocationName(LocationName& location_name);
|
||||
Result GetTotalLocationNameCount(Out<u32> out_count);
|
||||
Result LoadLocationNameList(Out<u32> out_count,
|
||||
OutArray<LocationName, BufferAttr_HipcMapAlias> out_names,
|
||||
u32 index);
|
||||
Result LoadTimeZoneRule(OutRule out_rule, LocationName& location_name);
|
||||
Result GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version);
|
||||
Result GetDeviceLocationNameAndUpdatedTime(Out<LocationName> location_name,
|
||||
Out<SteadyClockTimePoint> out_time_point);
|
||||
Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name,
|
||||
std::span<const u8> binary);
|
||||
Result ParseTimeZoneBinary(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToCalendarTime(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time, Tz::Rule& rule);
|
||||
Result ToCalendarTimeWithMyRule(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar_time, Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64, 2> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar_time);
|
||||
InBuffer<BufferAttr_HipcAutoSelect> binary);
|
||||
Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary);
|
||||
Result GetDeviceLocationNameOperationEventReadableHandle(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result ToCalendarTime(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule);
|
||||
Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time);
|
||||
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count, CalendarTime& calendar_time, InRule rule);
|
||||
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count, CalendarTime& calendar_time);
|
||||
|
||||
private:
|
||||
void Handle_GetDeviceLocationName(HLERequestContext& ctx);
|
||||
void Handle_SetDeviceLocationName(HLERequestContext& ctx);
|
||||
void Handle_GetTotalLocationNameCount(HLERequestContext& ctx);
|
||||
void Handle_LoadLocationNameList(HLERequestContext& ctx);
|
||||
void Handle_LoadTimeZoneRule(HLERequestContext& ctx);
|
||||
void Handle_GetTimeZoneRuleVersion(HLERequestContext& ctx);
|
||||
void Handle_GetDeviceLocationNameAndUpdatedTime(HLERequestContext& ctx);
|
||||
void Handle_SetDeviceLocationNameWithTimeZoneRule(HLERequestContext& ctx);
|
||||
void Handle_ParseTimeZoneBinary(HLERequestContext& ctx);
|
||||
void Handle_GetDeviceLocationNameOperationEventReadableHandle(HLERequestContext& ctx);
|
||||
void Handle_ToCalendarTime(HLERequestContext& ctx);
|
||||
void Handle_ToCalendarTimeWithMyRule(HLERequestContext& ctx);
|
||||
void Handle_ToPosixTime(HLERequestContext& ctx);
|
||||
void Handle_ToPosixTimeWithMyRule(HLERequestContext& ctx);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
StandardSteadyClockCore& m_clock_core;
|
||||
|
Reference in New Issue
Block a user