Intialize new phosphor-time-manager
phosphor-time-manager will be refactored to use sdbusplus interfaces.
This is a initial commit that EpochBase is implemented based on dbus
interface xyz/openbmc_project/Time/EpochTime.interface.yaml.
EpochBase is the base class that wraps EpochTime interface, and is
initialized with time mode and owner from settingsd.
An initial unit test case is added.
Change-Id: Ic944b70f63ec3c0329762cc8874f0f57b09ddce3
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/epoch_base.cpp b/epoch_base.cpp
new file mode 100644
index 0000000..06232bb
--- /dev/null
+++ b/epoch_base.cpp
@@ -0,0 +1,131 @@
+#include "epoch_base.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+#include <iomanip>
+#include <sstream>
+
+namespace // anonymous
+{
+constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host";
+constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
+constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
+constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
+constexpr auto METHOD_GET = "Get";
+}
+
+namespace phosphor
+{
+namespace time
+{
+
+using namespace phosphor::logging;
+
+const std::map<std::string, EpochBase::Owner>
+EpochBase::ownerMap = {
+ { "BMC", EpochBase::Owner::BMC },
+ { "HOST", EpochBase::Owner::HOST },
+ { "SPLIT", EpochBase::Owner::SPLIT },
+ { "BOTH", EpochBase::Owner::BOTH },
+};
+
+EpochBase::EpochBase(sdbusplus::bus::bus& bus,
+ const char* objPath)
+ : sdbusplus::server::object::object<EpochTime>(bus, objPath, true),
+ bus(bus)
+{
+ initialize();
+ // Deferred this until we could get our property correct
+ emit_object_added();
+}
+
+void EpochBase::setCurrentTimeMode(const std::string& mode)
+{
+ log<level::INFO>("Time mode is changed",
+ entry("MODE=%s", mode.c_str()));
+ timeMode = convertToMode(mode);
+}
+
+void EpochBase::setCurrentTimeOwner(const std::string& owner)
+{
+ log<level::INFO>("Time owner is changed",
+ entry("OWNER=%s", owner.c_str()));
+ timeOwner = convertToOwner(owner);
+}
+
+void EpochBase::initialize()
+{
+ setCurrentTimeMode(getSettings("time_mode"));
+ setCurrentTimeOwner(getSettings("time_owner"));
+ // TODO: subscribe settingsd's property changes callback
+}
+
+std::string EpochBase::getSettings(const char* value) const
+{
+ sdbusplus::message::variant<std::string> mode;
+ auto method = bus.new_method_call(SETTINGS_SERVICE,
+ SETTINGS_PATH,
+ PROPERTY_INTERFACE,
+ METHOD_GET);
+ method.append(SETTINGS_INTERFACE, value);
+ auto reply = bus.call(method);
+ if (reply)
+ {
+ reply.read(mode);
+ }
+
+ return mode.get<std::string>();
+}
+
+EpochBase::Mode EpochBase::convertToMode(const std::string& mode)
+{
+ if (mode == "NTP")
+ {
+ return Mode::NTP;
+ }
+ else if (mode == "MANUAL")
+ {
+ return Mode::MANUAL;
+ }
+ else
+ {
+ log<level::ERR>("Unrecognized mode",
+ entry("%s", mode.c_str()));
+ return Mode::NTP;
+ }
+}
+
+EpochBase::Owner EpochBase::convertToOwner(const std::string& owner)
+{
+ auto it = ownerMap.find(owner);
+ if (it == ownerMap.end())
+ {
+ log<level::ERR>("Unrecognized owner",
+ entry("%s", owner.c_str()));
+ return Owner::BMC;
+ }
+ return it->second;
+}
+
+using namespace std::chrono;
+void EpochBase::setTime(const microseconds& usec)
+{
+ auto method = bus.new_method_call("org.freedesktop.timedate1",
+ "/org/freedesktop/timedate1",
+ "org.freedesktop.timedate1",
+ "SetTime");
+ method.append(static_cast<int64_t>(usec.count()),
+ false, // relative
+ false); // user_interaction
+ bus.call_noreply(method);
+}
+
+microseconds EpochBase::getTime() const
+{
+ auto now = system_clock::now();
+ return duration_cast<microseconds>
+ (now.time_since_epoch());
+}
+
+} // namespace time
+} // namespace phosphor