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 <set>
11 #include <string>
12 #include <unordered_map>
13 
14 // to better see what the string is representing
15 using LedName = std::string;
16 
17 namespace phosphor
18 {
19 namespace led
20 {
21 using namespace phosphor::led::utils;
22 
23 static constexpr auto phyLedPath = "/xyz/openbmc_project/led/physical/";
24 static constexpr auto phyLedIntf = "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 & bus,const GroupMap & ledLayout,const sdeventplus::Event & event=sdeventplus::Event::get_default ())80     Manager(
81         sdbusplus::bus_t& bus, const GroupMap& ledLayout,
82         const sdeventplus::Event& event = sdeventplus::Event::get_default()) :
83         ledMap(ledLayout), bus(bus),
84         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     static int drivePhysicalLED(const std::string& objPath,
127                                 Layout::Action action, uint8_t dutyOn,
128                                 uint16_t period);
129 
130     /** @brief Set lamp test callback when enabled lamp test.
131      *
132      *  @param[in]  callBack   -  Custom callback when enabled lamp test
133      */
134     void setLampTestCallBack(
135         std::function<bool(ActionSet& ledsAssert, ActionSet& ledsDeAssert)>
136             callBack);
137 
138   private:
139     /** @brief sdbusplus handler */
140     sdbusplus::bus_t& bus;
141 
142     /** Map of physical LED path to service name */
143     std::unordered_map<std::string, std::string> phyLeds;
144 
145     /** @brief Pointers to groups that are in asserted state */
146     std::set<const Layout::GroupLayout*> assertedGroups;
147 
148     /** Map of led name to current state */
149     std::map<std::string, Layout::LedAction> ledStateMap;
150 
151     /** @brief Custom callback when enabled lamp test */
152     std::function<bool(ActionSet& ledsAssert, ActionSet& ledsDeAssert)>
153         lampTestCallBack;
154 
155     /** @brief Timer used for LEDs handler callback*/
156     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
157 
158     /** @brief Contains the required set of assert LEDs action */
159     ActionSet reqLedsAssert;
160 
161     /** @brief Contains the required set of deassert LEDs action */
162     ActionSet reqLedsDeAssert;
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