1 #pragma once 2 3 #include "sdbusplus.hpp" 4 5 #include <fmt/format.h> 6 7 #include <phosphor-logging/log.hpp> 8 9 #include <functional> 10 11 namespace phosphor::fan 12 { 13 14 /** 15 * @class PowerState 16 * 17 * This class provides an interface to check the current power state, 18 * and to register a function that gets called when there is a power 19 * state change. 20 * 21 * Different architectures may have different ways of considering 22 * power to be on, such as a pgood property on the 23 * org.openbmc.Control.Power interface, or the CurrentPowerState 24 * property on the State.Chassis interface, so those details will 25 * be in a derived class. 26 */ 27 class PowerState 28 { 29 public: 30 using StateChangeFunc = std::function<void(bool)>; 31 32 PowerState() = delete; 33 virtual ~PowerState() = default; 34 PowerState(const PowerState&) = delete; 35 PowerState& operator=(const PowerState&) = delete; 36 PowerState(PowerState&&) = delete; 37 PowerState& operator=(PowerState&&) = delete; 38 39 /** 40 * @brief Constructor 41 * 42 * @param[in] bus - The D-Bus bus connection object 43 * @param[in] callback - The function that should be run when 44 * the power state changes 45 */ 46 PowerState(sdbusplus::bus::bus& bus, StateChangeFunc callback) : 47 _bus(bus), _callback(std::move(callback)) 48 {} 49 50 /** 51 * @brief Says if power is on 52 * 53 * @return bool - The power state 54 */ 55 bool isPowerOn() const 56 { 57 return _powerState; 58 } 59 60 protected: 61 /** 62 * @brief Called by derived classes to set the power state value 63 * 64 * Will call the callback function if the state changed. 65 * 66 * @param[in] state - The new power state 67 */ 68 void setPowerState(bool state) 69 { 70 if (state != _powerState) 71 { 72 _powerState = state; 73 _callback(_powerState); 74 } 75 } 76 77 /** 78 * @brief Reference to the D-Bus connection object. 79 */ 80 sdbusplus::bus::bus& _bus; 81 82 /** 83 * @brief The power state value 84 */ 85 bool _powerState = false; 86 87 private: 88 /** 89 * @brief The callback function to run when the power state changes 90 */ 91 std::function<void(bool)> _callback; 92 }; 93 94 /** 95 * @class PGoodState 96 * 97 * This class implements the PowerState API by looking at the 'pgood' 98 * property on the org.openbmc.Control.Power interface. 99 */ 100 class PGoodState : public PowerState 101 { 102 public: 103 PGoodState() = delete; 104 virtual ~PGoodState() = default; 105 PGoodState(const PGoodState&) = delete; 106 PGoodState& operator=(const PGoodState&) = delete; 107 PGoodState(PGoodState&&) = delete; 108 PGoodState& operator=(PGoodState&&) = delete; 109 110 /** 111 * @brief Constructor 112 * 113 * @param[in] bus - The D-Bus bus connection object 114 * @param[in] callback - The function that should be run when 115 * the power state changes 116 */ 117 PGoodState(sdbusplus::bus::bus& bus, StateChangeFunc func) : 118 PowerState(bus, func), 119 _match(_bus, 120 sdbusplus::bus::match::rules::propertiesChanged(_pgoodPath, 121 _pgoodInterface), 122 [this](auto& msg) { this->pgoodChanged(msg); }) 123 { 124 try 125 { 126 auto pgood = util::SDBusPlus::getProperty<int32_t>( 127 _bus, _pgoodPath, _pgoodInterface, _pgoodProperty); 128 129 _powerState = static_cast<bool>(pgood); 130 } 131 catch (const util::DBusError& e) 132 { 133 using namespace phosphor::logging; 134 log<level::ERR>( 135 fmt::format("Could not find PGOOD interface {} on D-Bus", 136 _pgoodInterface) 137 .c_str()); 138 throw; 139 } 140 } 141 142 /** 143 * @brief PropertiesChanged callback for the PGOOD property. 144 * 145 * Will call the registered callback function if necessary. 146 * 147 * @param[in] msg - The payload of the propertiesChanged signal 148 */ 149 void pgoodChanged(sdbusplus::message::message& msg) 150 { 151 std::string interface; 152 std::map<std::string, std::variant<int32_t>> properties; 153 154 msg.read(interface, properties); 155 156 auto pgoodProp = properties.find(_pgoodProperty); 157 if (pgoodProp != properties.end()) 158 { 159 auto pgood = std::get<int32_t>(pgoodProp->second); 160 setPowerState(pgood); 161 } 162 } 163 164 private: 165 /** @brief D-Bus path constant */ 166 const std::string _pgoodPath{"/org/openbmc/control/power0"}; 167 168 /** @brief D-Bus interface constant */ 169 const std::string _pgoodInterface{"org.openbmc.control.Power"}; 170 171 /** @brief D-Bus property constant */ 172 const std::string _pgoodProperty{"pgood"}; 173 174 /** @brief The propertiesChanged match */ 175 sdbusplus::bus::match::match _match; 176 }; 177 178 } // namespace phosphor::fan 179