xref: /openbmc/phosphor-power/phosphor-power-sequencer/src/power_interface.cpp (revision 31ae6ee8c0e17f121e5cb3e581361296d69fdf2d)
1 /**
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 <phosphor-logging/lg2.hpp>
22 #include <sdbusplus/exception.hpp>
23 #include <sdbusplus/sdbus.hpp>
24 #include <sdbusplus/server.hpp>
25 
26 #include <string>
27 #include <tuple>
28 
29 namespace phosphor::power::sequencer
30 {
31 
PowerInterface(sdbusplus::bus_t & bus,const char * path)32 PowerInterface::PowerInterface(sdbusplus::bus_t& bus, const char* path) :
33     serverInterface(bus, path, POWER_IFACE, vtable, this)
34 {}
35 
callbackGetPgood(sd_bus *,const char *,const char *,const char *,sd_bus_message * msg,void * context,sd_bus_error * error)36 int PowerInterface::callbackGetPgood(
37     sd_bus* /*bus*/, const char* /*path*/, const char* /*interface*/,
38     const char* /*property*/, sd_bus_message* msg, void* context,
39     sd_bus_error* error)
40 {
41     if (msg != nullptr && context != nullptr)
42     {
43         try
44         {
45             auto pwrObj = static_cast<PowerInterface*>(context);
46             int pgood = pwrObj->getPgood();
47             lg2::debug("callbackGetPgood: {PGOOD}", "PGOOD", pgood);
48 
49             sdbusplus::message_t(msg).append(pgood);
50         }
51         catch (const sdbusplus::exception_t& e)
52         {
53             return sd_bus_error_set(error, e.name(), e.description());
54         }
55     }
56     else
57     {
58         // The message or context were null
59         lg2::error("Unable to service get pgood property callback");
60         return -1;
61     }
62 
63     return 1;
64 }
65 
callbackGetPgoodTimeout(sd_bus *,const char *,const char *,const char *,sd_bus_message * msg,void * context,sd_bus_error * error)66 int PowerInterface::callbackGetPgoodTimeout(
67     sd_bus* /*bus*/, const char* /*path*/, const char* /*interface*/,
68     const char* /*property*/, sd_bus_message* msg, void* context,
69     sd_bus_error* error)
70 {
71     if (msg != nullptr && context != nullptr)
72     {
73         try
74         {
75             auto pwrObj = static_cast<PowerInterface*>(context);
76             int timeout = pwrObj->getPgoodTimeout();
77             lg2::debug("callbackGetPgoodTimeout: {TIMEOUT}", "TIMEOUT",
78                        timeout);
79 
80             sdbusplus::message_t(msg).append(timeout);
81         }
82         catch (const sdbusplus::exception_t& e)
83         {
84             return sd_bus_error_set(error, e.name(), e.description());
85         }
86     }
87     else
88     {
89         // The message or context were null
90         lg2::error("Unable to service get pgood timeout property callback");
91         return -1;
92     }
93 
94     return 1;
95 }
96 
callbackGetPowerState(sd_bus_message * msg,void * context,sd_bus_error * error)97 int PowerInterface::callbackGetPowerState(sd_bus_message* msg, void* context,
98                                           sd_bus_error* error)
99 {
100     if (msg != nullptr && context != nullptr)
101     {
102         try
103         {
104             auto pwrObj = static_cast<PowerInterface*>(context);
105             // Return the current power state of the GPIO, rather than the last
106             // requested power state change
107             int pgood = pwrObj->getPgood();
108             lg2::debug("callbackGetPowerState: {PGOOD}", "PGOOD", pgood);
109 
110             auto reply = sdbusplus::message_t(msg).new_method_return();
111             reply.append(pgood);
112             reply.method_return();
113         }
114         catch (const sdbusplus::exception_t& e)
115         {
116             return sd_bus_error_set(error, e.name(), e.description());
117         }
118     }
119     else
120     {
121         // The message or context were null
122         lg2::error("Unable to service getPowerState method callback");
123         return -1;
124     }
125 
126     return 1;
127 }
128 
callbackSetPgoodTimeout(sd_bus *,const char *,const char *,const char *,sd_bus_message * msg,void * context,sd_bus_error * error)129 int PowerInterface::callbackSetPgoodTimeout(
130     sd_bus* /*bus*/, const char* /*path*/, const char* /*interface*/,
131     const char* /*property*/, sd_bus_message* msg, void* context,
132     sd_bus_error* error)
133 {
134     if (msg != nullptr && context != nullptr)
135     {
136         try
137         {
138             auto m = sdbusplus::message_t(msg);
139 
140             int timeout{};
141             m.read(timeout);
142             lg2::info("callbackSetPgoodTimeout: {TIMEOUT}", "TIMEOUT", timeout);
143 
144             auto pwrObj = static_cast<PowerInterface*>(context);
145             pwrObj->setPgoodTimeout(timeout);
146         }
147         catch (const sdbusplus::exception_t& e)
148         {
149             return sd_bus_error_set(error, e.name(), e.description());
150         }
151     }
152     else
153     {
154         // The message or context were null
155         lg2::error("Unable to service set pgood timeout property callback");
156         return -1;
157     }
158 
159     return 1;
160 }
161 
callbackGetState(sd_bus *,const char *,const char *,const char *,sd_bus_message * msg,void * context,sd_bus_error * error)162 int PowerInterface::callbackGetState(
163     sd_bus* /*bus*/, const char* /*path*/, const char* /*interface*/,
164     const char* /*property*/, sd_bus_message* msg, void* context,
165     sd_bus_error* error)
166 {
167     if (msg != nullptr && context != nullptr)
168     {
169         try
170         {
171             auto pwrObj = static_cast<PowerInterface*>(context);
172             int state = pwrObj->getState();
173             lg2::debug("callbackGetState: {STATE}", "STATE", state);
174 
175             sdbusplus::message_t(msg).append(state);
176         }
177         catch (const sdbusplus::exception_t& e)
178         {
179             return sd_bus_error_set(error, e.name(), e.description());
180         }
181     }
182     else
183     {
184         // The message or context were null
185         lg2::error("Unable to service get state property callback");
186         return -1;
187     }
188 
189     return 1;
190 }
191 
callbackSetPowerState(sd_bus_message * msg,void * context,sd_bus_error * error)192 int PowerInterface::callbackSetPowerState(sd_bus_message* msg, void* context,
193                                           sd_bus_error* error)
194 {
195     if (msg != nullptr && context != nullptr)
196     {
197         try
198         {
199             auto m = sdbusplus::message_t(msg);
200 
201             int state{};
202             m.read(state);
203 
204             if (state != 1 && state != 0)
205             {
206                 return sd_bus_error_set(error,
207                                         "org.openbmc.ControlPower.Error.Failed",
208                                         "Invalid power state");
209             }
210             lg2::info("callbackSetPowerState: {STATE}", "STATE", state);
211 
212             auto pwrObj = static_cast<PowerInterface*>(context);
213             pwrObj->setState(state);
214 
215             m.new_method_return().method_return();
216         }
217         catch (const sdbusplus::exception_t& e)
218         {
219             return sd_bus_error_set(error, e.name(), e.description());
220         }
221     }
222     else
223     {
224         // The message or context were null
225         lg2::error("Unable to service setPowerState method callback");
226         return -1;
227     }
228 
229     return 1;
230 }
231 
callbackSetPowerSupplyError(sd_bus_message * msg,void * context,sd_bus_error * error)232 int PowerInterface::callbackSetPowerSupplyError(
233     sd_bus_message* msg, void* context, sd_bus_error* error)
234 {
235     if (msg != nullptr && context != nullptr)
236     {
237         try
238         {
239             auto m = sdbusplus::message_t(msg);
240 
241             std::string psError{};
242             m.read(psError);
243             lg2::info("callbackSetPowerSupplyError: {PSERROR}", "PSERROR",
244                       psError);
245 
246             auto pwrObj = static_cast<PowerInterface*>(context);
247             pwrObj->setPowerSupplyError(psError);
248 
249             m.new_method_return().method_return();
250         }
251         catch (const sdbusplus::exception_t& e)
252         {
253             return sd_bus_error_set(error, e.name(), e.description());
254         }
255     }
256     else
257     {
258         // The message or context were null
259         lg2::error("Unable to service setPowerSupplyError method callback");
260         return -1;
261     }
262 
263     return 1;
264 }
265 
emitPowerGoodSignal()266 void PowerInterface::emitPowerGoodSignal()
267 {
268     lg2::info("emitPowerGoodSignal");
269     serverInterface.new_signal("PowerGood").signal_send();
270 }
271 
emitPowerLostSignal()272 void PowerInterface::emitPowerLostSignal()
273 {
274     lg2::info("emitPowerLostSignal");
275     serverInterface.new_signal("PowerLost").signal_send();
276 }
277 
emitPropertyChangedSignal(const char * property)278 void PowerInterface::emitPropertyChangedSignal(const char* property)
279 {
280     lg2::info("emitPropertyChangedSignal: {PROPERTY}", "PROPERTY", property);
281     serverInterface.property_changed(property);
282 }
283 
284 const sdbusplus::vtable::vtable_t PowerInterface::vtable[] = {
285     sdbusplus::vtable::start(),
286     // Method setPowerState takes an int parameter and returns void
287     sdbusplus::vtable::method("setPowerState", "i", "", callbackSetPowerState),
288     // Method getPowerState takes no parameters and returns int
289     sdbusplus::vtable::method("getPowerState", "", "i", callbackGetPowerState),
290     // Signal PowerGood
291     sdbusplus::vtable::signal("PowerGood", ""),
292     // Signal PowerLost
293     sdbusplus::vtable::signal("PowerLost", ""),
294     // Property pgood is type int, read only, and uses the emits_change flag
295     sdbusplus::vtable::property("pgood", "i", callbackGetPgood,
296                                 sdbusplus::vtable::property_::emits_change),
297     // Property state is type int, read only, and uses the emits_change flag
298     sdbusplus::vtable::property("state", "i", callbackGetState,
299                                 sdbusplus::vtable::property_::emits_change),
300     // Property pgood_timeout is type int, read write, and uses the emits_change
301     // flag
302     sdbusplus::vtable::property("pgood_timeout", "i", callbackGetPgoodTimeout,
303                                 callbackSetPgoodTimeout,
304                                 sdbusplus::vtable::property_::emits_change),
305     // Method setPowerSupplyError takes a string parameter and returns void
306     sdbusplus::vtable::method("setPowerSupplyError", "s", "",
307                               callbackSetPowerSupplyError),
308     sdbusplus::vtable::end()};
309 
310 } // namespace phosphor::power::sequencer
311