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