blob: c4732f459e35b6857c5263c1a233b19de6fbf8e9 [file] [log] [blame]
#include "manager.hpp"
#include <phosphor-logging/log.hpp>
namespace rules = sdbusplus::bus::match::rules;
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";
constexpr auto PROPERTY_TIME_MODE = "time_mode";
constexpr auto PROPERTY_TIME_OWNER = "time_owner";
// TODO: Use new settings in xyz.openbmc_project
const auto MATCH_PROPERTY_CHANGE =
rules::type::signal() +
rules::member("PropertiesChanged") +
rules::path("/org/openbmc/settings/host0") +
rules::interface("org.freedesktop.DBus.Properties");
}
namespace phosphor
{
namespace time
{
using namespace phosphor::logging;
const std::set<std::string>
Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER};
const std::map<std::string, Owner> Manager::ownerMap =
{
{ "BMC", Owner::BMC },
{ "HOST", Owner::HOST },
{ "SPLIT", Owner::SPLIT },
{ "BOTH", Owner::BOTH },
};
Manager::Manager(sdbusplus::bus::bus& bus)
: bus(bus),
propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this)
{
setCurrentTimeMode(getSettings(PROPERTY_TIME_MODE));
setCurrentTimeOwner(getSettings(PROPERTY_TIME_OWNER));
}
void Manager::addListener(PropertyChangeListner* listener)
{
// Notify listener about the initial value
listener->onModeChanged(timeMode);
listener->onOwnerChanged(timeOwner);
listeners.insert(listener);
}
void Manager::onPropertyChanged(const std::string& key,
const std::string& value)
{
// TODO: Check pgood
// If it's off, notify listners;
// If it's on, hold the values and store in persistent storage.
// And when pgood turns back to off, notify the listners.
// TODO: Check dhcp_ntp
if (key == PROPERTY_TIME_MODE)
{
setCurrentTimeMode(value);
for (const auto& listener : listeners)
{
listener->onModeChanged(timeMode);
}
}
else if (key == PROPERTY_TIME_OWNER)
{
setCurrentTimeOwner(value);
for (const auto& listener : listeners)
{
listener->onOwnerChanged(timeOwner);
}
}
}
int Manager::onPropertyChanged(sd_bus_message* msg,
void* userData,
sd_bus_error* retError)
{
using properties = std::map < std::string,
sdbusplus::message::variant<int, std::string >>;
auto m = sdbusplus::message::message(msg);
// message type: sa{sv}as
std::string ignore;
properties props;
m.read(ignore, props);
for (const auto& item : props)
{
if (managedProperties.find(item.first) != managedProperties.end())
{
static_cast<Manager*>(userData)
->onPropertyChanged(item.first, item.second.get<std::string>());
}
}
return 0;
}
void Manager::setCurrentTimeMode(const std::string& mode)
{
log<level::INFO>("Time mode is changed",
entry("MODE=%s", mode.c_str()));
timeMode = convertToMode(mode);
}
void Manager::setCurrentTimeOwner(const std::string& owner)
{
log<level::INFO>("Time owner is changed",
entry("OWNER=%s", owner.c_str()));
timeOwner = convertToOwner(owner);
}
std::string Manager::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);
}
else
{
log<level::ERR>("Failed to get settings");
}
return mode.get<std::string>();
}
Mode Manager::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;
}
}
Owner Manager::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;
}
}
}