blob: 5a3d92830a8e4c592850ce80104756abe992136b [file] [log] [blame]
Lei YU415b9642017-02-09 11:37:26 +08001#include "manager.hpp"
2
3#include <phosphor-logging/log.hpp>
4
5namespace rules = sdbusplus::bus::match::rules;
6
7namespace // anonymous
8{
9constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host";
10constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
11constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
12constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
13constexpr auto METHOD_GET = "Get";
14
15constexpr auto PROPERTY_TIME_MODE = "time_mode";
16constexpr auto PROPERTY_TIME_OWNER = "time_owner";
17
18// TODO: Use new settings in xyz.openbmc_project
19const 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
Lei YUc6fe8692017-02-23 15:12:07 +080025const auto MATCH_PGOOD_CHANGE =
26 rules::type::signal() +
27 rules::member("PropertiesChanged") +
28 rules::path("/org/openbmc/control/power0") +
29 rules::interface("org.freedesktop.DBus.Properties");
30
31// TODO: consider put the get properties related functions into a common place
32constexpr auto POWER_SERVICE = "org.openbmc.control.Power";
33constexpr auto POWER_PATH = "/org/openbmc/control/power0";
34constexpr auto POWER_INTERFACE = POWER_SERVICE;
35constexpr auto PGOOD_STR = "pgood";
Lei YU415b9642017-02-09 11:37:26 +080036}
37
38namespace phosphor
39{
40namespace time
41{
42
43using namespace phosphor::logging;
44
45const std::set<std::string>
46Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER};
47
48const std::map<std::string, Owner> Manager::ownerMap =
49{
50 { "BMC", Owner::BMC },
51 { "HOST", Owner::HOST },
52 { "SPLIT", Owner::SPLIT },
53 { "BOTH", Owner::BOTH },
54};
55
56Manager::Manager(sdbusplus::bus::bus& bus)
57 : bus(bus),
Lei YUc6fe8692017-02-23 15:12:07 +080058 propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this),
59 pgoodChangeMatch(bus, MATCH_PGOOD_CHANGE, onPgoodChanged, this)
Lei YU415b9642017-02-09 11:37:26 +080060{
61 setCurrentTimeMode(getSettings(PROPERTY_TIME_MODE));
62 setCurrentTimeOwner(getSettings(PROPERTY_TIME_OWNER));
Lei YUc6fe8692017-02-23 15:12:07 +080063 checkHostOn();
Lei YU415b9642017-02-09 11:37:26 +080064}
65
66void Manager::addListener(PropertyChangeListner* listener)
67{
68 // Notify listener about the initial value
69 listener->onModeChanged(timeMode);
70 listener->onOwnerChanged(timeOwner);
71
72 listeners.insert(listener);
73}
74
Lei YUc6fe8692017-02-23 15:12:07 +080075void Manager::checkHostOn()
76{
77 sdbusplus::message::variant<int> pgood = 0;
78 auto method = bus.new_method_call(POWER_SERVICE,
79 POWER_PATH,
80 PROPERTY_INTERFACE,
81 METHOD_GET);
82 method.append(PROPERTY_INTERFACE, PGOOD_STR);
83 auto reply = bus.call(method);
84 if (reply)
85 {
86 reply.read(pgood);
87 }
88
89 hostOn = static_cast<bool>(pgood.get<int>());
90}
91
Lei YU415b9642017-02-09 11:37:26 +080092void Manager::onPropertyChanged(const std::string& key,
93 const std::string& value)
94{
95 // TODO: Check pgood
96 // If it's off, notify listners;
Lei YUc6fe8692017-02-23 15:12:07 +080097 // If it's on, hold the values and store in persistent storage
98 // as requested time mode/owner.
Lei YU415b9642017-02-09 11:37:26 +080099 // And when pgood turns back to off, notify the listners.
100
101 // TODO: Check dhcp_ntp
102
103 if (key == PROPERTY_TIME_MODE)
104 {
105 setCurrentTimeMode(value);
106 for (const auto& listener : listeners)
107 {
108 listener->onModeChanged(timeMode);
109 }
110 }
111 else if (key == PROPERTY_TIME_OWNER)
112 {
113 setCurrentTimeOwner(value);
114 for (const auto& listener : listeners)
115 {
116 listener->onOwnerChanged(timeOwner);
117 }
118 }
119}
120
121int Manager::onPropertyChanged(sd_bus_message* msg,
122 void* userData,
123 sd_bus_error* retError)
124{
125 using properties = std::map < std::string,
Lei YUc6fe8692017-02-23 15:12:07 +0800126 sdbusplus::message::variant<std::string> >;
Lei YU415b9642017-02-09 11:37:26 +0800127 auto m = sdbusplus::message::message(msg);
128 // message type: sa{sv}as
129 std::string ignore;
130 properties props;
131 m.read(ignore, props);
132 for (const auto& item : props)
133 {
134 if (managedProperties.find(item.first) != managedProperties.end())
135 {
136 static_cast<Manager*>(userData)
137 ->onPropertyChanged(item.first, item.second.get<std::string>());
138 }
139 }
140 return 0;
141}
142
Lei YUc6fe8692017-02-23 15:12:07 +0800143void Manager::onPgoodChanged(bool pgood)
144{
145 hostOn = pgood;
146 // TODO: if host is off, check requested time_mode/owner:
147 // and notify the listeners if any.
148}
149
150int Manager::onPgoodChanged(sd_bus_message* msg,
151 void* userData,
152 sd_bus_error* retError)
153{
154 using properties = std::map < std::string,
155 sdbusplus::message::variant<int> >;
156 auto m = sdbusplus::message::message(msg);
157 // message type: sa{sv}as
158 std::string ignore;
159 properties props;
160 m.read(ignore, props);
161 for (const auto& item : props)
162 {
163 if (item.first == PGOOD_STR)
164 {
165 static_cast<Manager*>(userData)
166 ->onPgoodChanged(static_cast<bool>(item.second.get<int>()));
167 }
168 }
169 return 0;
170}
Lei YU415b9642017-02-09 11:37:26 +0800171
172void Manager::setCurrentTimeMode(const std::string& mode)
173{
174 log<level::INFO>("Time mode is changed",
175 entry("MODE=%s", mode.c_str()));
176 timeMode = convertToMode(mode);
177}
178
179void Manager::setCurrentTimeOwner(const std::string& owner)
180{
181 log<level::INFO>("Time owner is changed",
182 entry("OWNER=%s", owner.c_str()));
183 timeOwner = convertToOwner(owner);
184}
185
186std::string Manager::getSettings(const char* value) const
187{
188 sdbusplus::message::variant<std::string> mode;
189 auto method = bus.new_method_call(SETTINGS_SERVICE,
190 SETTINGS_PATH,
191 PROPERTY_INTERFACE,
192 METHOD_GET);
193 method.append(SETTINGS_INTERFACE, value);
194 auto reply = bus.call(method);
195 if (reply)
196 {
197 reply.read(mode);
198 }
199 else
200 {
201 log<level::ERR>("Failed to get settings");
202 }
203
204 return mode.get<std::string>();
205}
206
207Mode Manager::convertToMode(const std::string& mode)
208{
209 if (mode == "NTP")
210 {
211 return Mode::NTP;
212 }
213 else if (mode == "MANUAL")
214 {
215 return Mode::MANUAL;
216 }
217 else
218 {
219 log<level::ERR>("Unrecognized mode",
220 entry("%s", mode.c_str()));
221 return Mode::NTP;
222 }
223}
224
225Owner Manager::convertToOwner(const std::string& owner)
226{
227 auto it = ownerMap.find(owner);
228 if (it == ownerMap.end())
229 {
230 log<level::ERR>("Unrecognized owner",
231 entry("%s", owner.c_str()));
232 return Owner::BMC;
233 }
234 return it->second;
235}
236
237}
238}