| /** |
| * Copyright © 2021 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "power_interface.hpp" |
| |
| #include "types.hpp" |
| |
| #include <fmt/format.h> |
| |
| #include <phosphor-logging/log.hpp> |
| #include <sdbusplus/exception.hpp> |
| #include <sdbusplus/sdbus.hpp> |
| #include <sdbusplus/server.hpp> |
| |
| #include <string> |
| #include <tuple> |
| |
| using namespace phosphor::logging; |
| |
| namespace phosphor::power::sequencer |
| { |
| |
| PowerInterface::PowerInterface(sdbusplus::bus_t& bus, const char* path) : |
| serverInterface(bus, path, POWER_IFACE, vtable, this) |
| {} |
| |
| int PowerInterface::callbackGetPgood(sd_bus* /*bus*/, const char* /*path*/, |
| const char* /*interface*/, |
| const char* /*property*/, |
| sd_bus_message* msg, void* context, |
| sd_bus_error* error) |
| { |
| if (msg != nullptr && context != nullptr) |
| { |
| try |
| { |
| auto pwrObj = static_cast<PowerInterface*>(context); |
| int pgood = pwrObj->getPgood(); |
| log<level::INFO>( |
| fmt::format("callbackGetPgood: {}", pgood).c_str()); |
| |
| sdbusplus::message_t(msg).append(pgood); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| return sd_bus_error_set(error, e.name(), e.description()); |
| } |
| } |
| else |
| { |
| // The message or context were null |
| log<level::ERR>("Unable to service get pgood property callback"); |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| int PowerInterface::callbackGetPgoodTimeout(sd_bus* /*bus*/, |
| const char* /*path*/, |
| const char* /*interface*/, |
| const char* /*property*/, |
| sd_bus_message* msg, void* context, |
| sd_bus_error* error) |
| { |
| if (msg != nullptr && context != nullptr) |
| { |
| try |
| { |
| auto pwrObj = static_cast<PowerInterface*>(context); |
| int timeout = pwrObj->getPgoodTimeout(); |
| log<level::INFO>( |
| fmt::format("callbackGetPgoodTimeout: {}", timeout).c_str()); |
| |
| sdbusplus::message_t(msg).append(timeout); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| return sd_bus_error_set(error, e.name(), e.description()); |
| } |
| } |
| else |
| { |
| // The message or context were null |
| log<level::ERR>( |
| "Unable to service get pgood timeout property callback"); |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| int PowerInterface::callbackGetPowerState(sd_bus_message* msg, void* context, |
| sd_bus_error* error) |
| { |
| if (msg != nullptr && context != nullptr) |
| { |
| try |
| { |
| auto pwrObj = static_cast<PowerInterface*>(context); |
| // Return the current power state of the GPIO, rather than the last |
| // requested power state change |
| int pgood = pwrObj->getPgood(); |
| log<level::INFO>( |
| fmt::format("callbackGetPowerState: {}", pgood).c_str()); |
| |
| auto reply = sdbusplus::message_t(msg).new_method_return(); |
| reply.append(pgood); |
| reply.method_return(); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| return sd_bus_error_set(error, e.name(), e.description()); |
| } |
| } |
| else |
| { |
| // The message or context were null |
| log<level::ERR>("Unable to service getPowerState method callback"); |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| int PowerInterface::callbackSetPgoodTimeout(sd_bus* /*bus*/, |
| const char* /*path*/, |
| const char* /*interface*/, |
| const char* /*property*/, |
| sd_bus_message* msg, void* context, |
| sd_bus_error* error) |
| { |
| if (msg != nullptr && context != nullptr) |
| { |
| try |
| { |
| auto m = sdbusplus::message_t(msg); |
| |
| int timeout{}; |
| m.read(timeout); |
| log<level::INFO>( |
| fmt::format("callbackSetPgoodTimeout: {}", timeout).c_str()); |
| |
| auto pwrObj = static_cast<PowerInterface*>(context); |
| pwrObj->setPgoodTimeout(timeout); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| return sd_bus_error_set(error, e.name(), e.description()); |
| } |
| } |
| else |
| { |
| // The message or context were null |
| log<level::ERR>( |
| "Unable to service set pgood timeout property callback"); |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| int PowerInterface::callbackGetState(sd_bus* /*bus*/, const char* /*path*/, |
| const char* /*interface*/, |
| const char* /*property*/, |
| sd_bus_message* msg, void* context, |
| sd_bus_error* error) |
| { |
| if (msg != nullptr && context != nullptr) |
| { |
| try |
| { |
| auto pwrObj = static_cast<PowerInterface*>(context); |
| int state = pwrObj->getState(); |
| log<level::INFO>( |
| fmt::format("callbackGetState: {}", state).c_str()); |
| |
| sdbusplus::message_t(msg).append(state); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| return sd_bus_error_set(error, e.name(), e.description()); |
| } |
| } |
| else |
| { |
| // The message or context were null |
| log<level::ERR>("Unable to service get state property callback"); |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| int PowerInterface::callbackSetPowerState(sd_bus_message* msg, void* context, |
| sd_bus_error* error) |
| { |
| if (msg != nullptr && context != nullptr) |
| { |
| try |
| { |
| auto m = sdbusplus::message_t(msg); |
| |
| int state{}; |
| m.read(state); |
| |
| if (state != 1 && state != 0) |
| { |
| return sd_bus_error_set(error, |
| "org.openbmc.ControlPower.Error.Failed", |
| "Invalid power state"); |
| } |
| log<level::INFO>( |
| fmt::format("callbackSetPowerState: {}", state).c_str()); |
| |
| auto pwrObj = static_cast<PowerInterface*>(context); |
| pwrObj->setState(state); |
| |
| m.new_method_return().method_return(); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| return sd_bus_error_set(error, e.name(), e.description()); |
| } |
| } |
| else |
| { |
| // The message or context were null |
| log<level::ERR>("Unable to service setPowerState method callback"); |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| int PowerInterface::callbackSetPowerSupplyError(sd_bus_message* msg, |
| void* context, |
| sd_bus_error* error) |
| { |
| if (msg != nullptr && context != nullptr) |
| { |
| try |
| { |
| auto m = sdbusplus::message_t(msg); |
| |
| std::string psError{}; |
| m.read(psError); |
| log<level::INFO>( |
| fmt::format("callbackSetPowerSupplyError: {}", psError) |
| .c_str()); |
| |
| auto pwrObj = static_cast<PowerInterface*>(context); |
| pwrObj->setPowerSupplyError(psError); |
| |
| m.new_method_return().method_return(); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| return sd_bus_error_set(error, e.name(), e.description()); |
| } |
| } |
| else |
| { |
| // The message or context were null |
| log<level::ERR>( |
| "Unable to service setPowerSupplyError method callback"); |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| void PowerInterface::emitPowerGoodSignal() |
| { |
| log<level::INFO>("emitPowerGoodSignal"); |
| serverInterface.new_signal("PowerGood").signal_send(); |
| } |
| |
| void PowerInterface::emitPowerLostSignal() |
| { |
| log<level::INFO>("emitPowerLostSignal"); |
| serverInterface.new_signal("PowerLost").signal_send(); |
| } |
| |
| void PowerInterface::emitPropertyChangedSignal(const char* property) |
| { |
| log<level::INFO>( |
| fmt::format("emitPropertyChangedSignal: {}", property).c_str()); |
| serverInterface.property_changed(property); |
| } |
| |
| const sdbusplus::vtable::vtable_t PowerInterface::vtable[] = { |
| sdbusplus::vtable::start(), |
| // Method setPowerState takes an int parameter and returns void |
| sdbusplus::vtable::method("setPowerState", "i", "", callbackSetPowerState), |
| // Method getPowerState takes no parameters and returns int |
| sdbusplus::vtable::method("getPowerState", "", "i", callbackGetPowerState), |
| // Signal PowerGood |
| sdbusplus::vtable::signal("PowerGood", ""), |
| // Signal PowerLost |
| sdbusplus::vtable::signal("PowerLost", ""), |
| // Property pgood is type int, read only, and uses the emits_change flag |
| sdbusplus::vtable::property("pgood", "i", callbackGetPgood, |
| sdbusplus::vtable::property_::emits_change), |
| // Property state is type int, read only, and uses the emits_change flag |
| sdbusplus::vtable::property("state", "i", callbackGetState, |
| sdbusplus::vtable::property_::emits_change), |
| // Property pgood_timeout is type int, read write, and uses the emits_change |
| // flag |
| sdbusplus::vtable::property("pgood_timeout", "i", callbackGetPgoodTimeout, |
| callbackSetPgoodTimeout, |
| sdbusplus::vtable::property_::emits_change), |
| // Method setPowerSupplyError takes a string parameter and returns void |
| sdbusplus::vtable::method("setPowerSupplyError", "s", "", |
| callbackSetPowerSupplyError), |
| sdbusplus::vtable::end()}; |
| |
| } // namespace phosphor::power::sequencer |