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