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 32 PowerInterface::PowerInterface(sdbusplus::bus_t& bus, const char* path) : 33 serverInterface(bus, path, POWER_IFACE, vtable, this) 34 {} 35 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 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 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 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 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 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 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 266 void PowerInterface::emitPowerGoodSignal() 267 { 268 lg2::info("emitPowerGoodSignal"); 269 serverInterface.new_signal("PowerGood").signal_send(); 270 } 271 272 void PowerInterface::emitPowerLostSignal() 273 { 274 lg2::info("emitPowerLostSignal"); 275 serverInterface.new_signal("PowerLost").signal_send(); 276 } 277 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