Various timesrv cleanups and comments

Mainly just adapts the rest of time to add some things missed in the
initial commit as they required TZ, everything else is just renames from
switchbrew and comments.
This commit is contained in:
Billy Laws 2021-03-04 19:38:34 +00:00 committed by ◱ Mark
parent ba418976b0
commit 74cd0bc2c3
14 changed files with 113 additions and 45 deletions

View File

@ -8,8 +8,8 @@
namespace skyline::service::glue {
/**
* @brief IStaticService (covers time:a, time:r, time:u) is glue's version of pcv::IStaticService, it adds some more functions and provides the user variant
* @url https://switchbrew.org/wiki/PSC_services#time:su.2C_time:s
* @brief IStaticService (covers time:a, time:r, time:u) is glue's extension of pcv::IStaticService, it adds some more functions and provides the user variant that most applications use
* @url https://switchbrew.org/wiki/Glue_services#time:a.2C_time:r.2C_time:u
*/
class IStaticService : public BaseService {
private:

View File

@ -13,9 +13,13 @@ namespace skyline::service::timesrv {
struct TimeServiceObject;
}
}
namespace skyline::service::glue {
/**
* @brief ITimeZoneService is glue's extension of psc::ITimeZoneService, it adds support for reading TimeZone location data and simplifies rule handling. This is the variant normally used by applications.
* @url https://switchbrew.org/wiki/Glue_services#ITimeZoneService
*/
class ITimeZoneService : public BaseService {
private:
std::shared_ptr<timesrv::ITimeZoneService> core;
@ -32,6 +36,10 @@ namespace skyline::service::glue {
Result GetTotalLocationNameCount(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief Returns a list of available timezone location names beginning from the given index
* @url https://switchbrew.org/wiki/Glue_services#LoadLocationNameList
*/
Result LoadLocationNameList(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
Result LoadTimeZoneRule(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);

View File

@ -64,9 +64,9 @@ namespace skyline::service {
SERVICE_CASE(hid::IHidServer, "hid")
SERVICE_CASE(timesrv::IStaticService, "time:s", globalServiceState->timesrv, timesrv::constant::StaticServiceSystemPermissions) // Both of these would be registered after TimeServiceManager::Setup normally but we call that in the GlobalServiceState constructor so can just list them here directly
SERVICE_CASE(timesrv::IStaticService, "time:su", globalServiceState->timesrv, timesrv::constant::StaticServiceSystemUpdatePermissions)
SERVICE_CASE(glue::IStaticService, "time:a", globalServiceState->timesrv.managerServer.GetAdminStaticService(state, *this), globalServiceState->timesrv, timesrv::constant::StaticServiceAdminPermissions)
SERVICE_CASE(glue::IStaticService, "time:r", globalServiceState->timesrv.managerServer.GetRepairStaticService(state, *this), globalServiceState->timesrv, timesrv::constant::StaticServiceRepairPermissions)
SERVICE_CASE(glue::IStaticService, "time:u", globalServiceState->timesrv.managerServer.GetUserStaticService(state, *this), globalServiceState->timesrv, timesrv::constant::StaticServiceUserPermissions)
SERVICE_CASE(glue::IStaticService, "time:a", globalServiceState->timesrv.managerServer.GetStaticServiceAsAdmin(state, *this), globalServiceState->timesrv, timesrv::constant::StaticServiceAdminPermissions)
SERVICE_CASE(glue::IStaticService, "time:r", globalServiceState->timesrv.managerServer.GetStaticServiceAsRepair(state, *this), globalServiceState->timesrv, timesrv::constant::StaticServiceRepairPermissions)
SERVICE_CASE(glue::IStaticService, "time:u", globalServiceState->timesrv.managerServer.GetStaticServiceAsUser(state, *this), globalServiceState->timesrv, timesrv::constant::StaticServiceUserPermissions)
SERVICE_CASE(fssrv::IFileSystemProxy, "fsp-srv")
SERVICE_CASE(nvdrv::INvDrvServices, "nvdrv")
SERVICE_CASE(nvdrv::INvDrvServices, "nvdrv:a")

View File

@ -127,14 +127,25 @@ namespace skyline::service::timesrv {
out.steadyClockTimePoint = *timePoint;
out.automaticCorrectionEnabled = core.userSystemClock.IsAutomaticCorrectionEnabled();
// TODO GetDeviceLocationName
auto locationName{core.timeZoneManager.GetLocationName()};
if (!locationName)
return locationName;
out.locationName = *locationName;
auto userPosixTime{ClockSnapshot::GetCurrentTime(out.steadyClockTimePoint, out.userContext)};
if (!userPosixTime)
return userPosixTime;
out.userPosixTime = *userPosixTime;
// TODO CalendarTimeWithMyRule
auto userCalendarTime{core.timeZoneManager.ToCalendarTimeWithMyRule(*userPosixTime)};
if (!userCalendarTime)
return userCalendarTime;
out.userCalendarTime = userCalendarTime->calendarTime;
out.userCalendarAdditionalInfo = userCalendarTime->additionalInfo;
// Not necessarily a fatal error if this fails
auto networkPosixTime{ClockSnapshot::GetCurrentTime(out.steadyClockTimePoint, out.networkContext)};
@ -143,7 +154,12 @@ namespace skyline::service::timesrv {
else
out.networkPosixTime = 0;
// TODO CalendarTimeWithMyRule
auto networkCalendarTime{core.timeZoneManager.ToCalendarTimeWithMyRule(out.networkPosixTime)};
if (!networkCalendarTime)
return networkCalendarTime;
out.networkCalendarTime = networkCalendarTime->calendarTime;
out.networkCalendarAdditionalInfo = networkCalendarTime->additionalInfo;
out._unk_ = unk;
out.version = 0;

View File

@ -47,4 +47,4 @@ namespace skyline::service::timesrv {
SFUNC(0xC8, ISteadyClock, GetInternalOffset),
)
};
}
}

View File

@ -57,7 +57,7 @@ namespace skyline::service::timesrv {
return updateTime;
response.Push(*locationName);
response.Push<u32>(0);
response.Push<u32>(0); // Padding
response.Push(*updateTime);
return {};
@ -77,11 +77,11 @@ namespace skyline::service::timesrv {
}
Result ITimeZoneService::ParseTimeZoneBinaryIpc(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
return core.timeZoneManager.ParseTimeZoneBinary(request.inputBuf.at(0), request.outputBuf.at(0));
return core::TimeZoneManager::ParseTimeZoneBinary(request.inputBuf.at(0), request.outputBuf.at(0));
}
Result ITimeZoneService::ParseTimeZoneBinary(span<u8> binary, span<u8> rule) {
return core.timeZoneManager.ParseTimeZoneBinary(binary, rule);
return core::TimeZoneManager::ParseTimeZoneBinary(binary, rule);
}
Result ITimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
@ -90,7 +90,7 @@ namespace skyline::service::timesrv {
Result ITimeZoneService::ToCalendarTime(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto posixTime{request.Pop<PosixTime>()};
auto calendarTime{core.timeZoneManager.ToCalendarTime(reinterpret_cast<tz_timezone_t>(request.inputBuf.at(0).data()), posixTime)};
auto calendarTime{core::TimeZoneManager::ToCalendarTime(reinterpret_cast<tz_timezone_t>(request.inputBuf.at(0).data()), posixTime)};
if (calendarTime)
response.Push(*calendarTime);
@ -110,7 +110,7 @@ namespace skyline::service::timesrv {
Result ITimeZoneService::ToPosixTime(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto calendarTime{request.Pop<CalendarTime>()};
auto posixTime{core.timeZoneManager.ToPosixTime(reinterpret_cast<tz_timezone_t>(request.inputBuf.at(0).data()), calendarTime)};
auto posixTime{core::TimeZoneManager::ToPosixTime(reinterpret_cast<tz_timezone_t>(request.inputBuf.at(0).data()), calendarTime)};
if (!posixTime)
return posixTime;

View File

@ -11,7 +11,7 @@ namespace skyline::service::timesrv {
}
/**
* @brief ITimeZoneService is used to retrieve and set timezone info and convert between times and dates
* @brief ITimeZoneService is used to retrieve and set timezone info and convert between times and dates by the system
* @url https://switchbrew.org/wiki/PSC_services#ITimeZoneService
*/
class ITimeZoneService : public BaseService {

View File

@ -5,7 +5,7 @@
namespace skyline::service::timesrv {
using PosixTime = i64; //!< Unit for time in seconds since the epoch
using LocationName = std::array<char, 0x18>;
using LocationName = std::array<char, 0x24>;
/**
* @brief Stores a quantity of time with nanosecond accuracy and provides helper functions to convert it to other units
@ -58,6 +58,7 @@ namespace skyline::service::timesrv {
/**
* @brief Holds details about a point in time sourced from a steady clock (e.g. RTC)
* @url https://switchbrew.org/w/index.php?title=PSC_services#SteadyClockTimePoint
*/
struct __attribute__((packed)) SteadyClockTimePoint {
i64 timePoint; //!< Time in seconds
@ -69,6 +70,7 @@ namespace skyline::service::timesrv {
/**
* @brief Describes a system clocks offset from its associated steady clock
* @url https://switchbrew.org/w/index.php?title=PSC_services#SystemClockContext
*/
struct __attribute__((packed)) SystemClockContext {
i64 offset; // Offset between the steady timepoint and the epoch
@ -80,6 +82,7 @@ namespace skyline::service::timesrv {
/**
* @brief A particular time point in Nintendo's calendar format
* @url https://switchbrew.org/w/index.php?title=PSC_services#CalendarTime
*/
struct CalendarTime {
u16 year; //!< The current year minus 1900
@ -94,6 +97,7 @@ namespace skyline::service::timesrv {
/**
* @brief Additional metadata about the time alongside CalendarTime
* @url https://switchbrew.org/w/index.php?title=PSC_services#CalendarAdditionalInfo
*/
struct CalendarAdditionalInfo {
u32 dayOfWeek; //!< 0-6
@ -126,7 +130,7 @@ namespace skyline::service::timesrv {
CalendarAdditionalInfo userCalendarAdditionalInfo;
CalendarAdditionalInfo networkCalendarAdditionalInfo;
SteadyClockTimePoint steadyClockTimePoint;
std::array<u8, 36> locationName;
LocationName locationName;
u8 automaticCorrectionEnabled;
u8 _unk_;
u16 version;

View File

@ -3,7 +3,7 @@
#include <os.h>
#include <vfs/filesystem.h>
#include <time.h>
#include <ctime>
#include "core.h"
#include "time_manager_server.h"

View File

@ -2,26 +2,26 @@
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <common.h>
#include <services/serviceman.h>
#include "core.h"
#include "IStaticService.h"
#include "time_manager_server.h"
namespace skyline::service::timesrv {
TimeManagerServer::TimeManagerServer(core::TimeServiceObject &core) : core(core) {}
std::shared_ptr<IStaticService> TimeManagerServer::GetUserStaticService(const DeviceState &state, ServiceManager &manager) {
std::shared_ptr<IStaticService> TimeManagerServer::GetStaticServiceAsUser(const DeviceState &state, ServiceManager &manager) {
return std::make_shared<IStaticService>(state, manager, core, constant::StaticServiceUserPermissions);
}
std::shared_ptr<IStaticService> TimeManagerServer::GetAdminStaticService(const DeviceState &state, ServiceManager &manager) {
std::shared_ptr<IStaticService> TimeManagerServer::GetStaticServiceAsAdmin(const DeviceState &state, ServiceManager &manager) {
return std::make_shared<IStaticService>(state, manager, core, constant::StaticServiceAdminPermissions);
}
std::shared_ptr<IStaticService> TimeManagerServer::GetRepairStaticService(const DeviceState &state, ServiceManager &manager) {
std::shared_ptr<IStaticService> TimeManagerServer::GetStaticServiceAsRepair(const DeviceState &state, ServiceManager &manager) {
return std::make_shared<IStaticService>(state, manager, core, constant::StaticServiceRepairPermissions);
}
std::shared_ptr<IStaticService> TimeManagerServer::GetManagerStaticService(const DeviceState &state, ServiceManager &manager) {
std::shared_ptr<IStaticService> TimeManagerServer::GetStaticServiceAsServiceManager(const DeviceState &state, ServiceManager &manager) {
return std::make_shared<IStaticService>(state, manager, core, constant::StaticServiceManagerPermissions);
}

View File

@ -6,14 +6,20 @@
#include <common.h>
#include <common/uuid.h>
#include <kernel/types/KEvent.h>
#include <services/serviceman.h>
#include "common.h"
#include "IStaticService.h"
namespace skyline::service::timesrv {
namespace core {
struct TimeServiceObject;
}
class IStaticService;
/**
* @brief time:m (we don't expose this as IPC as games don't use it) is used to manage the state of timesrv
* @url https://switchbrew.org/w/index.php?title=PSC_services#time:m
*/
class TimeManagerServer {
private:
core::TimeServiceObject &core;
@ -21,29 +27,61 @@ namespace skyline::service::timesrv {
public:
TimeManagerServer(core::TimeServiceObject &core);
std::shared_ptr<IStaticService> GetUserStaticService(const DeviceState &state, ServiceManager &manager);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#GetStaticServiceAsUser
*/
std::shared_ptr<IStaticService> GetStaticServiceAsUser(const DeviceState &state, ServiceManager &manager);
std::shared_ptr<IStaticService> GetAdminStaticService(const DeviceState &state, ServiceManager &manager);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#GetStaticServiceAsAdmin
*/
std::shared_ptr<IStaticService> GetStaticServiceAsAdmin(const DeviceState &state, ServiceManager &manager);
std::shared_ptr<IStaticService> GetRepairStaticService(const DeviceState &state, ServiceManager &manager);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#GetStaticServiceAsRepair
*/
std::shared_ptr<IStaticService> GetStaticServiceAsRepair(const DeviceState &state, ServiceManager &manager);
std::shared_ptr<IStaticService> GetManagerStaticService(const DeviceState &state, ServiceManager &manager);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#GetStaticServiceAsServiceManager
*/
std::shared_ptr<IStaticService> GetStaticServiceAsServiceManager(const DeviceState &state, ServiceManager &manager);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#SetupStandardSteadyClockCore
*/
Result SetupStandardSteadyClock(UUID rtcId, TimeSpanType rtcOffset, TimeSpanType internalOffset, TimeSpanType testOffset, bool rtcResetDetected);
Result SetupTimeZoneManager(std::string_view locationName, const SteadyClockTimePoint &updateTime, size_t locationCount, std::array<u8, 0x10> binaryVersion, span<u8> binary);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#SetupStandardLocalSystemClockCore
*/
Result SetupStandardLocalSystemClock(const SystemClockContext &context, PosixTime posixTime);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#SetupStandardNetworkSystemClockCore
*/
Result SetupStandardNetworkSystemClock(const SystemClockContext &context, TimeSpanType sufficientAccuracy);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#SetupStandardUserSystemClockCore
*/
Result SetupStandardUserSystemClock(bool enableAutomaticCorrection, const SteadyClockTimePoint &automaticCorrectionUpdateTime);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#SetupTimeZoneServiceCore
*/
Result SetupTimeZoneManager(std::string_view locationName, const SteadyClockTimePoint &updateTime, size_t locationCount, std::array<u8, 0x10> binaryVersion, span<u8> binary);
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#SetupEphemeralNetworkSystemClockCore
*/
Result SetupEphemeralSystemClock();
std::shared_ptr<kernel::type::KEvent> GetStandardUserSystemClockAutomaticCorrectionEvent();
/**
* @url https://switchbrew.org/w/index.php?title=PSC_services#SetStandardSteadyClockBaseTime
*/
Result SetStandardSteadyClockRtcOffset(TimeSpanType rtcOffset);
};
}

View File

@ -53,11 +53,9 @@ namespace skyline::service::timesrv::core {
return out;
}
namespace constant {
constexpr size_t TimeSharedMemorySize{0x1000}; //!< The size of the time shared memory region
}
constexpr size_t TimeSharedMemorySize{0x1000}; //!< The size of the time shared memory region
TimeSharedMemory::TimeSharedMemory(const DeviceState &state) : kTimeSharedMemory(std::make_shared<kernel::type::KSharedMemory>(state, constant::TimeSharedMemorySize)), timeSharedMemory(reinterpret_cast<TimeSharedMemoryLayout *>(kTimeSharedMemory->kernel.ptr)) {}
TimeSharedMemory::TimeSharedMemory(const DeviceState &state) : kTimeSharedMemory(std::make_shared<kernel::type::KSharedMemory>(state, TimeSharedMemorySize)), timeSharedMemory(reinterpret_cast<TimeSharedMemoryLayout *>(kTimeSharedMemory->kernel.ptr)) {}
void TimeSharedMemory::SetupStandardSteadyClock(UUID rtcId, TimeSpanType baseTimePoint) {
SteadyClockTimePoint context{

View File

@ -18,7 +18,7 @@ namespace skyline::service::timesrv::core {
ResultValue<LocationName> TimeZoneManager::GetLocationName() {
std::lock_guard lock(mutex);
if (!initialized)
if (!IsInitialized())
return result::ClockUninitialized;
return locationName;
@ -39,7 +39,7 @@ namespace skyline::service::timesrv::core {
ResultValue<SteadyClockTimePoint> TimeZoneManager::GetUpdateTime() {
std::lock_guard lock(mutex);
if (!initialized)
if (!IsInitialized())
return result::ClockUninitialized;
return updateTime;
@ -53,7 +53,7 @@ namespace skyline::service::timesrv::core {
ResultValue<int> TimeZoneManager::GetLocationCount() {
std::lock_guard lock(mutex);
if (!initialized)
if (!IsInitialized())
return result::ClockUninitialized;
return locationCount;
@ -67,7 +67,7 @@ namespace skyline::service::timesrv::core {
ResultValue<std::array<u8, 0x10>> TimeZoneManager::GetBinaryVersion() {
std::lock_guard lock(mutex);
if (!initialized)
if (!IsInitialized())
return result::ClockUninitialized;
return binaryVersion;
@ -124,7 +124,7 @@ namespace skyline::service::timesrv::core {
.tm_sec = calendarTime.second,
};
// Nintendo optionally two times here, presumably to deal with DST correction but we are probably fine without it
// Nintendo optionally returns two times here, presumably to deal with DST correction but we are probably fine without it
return static_cast<PosixTime>(tz_mktime_z(pRule, &posixCalendarTime));
}
}

View File

@ -26,6 +26,10 @@ namespace skyline::service::timesrv::core {
}
public:
bool IsInitialized() {
return initialized;
}
/**
* @brief Initialises the manager, setting the initial timezone so it is ready for use by applications
*/
@ -53,12 +57,12 @@ namespace skyline::service::timesrv::core {
/**
* @brief Parses a raw TZIF2 file into a timezone rule that can be passed to other functions
*/
Result ParseTimeZoneBinary(span<u8> binary, span<u8> ruleOut);
static Result ParseTimeZoneBinary(span<u8> binary, span<u8> ruleOut);
/**
* @brief Converts a POSIX time to a calendar time using the given rule
*/
ResultValue<FullCalendarTime> ToCalendarTime(tz_timezone_t pRule, PosixTime posixTime);
static ResultValue<FullCalendarTime> ToCalendarTime(tz_timezone_t pRule, PosixTime posixTime);
/**
* @brief Converts a POSIX to a calendar time using the current location's rule
@ -70,7 +74,7 @@ namespace skyline::service::timesrv::core {
/**
* @brief Converts a calendar time to a POSIX time using the given rule
*/
ResultValue<PosixTime> ToPosixTime(tz_timezone_t pRule, CalendarTime calendarTime);
static ResultValue<PosixTime> ToPosixTime(tz_timezone_t pRule, CalendarTime calendarTime);
/**
* @brief Converts a calendar time to a POSIX time using the current location's rule
@ -79,4 +83,4 @@ namespace skyline::service::timesrv::core {
return ToPosixTime(rule, calendarTime);
}
};
}
}