blob: ed537db322d39ae152fff135145db7e47f9d9659 [file] [log] [blame]
Jim Wright19920832021-08-25 11:13:56 -05001/**
2 * Copyright © 2021 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "power_interface.hpp"
18
19#include "types.hpp"
20
21#include <fmt/format.h>
22
23#include <phosphor-logging/log.hpp>
24#include <sdbusplus/exception.hpp>
25#include <sdbusplus/sdbus.hpp>
26#include <sdbusplus/server.hpp>
27
28#include <string>
29#include <tuple>
30
31using namespace phosphor::logging;
32
33namespace phosphor::power::sequencer
34{
35
36PowerInterface::PowerInterface(sdbusplus::bus::bus& bus, const char* path) :
37 _serverInterface(bus, path, POWER_IFACE, _vtable, this)
38{
39}
40
41int PowerInterface::callbackGetPgood(sd_bus* /*bus*/, const char* /*path*/,
42 const char* /*interface*/,
43 const char* /*property*/,
44 sd_bus_message* msg, void* context,
45 sd_bus_error* error)
46{
47 if (msg != nullptr && context != nullptr)
48 {
49 try
50 {
51 auto pwrObj = static_cast<PowerInterface*>(context);
52 int pgood = pwrObj->getPgood();
53 log<level::INFO>(
54 fmt::format("callbackGetPgood: {}", pgood).c_str());
55
56 sdbusplus::message::message(msg).append(pgood);
57 }
58 catch (sdbusplus::exception_t& e)
59 {
60 return sd_bus_error_set(error, e.name(), e.description());
61 }
62 }
63 else
64 {
65 // The message or context were null
66 log<level::ERR>("Unable to service get pgood property callback");
67 return -1;
68 }
69
70 return 1;
71}
72
73int PowerInterface::callbackGetPgoodTimeout(sd_bus* /*bus*/,
74 const char* /*path*/,
75 const char* /*interface*/,
76 const char* /*property*/,
77 sd_bus_message* msg, void* context,
78 sd_bus_error* error)
79{
80 if (msg != nullptr && context != nullptr)
81 {
82 try
83 {
84 auto pwrObj = static_cast<PowerInterface*>(context);
85 int timeout = pwrObj->getPgoodTimeout();
86 log<level::INFO>(
87 fmt::format("callbackGetPgoodTimeout: {}", timeout).c_str());
88
89 sdbusplus::message::message(msg).append(timeout);
90 }
91 catch (sdbusplus::exception_t& e)
92 {
93 return sd_bus_error_set(error, e.name(), e.description());
94 }
95 }
96 else
97 {
98 // The message or context were null
99 log<level::ERR>(
100 "Unable to service get pgood timeout property callback");
101 return -1;
102 }
103
104 return 1;
105}
106
107int PowerInterface::callbackGetPowerState(sd_bus_message* msg, void* context,
108 sd_bus_error* error)
109{
110 if (msg != nullptr && context != nullptr)
111 {
112 try
113 {
114 auto pwrObj = static_cast<PowerInterface*>(context);
115 // Return the current power state of the GPIO, rather than the last
116 // requested power state change
117 int pgood = pwrObj->getPgood();
118 log<level::INFO>(
119 fmt::format("callbackGetPowerState: {}", pgood).c_str());
120
121 auto reply = sdbusplus::message::message(msg).new_method_return();
122 reply.append(pgood);
123 reply.method_return();
124 }
125 catch (sdbusplus::exception_t& e)
126 {
127 return sd_bus_error_set(error, e.name(), e.description());
128 }
129 }
130 else
131 {
132 // The message or context were null
133 log<level::ERR>("Unable to service getPowerState method callback");
134 return -1;
135 }
136
137 return 1;
138}
139
140int PowerInterface::callbackSetPgoodTimeout(sd_bus* /*bus*/,
141 const char* /*path*/,
142 const char* /*interface*/,
143 const char* /*property*/,
144 sd_bus_message* msg, void* context,
145 sd_bus_error* error)
146{
147 if (msg != nullptr && context != nullptr)
148 {
149 try
150 {
151 auto m = sdbusplus::message::message(msg);
152
153 int timeout{};
154 m.read(timeout);
155
156 auto pwrObj = static_cast<PowerInterface*>(context);
157 log<level::INFO>(
158 fmt::format("callbackSetPgoodTimeout: {}", timeout).c_str());
159 pwrObj->setPgoodTimeout(timeout);
160 }
161 catch (sdbusplus::exception_t& e)
162 {
163 return sd_bus_error_set(error, e.name(), e.description());
164 }
165 }
166 else
167 {
168 // The message or context were null
169 log<level::ERR>(
170 "Unable to service set pgood timeout property callback");
171 return -1;
172 }
173
174 return 1;
175}
176
177int PowerInterface::callbackGetState(sd_bus* /*bus*/, const char* /*path*/,
178 const char* /*interface*/,
179 const char* /*property*/,
180 sd_bus_message* msg, void* context,
181 sd_bus_error* error)
182{
183 if (msg != nullptr && context != nullptr)
184 {
185 try
186 {
187 auto pwrObj = static_cast<PowerInterface*>(context);
188 int state = pwrObj->getState();
189 log<level::INFO>(
190 fmt::format("callbackGetState: {}", state).c_str());
191
192 sdbusplus::message::message(msg).append(state);
193 }
194 catch (sdbusplus::exception_t& e)
195 {
196 return sd_bus_error_set(error, e.name(), e.description());
197 }
198 }
199 else
200 {
201 // The message or context were null
202 log<level::ERR>("Unable to service get state property callback");
203 return -1;
204 }
205
206 return 1;
207}
208
209int PowerInterface::callbackSetPowerState(sd_bus_message* msg, void* context,
210 sd_bus_error* error)
211{
212 if (msg != nullptr && context != nullptr)
213 {
214 try
215 {
216 auto m = sdbusplus::message::message(msg);
217
218 int state{};
219 m.read(state);
220
221 if (state != 1 && state != 0)
222 {
223 return sd_bus_error_set(error,
224 "org.openbmc.ControlPower.Error.Failed",
225 "Invalid power state");
226 }
227
228 auto pwrObj = static_cast<PowerInterface*>(context);
229 log<level::INFO>(
230 fmt::format("callbackSetPowerState: {}", state).c_str());
231 pwrObj->setState(state);
232
233 m.new_method_return().method_return();
234 }
235 catch (sdbusplus::exception_t& e)
236 {
237 return sd_bus_error_set(error, e.name(), e.description());
238 }
239 }
240 else
241 {
242 // The message or context were null
243 log<level::ERR>("Unable to service setPowerState method callback");
244 return -1;
245 }
246
247 return 1;
248}
249
250void PowerInterface::emitPowerGoodSignal()
251{
252 log<level::INFO>("emitPowerGoodSignal");
253 _serverInterface.new_signal("PowerGood").signal_send();
254}
255
256void PowerInterface::emitPowerLostSignal()
257{
258 log<level::INFO>("emitPowerLostSignal");
259 _serverInterface.new_signal("PowerLost").signal_send();
260}
261
262void PowerInterface::emitPropertyChangedSignal(const char* property)
263{
264 log<level::INFO>(
265 fmt::format("emitPropertyChangedSignal: {}", property).c_str());
266 _serverInterface.property_changed(property);
267}
268
269const sdbusplus::vtable::vtable_t PowerInterface::_vtable[] = {
270 sdbusplus::vtable::start(),
271 // Method setPowerState takes an int parameter and returns void
272 sdbusplus::vtable::method("setPowerState", "i", "", callbackSetPowerState),
273 // Method getPowerState takes no parameters and returns int
274 sdbusplus::vtable::method("getPowerState", "", "i", callbackGetPowerState),
275 // Signal PowerGood
276 sdbusplus::vtable::signal("PowerGood", ""),
277 // Signal PowerLost
278 sdbusplus::vtable::signal("PowerLost", ""),
279 // Property pgood is type int, read only, and uses the emits_change flag
280 sdbusplus::vtable::property("pgood", "i", callbackGetPgood,
281 sdbusplus::vtable::property_::emits_change),
282 // Property state is type int, read only, and uses the emits_change flag
283 sdbusplus::vtable::property("state", "i", callbackGetState,
284 sdbusplus::vtable::property_::emits_change),
285 // Property pgood_timeout is type int, read write, and uses the emits_change
286 // flag
287 sdbusplus::vtable::property("pgood_timeout", "i", callbackGetPgoodTimeout,
288 callbackSetPgoodTimeout,
289 sdbusplus::vtable::property_::emits_change),
290 sdbusplus::vtable::end()};
291
292} // namespace phosphor::power::sequencer