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