1 #include "manager.hpp" 2 3 #include <phosphor-logging/log.hpp> 4 5 namespace rules = sdbusplus::bus::match::rules; 6 7 namespace // anonymous 8 { 9 constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host"; 10 constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0"; 11 constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host"; 12 constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"; 13 constexpr auto METHOD_GET = "Get"; 14 15 constexpr auto PROPERTY_TIME_MODE = "time_mode"; 16 constexpr auto PROPERTY_TIME_OWNER = "time_owner"; 17 18 // TODO: Use new settings in xyz.openbmc_project 19 const auto MATCH_PROPERTY_CHANGE = 20 rules::type::signal() + 21 rules::member("PropertiesChanged") + 22 rules::path("/org/openbmc/settings/host0") + 23 rules::interface("org.freedesktop.DBus.Properties"); 24 25 } 26 27 namespace phosphor 28 { 29 namespace time 30 { 31 32 using namespace phosphor::logging; 33 34 const std::set<std::string> 35 Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER}; 36 37 const std::map<std::string, Owner> Manager::ownerMap = 38 { 39 { "BMC", Owner::BMC }, 40 { "HOST", Owner::HOST }, 41 { "SPLIT", Owner::SPLIT }, 42 { "BOTH", Owner::BOTH }, 43 }; 44 45 Manager::Manager(sdbusplus::bus::bus& bus) 46 : bus(bus), 47 propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this) 48 { 49 setCurrentTimeMode(getSettings(PROPERTY_TIME_MODE)); 50 setCurrentTimeOwner(getSettings(PROPERTY_TIME_OWNER)); 51 } 52 53 void Manager::addListener(PropertyChangeListner* listener) 54 { 55 // Notify listener about the initial value 56 listener->onModeChanged(timeMode); 57 listener->onOwnerChanged(timeOwner); 58 59 listeners.insert(listener); 60 } 61 62 void Manager::onPropertyChanged(const std::string& key, 63 const std::string& value) 64 { 65 // TODO: Check pgood 66 // If it's off, notify listners; 67 // If it's on, hold the values and store in persistent storage. 68 // And when pgood turns back to off, notify the listners. 69 70 // TODO: Check dhcp_ntp 71 72 if (key == PROPERTY_TIME_MODE) 73 { 74 setCurrentTimeMode(value); 75 for (const auto& listener : listeners) 76 { 77 listener->onModeChanged(timeMode); 78 } 79 } 80 else if (key == PROPERTY_TIME_OWNER) 81 { 82 setCurrentTimeOwner(value); 83 for (const auto& listener : listeners) 84 { 85 listener->onOwnerChanged(timeOwner); 86 } 87 } 88 } 89 90 int Manager::onPropertyChanged(sd_bus_message* msg, 91 void* userData, 92 sd_bus_error* retError) 93 { 94 using properties = std::map < std::string, 95 sdbusplus::message::variant<int, std::string >>; 96 auto m = sdbusplus::message::message(msg); 97 // message type: sa{sv}as 98 std::string ignore; 99 properties props; 100 m.read(ignore, props); 101 for (const auto& item : props) 102 { 103 if (managedProperties.find(item.first) != managedProperties.end()) 104 { 105 static_cast<Manager*>(userData) 106 ->onPropertyChanged(item.first, item.second.get<std::string>()); 107 } 108 } 109 return 0; 110 } 111 112 113 void Manager::setCurrentTimeMode(const std::string& mode) 114 { 115 log<level::INFO>("Time mode is changed", 116 entry("MODE=%s", mode.c_str())); 117 timeMode = convertToMode(mode); 118 } 119 120 void Manager::setCurrentTimeOwner(const std::string& owner) 121 { 122 log<level::INFO>("Time owner is changed", 123 entry("OWNER=%s", owner.c_str())); 124 timeOwner = convertToOwner(owner); 125 } 126 127 std::string Manager::getSettings(const char* value) const 128 { 129 sdbusplus::message::variant<std::string> mode; 130 auto method = bus.new_method_call(SETTINGS_SERVICE, 131 SETTINGS_PATH, 132 PROPERTY_INTERFACE, 133 METHOD_GET); 134 method.append(SETTINGS_INTERFACE, value); 135 auto reply = bus.call(method); 136 if (reply) 137 { 138 reply.read(mode); 139 } 140 else 141 { 142 log<level::ERR>("Failed to get settings"); 143 } 144 145 return mode.get<std::string>(); 146 } 147 148 Mode Manager::convertToMode(const std::string& mode) 149 { 150 if (mode == "NTP") 151 { 152 return Mode::NTP; 153 } 154 else if (mode == "MANUAL") 155 { 156 return Mode::MANUAL; 157 } 158 else 159 { 160 log<level::ERR>("Unrecognized mode", 161 entry("%s", mode.c_str())); 162 return Mode::NTP; 163 } 164 } 165 166 Owner Manager::convertToOwner(const std::string& owner) 167 { 168 auto it = ownerMap.find(owner); 169 if (it == ownerMap.end()) 170 { 171 log<level::ERR>("Unrecognized owner", 172 entry("%s", owner.c_str())); 173 return Owner::BMC; 174 } 175 return it->second; 176 } 177 178 } 179 } 180