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