// SPDX-License-Identifier: MPL-2.0 // Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) #pragma once #include #include #include #include #include namespace skyline::service::timesrv::core { struct TimeSharedMemoryLayout; /** * @brief TimeSharedMemory holds context data about clocks in a double buffered format */ class TimeSharedMemory { private: std::shared_ptr kTimeSharedMemory; TimeSharedMemoryLayout *timeSharedMemory; public: TimeSharedMemory(const DeviceState &state); std::shared_ptr GetSharedMemory() { return kTimeSharedMemory; } /** * @brief Fills in the steady clock section of shmem, the current time is subtracted from baseTimePoint to workout the offset */ void SetupStandardSteadyClock(UUID rtcId, TimeSpanType baseTimePoint); void SetSteadyClockRawTimePoint(TimeSpanType timePoint); void UpdateLocalSystemClockContext(const SystemClockContext &context); void UpdateNetworkSystemClockContext(const SystemClockContext &context); void SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled); }; /** * @brief Base class for callbacks that run after a system clock context is updated */ class SystemClockContextUpdateCallback { private: std::list> operationEvents; //!< List of KEvents to be signalled when this callback is called std::mutex mutex; //!< Synchronises access to operationEvents std::optional context; //!< The context that used when this callback was last called protected: /** * @brief Updates the base callback context with the one supplied as an argument * @return true if the context was updated */ bool UpdateBaseContext(const SystemClockContext &newContext); /** * @brief Signals all events in the operation event list */ void SignalOperationEvent(); public: virtual ~SystemClockContextUpdateCallback() = default; /** * @brief Adds an operation event to be siignalled on context updates */ void AddOperationEvent(const std::shared_ptr &event); /** * @brief Replaces the current context with the supplied one and signals events if the context differs from the last used one */ virtual Result UpdateContext(const SystemClockContext &newContext) = 0; }; /** * @brief Update callback for the local system clock, handles writing data to shmem */ class LocalSystemClockUpdateCallback : public SystemClockContextUpdateCallback { private: TimeSharedMemory &timeSharedMemory; public: LocalSystemClockUpdateCallback(TimeSharedMemory &timeSharedMemory); Result UpdateContext(const SystemClockContext &newContext) override; }; /** * @brief Update callback for the network system clock, handles writing data to shmem */ class NetworkSystemClockUpdateCallback : public SystemClockContextUpdateCallback { private: TimeSharedMemory &timeSharedMemory; public: NetworkSystemClockUpdateCallback(TimeSharedMemory &timeSharedMemory); Result UpdateContext(const SystemClockContext &newContext) override; }; /** * @brief Update callback for the ephemeral network system clock, only handles signalling the event as there is no shmem entry for ephemeral */ class EphemeralNetworkSystemClockUpdateCallback : public SystemClockContextUpdateCallback { public: Result UpdateContext(const SystemClockContext &newContext) override; }; }