94b63924ed
... and set initial time by using RTC session. Up to now Noux used a monotic clock whose initial start value always was '0' (which correlates to the start of the UNIX epoch) to provide a notion of time. In addition it is now possible to use the RTC session to set the initial value for use cases where having a proper real-world time matters. To use the RTC session the 'rtc' attribute of the '<config>' node must be set to 'yes'. Thereby the session becomes a mandatory dependency as Noux will not start without it. Issue #1784
105 lines
2.2 KiB
C++
105 lines
2.2 KiB
C++
/*
|
|
* \brief Time information
|
|
* \author Josef Soentgen
|
|
* \date 2019-04-09
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2019 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _NOUX__TIME_INFO_H_
|
|
#define _NOUX__TIME_INFO_H_
|
|
|
|
/* Genode includes */
|
|
#include <util/string.h>
|
|
#include <util/xml_node.h>
|
|
#include <rtc_session/connection.h>
|
|
|
|
/* Noux includes */
|
|
#include <noux_session/sysio.h>
|
|
|
|
namespace Noux {
|
|
class Time_info;
|
|
using namespace Genode;
|
|
}
|
|
|
|
|
|
class Noux::Time_info : Noncopyable
|
|
{
|
|
private:
|
|
|
|
Constructible<Rtc::Connection> _rtc { };
|
|
|
|
Genode::int64_t _initial_time { 0 };
|
|
|
|
static bool _leap(unsigned year)
|
|
{
|
|
return ((year % 4) == 0
|
|
&& ((year % 100) != 0 || (year % 400) == 0));
|
|
}
|
|
|
|
/**
|
|
* Convert RTC timestamp to UNIX epoch (UTC)
|
|
*/
|
|
static Genode::int64_t _convert(Rtc::Timestamp const &ts)
|
|
{
|
|
if (ts.year < 1970) { return 0; }
|
|
|
|
/*
|
|
* Seconds per year lookup table
|
|
*/
|
|
static constexpr unsigned _secs_per_year[2] = {
|
|
365 * 86400, 366 * 86400,
|
|
};
|
|
|
|
/*
|
|
* Seconds per month lookup table
|
|
*/
|
|
static constexpr unsigned _sec_per_month[13] = {
|
|
0 * 86400,
|
|
31 * 86400, 28 * 86400, 31 * 86400, 30 * 86400,
|
|
31 * 86400, 30 * 86400, 31 * 86400, 31 * 86400,
|
|
30 * 86400, 31 * 86400, 30 * 86400, 31 * 86400
|
|
};
|
|
|
|
Genode::int64_t time = 0;
|
|
|
|
for (unsigned i = 1970; i < ts.year; i++) {
|
|
/* abuse bool conversion for seconds look up */
|
|
time += _secs_per_year[(int)_leap(i)];
|
|
}
|
|
|
|
for (unsigned i = 1; i < ts.month; i++) {
|
|
time += _sec_per_month[i];
|
|
}
|
|
time += _leap(ts.year) * 86400LL;
|
|
|
|
time += 86400LL * (ts.day-1);
|
|
time += 3600LL * ts.hour;
|
|
time += 60LL * ts.minute;
|
|
time += ts.second;
|
|
|
|
return time;
|
|
}
|
|
|
|
public:
|
|
|
|
Time_info(Env &env, Xml_node config)
|
|
{
|
|
/* only try to establish the connection on demand */
|
|
bool const rtc = config.attribute_value("rtc", false);
|
|
if (!rtc) { return; }
|
|
|
|
_rtc.construct(env);
|
|
_initial_time = _convert(_rtc->current_time());
|
|
}
|
|
|
|
Genode::int64_t initial_time() const { return _initial_time; }
|
|
};
|
|
|
|
#endif /* _NOUX__TIME_INFO_H_ */
|