xref: /openbmc/phosphor-led-manager/manager/manager.hpp (revision d4d474fe5f09c1b44b2590def26a57f0583635f1)
1 #pragma once
2 
3 #include "grouplayout.hpp"
4 #include "ledlayout.hpp"
5 #include "utils.hpp"
6 
7 #include <sdeventplus/event.hpp>
8 #include <sdeventplus/utility/timer.hpp>
9 
10 #include <chrono>
11 #include <set>
12 #include <string>
13 #include <unordered_map>
14 
15 // to better see what the string is representing
16 using LedName = std::string;
17 
18 namespace phosphor
19 {
20 namespace led
21 {
22 using namespace phosphor::led::utils;
23 
24 static constexpr auto phyLedPath = "/xyz/openbmc_project/led/physical/";
25 
26 /** @class Manager
27  *  @brief Manages group of LEDs and applies action on the elements of group
28  */
29 class Manager
30 {
31   public:
32     /** @brief Only need the default Manager */
33     Manager() = delete;
34     ~Manager() = default;
35     Manager(const Manager&) = delete;
36     Manager& operator=(const Manager&) = delete;
37     Manager(Manager&&) = delete;
38     Manager& operator=(Manager&&) = delete;
39 
40     /** @brief Special comparator for finding set difference */
ledComp(const phosphor::led::Layout::LedAction & left,const phosphor::led::Layout::LedAction & right)41     static bool ledComp(const phosphor::led::Layout::LedAction& left,
42                         const phosphor::led::Layout::LedAction& right)
43     {
44         // Example :
45         // If FIRST_1 is {fan0, 1, 1} and FIRST_2 is {fan0, 2, 2},
46         // with default priority of Blink, this comparator would return
47         // false. But considering the priority, this comparator would need
48         // to return true so that we consider appropriate set and in
49         // this case its {fan0, 1, 1}
50         if (left.name == right.name)
51         {
52             return left.action != right.action;
53         }
54         return left.name < right.name;
55     }
56 
57     /** @brief Comparator for finding LEDs to be DeAsserted */
ledLess(const phosphor::led::Layout::LedAction & left,const phosphor::led::Layout::LedAction & right)58     static bool ledLess(const phosphor::led::Layout::LedAction& left,
59                         const phosphor::led::Layout::LedAction& right)
60     {
61         return left.name < right.name;
62     }
63 
64     /** @brief Comparator for helping unique_copy */
ledEqual(const phosphor::led::Layout::LedAction & left,const phosphor::led::Layout::LedAction & right)65     static bool ledEqual(const phosphor::led::Layout::LedAction& left,
66                          const phosphor::led::Layout::LedAction& right)
67     {
68         return left.name == right.name;
69     }
70 
71     /** @brief static global map constructed at compile time */
72     const GroupMap& ledMap;
73 
74     /** @brief Refer the user supplied LED layout and sdbusplus handler
75      *
76      *  @param [in] bus       - sdbusplus handler
77      *  @param [in] GroupMap - LEDs group layout
78      *  @param [in] Event    - sd event handler
79      */
Manager(sdbusplus::bus_t &,const GroupMap & ledLayout,const sdeventplus::Event & event=sdeventplus::Event::get_default ())80     Manager(
81         sdbusplus::bus_t&, const GroupMap& ledLayout,
82         const sdeventplus::Event& event = sdeventplus::Event::get_default()) :
83         ledMap(ledLayout), timer(event, [this](auto&) { driveLedsHandler(); })
84     {
85         // Nothing here
86     }
87 
88     /* create the resulting map from all currently asserted groups */
89     static auto getNewMap(std::set<const Layout::GroupLayout*> assertedGroups)
90         -> std::map<LedName, Layout::LedAction>;
91 
92     /** @brief Given a group name, applies the action on the group
93      *
94      *  @param[in]  path          -  dbus path of group
95      *  @param[in]  assert        -  Could be true or false
96      *  @param[in]  ledsAssert    -  LEDs that are to be asserted new
97      *                               or to a different state
98      *  @param[in]  ledsDeAssert  -  LEDs that are to be Deasserted
99      *
100      *  @return                   -  Success or exception thrown
101      */
102     bool setGroupState(const std::string& path, bool assert,
103                        ActionSet& ledsAssert, ActionSet& ledsDeAssert);
104 
105     /** @brief Finds the set of LEDs to operate on and executes action
106      *
107      *  @param[in]  ledsAssert    -  LEDs that are to be asserted newly
108      *                               or to a different state
109      *  @param[in]  ledsDeAssert  -  LEDs that are to be Deasserted
110      *
111      *  @return: None
112      */
113     void driveLEDs(ActionSet& ledsAssert, ActionSet& ledsDeAssert);
114 
115     /** @brief Chooses appropriate action to be triggered on physical LED
116      *  and calls into function that applies the actual action.
117      *
118      *  @param[in]  objPath   -  D-Bus object path
119      *  @param[in]  action    -  Intended action to be triggered
120      *  @param[in]  dutyOn    -  Duty Cycle ON percentage
121      *  @param[in]  period    -  Time taken for one blink cycle
122      *
123      *  @return:              -  0: success, -1: LED set failed
124      */
125     int drivePhysicalLED(const std::string& objPath, Layout::Action action,
126                          uint8_t dutyOn, uint16_t period);
127 
128     /** @brief Set lamp test callback when enabled lamp test.
129      *
130      *  @param[in]  callBack   -  Custom callback when enabled lamp test
131      */
132     void setLampTestCallBack(
133         std::function<bool(ActionSet& ledsAssert, ActionSet& ledsDeAssert)>
134             callBack);
135 
136   private:
137     /** Map of physical LED path to service name */
138     std::unordered_map<std::string, std::string> phyLeds;
139 
140     /** @brief Pointers to groups that are in asserted state */
141     std::set<const Layout::GroupLayout*> assertedGroups;
142 
143     /** Map of led name to current state */
144     std::map<std::string, Layout::LedAction> ledStateMap;
145 
146     /** @brief Custom callback when enabled lamp test */
147     std::function<bool(ActionSet& ledsAssert, ActionSet& ledsDeAssert)>
148         lampTestCallBack;
149 
150     /** @brief Timer used for LEDs handler callback*/
151     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
152 
153     /** @brief Contains the required set of assert LEDs action */
154     ActionSet reqLedsAssert;
155 
156     /** @brief Contains the required set of deassert LEDs action */
157     ActionSet reqLedsDeAssert;
158 
159     /** @brief Map to store the last error time for physical LED paths */
160     std::unordered_map<std::string,
161                        std::chrono::time_point<std::chrono::steady_clock>>
162         physicalLEDErrors;
163 
164     /** @brief LEDs handler callback */
165     void driveLedsHandler();
166 
167     /** @brief Returns action string based on enum
168      *
169      *  @param[in]  action - Action enum
170      *
171      *  @return string equivalent of the passed in enumeration
172      */
173     static std::string getPhysicalAction(Layout::Action action);
174 };
175 
176 } // namespace led
177 } // namespace phosphor
178