1 #pragma once
2 
3 #include "power_supply.hpp"
4 #include "types.hpp"
5 #include "utility.hpp"
6 
7 #include <phosphor-logging/log.hpp>
8 #include <sdbusplus/bus/match.hpp>
9 #include <sdeventplus/event.hpp>
10 #include <sdeventplus/utility/timer.hpp>
11 
12 struct sys_properties
13 {
14     int minPowerSupplies;
15     int maxPowerSupplies;
16 };
17 
18 using namespace phosphor::power::psu;
19 using namespace phosphor::logging;
20 
21 namespace phosphor
22 {
23 namespace power
24 {
25 namespace manager
26 {
27 
28 /**
29  * @class PSUManager
30  *
31  * This class will create an object used to manage and monitor a list of power
32  * supply devices.
33  */
34 class PSUManager
35 {
36   public:
37     PSUManager() = delete;
38     ~PSUManager() = default;
39     PSUManager(const PSUManager&) = delete;
40     PSUManager& operator=(const PSUManager&) = delete;
41     PSUManager(PSUManager&&) = delete;
42     PSUManager& operator=(PSUManager&&) = delete;
43 
44     /**
45      * Constructor
46      *
47      * @param[in] bus - D-Bus bus object
48      * @param[in] e - event object
49      * @param[in] configfile - string path to the configuration file
50      */
51     PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
52                const std::string& configfile);
53 
54     void getJSONProperties(const std::string& path, sdbusplus::bus::bus& bus,
55                            sys_properties& p,
56                            std::vector<std::unique_ptr<PowerSupply>>& psus);
57 
58     /**
59      * Initializes the manager.
60      *
61      * Get current BMC state, ...
62      */
63     void initialize()
64     {
65         // When state = 1, system is powered on
66         int32_t state = 0;
67 
68         try
69         {
70             // Use getProperty utility function to get power state.
71             util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
72                                        powerService, bus, state);
73 
74             if (state)
75             {
76                 powerOn = true;
77             }
78             else
79             {
80                 powerOn = false;
81             }
82         }
83         catch (std::exception& e)
84         {
85             log<level::INFO>("Failed to get power state. Assuming it is off.");
86             powerOn = false;
87         }
88 
89         onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
90         clearFaults();
91         updateInventory();
92     }
93 
94     /**
95      * Starts the timer to start monitoring the list of devices.
96      */
97     int run()
98     {
99         return timer->get_event().loop();
100     }
101 
102     /**
103      * Write PMBus ON_OFF_CONFIG
104      *
105      * This function will be called to cause the PMBus device driver to send the
106      * ON_OFF_CONFIG command. Takes one byte of data.
107      */
108     void onOffConfig(const uint8_t data)
109     {
110         for (auto& psu : psus)
111         {
112             psu->onOffConfig(data);
113         }
114     }
115 
116     /**
117      * This function will be called in various situations in order to clear
118      * any fault status bits that may have been set, in order to start over
119      * with a clean state. Presence changes and power state changes will want
120      * to clear any faults logged.
121      */
122     void clearFaults()
123     {
124         for (auto& psu : psus)
125         {
126             psu->clearFaults();
127         }
128 
129         faultLogged = false;
130     }
131 
132   private:
133     /**
134      * The D-Bus object
135      */
136     sdbusplus::bus::bus& bus;
137 
138     /**
139      * The timer that runs to periodically check the power supplies.
140      */
141     std::unique_ptr<
142         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
143         timer;
144 
145     /**
146      * Analyze the status of each of the power supplies.
147      */
148     void analyze()
149     {
150         for (auto& psu : psus)
151         {
152             psu->analyze();
153         }
154 
155         for (auto& psu : psus)
156         {
157             // TODO: Fault priorities #918
158             if (!faultLogged && psu->isFaulted())
159             {
160                 if (psu->hasInputFault())
161                 {
162                     // TODO: Create error log
163                 }
164 
165                 if (psu->hasMFRFault())
166                 {
167                     // TODO: Create error log
168                 }
169 
170                 if (psu->hasVINUVFault())
171                 {
172                     // TODO: Create error log
173                 }
174             }
175         }
176     }
177 
178     /** @brief True if the power is on. */
179     bool powerOn = false;
180 
181     /** @brief True if fault logged. Clear in clearFaults(). */
182     bool faultLogged = false;
183 
184     /** @brief Used as part of subscribing to power on state changes*/
185     std::string powerService;
186 
187     /** @brief Used to subscribe to D-Bus power on state changes */
188     std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
189 
190     /**
191      * @brief Callback for power state property changes
192      *
193      * Process changes to the powered on state property for the system.
194      *
195      * @param[in] msg - Data associated with the power state signal
196      */
197     void powerStateChanged(sdbusplus::message::message& msg);
198 
199     /**
200      * @brief Adds properties to the inventory.
201      *
202      * Reads the values from the devices and writes them to the associated
203      * power supply D-Bus inventory objects.
204      *
205      * This needs to be done on startup, and each time the presence state
206      * changes.
207      */
208     void updateInventory()
209     {
210         for (auto& psu : psus)
211         {
212             psu->updateInventory();
213         }
214     }
215 
216     /**
217      * @brief Minimum number of power supplies to operate.
218      */
219     int minPSUs = 1;
220 
221     /**
222      * @brief Maximum number of power supplies possible.
223      */
224     int maxPSUs = 1;
225 
226     /**
227      * @brief The vector for power supplies.
228      */
229     std::vector<std::unique_ptr<PowerSupply>> psus;
230 };
231 
232 } // namespace manager
233 } // namespace power
234 } // namespace phosphor
235