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