blob: d576afe0e50129a1c16b54bce3f87574de311b0f [file] [log] [blame]
Matt Spinler432efec2020-09-24 13:41:31 -05001#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
11namespace 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 */
27class 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 */
100class 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