1 #pragma once
2 
3 #include "ledlayout.hpp"
4 #include "utils.hpp"
5 
6 #include <sdeventplus/event.hpp>
7 #include <sdeventplus/utility/timer.hpp>
8 
9 #include <set>
10 #include <string>
11 #include <unordered_map>
12 
13 namespace phosphor
14 {
15 namespace led
16 {
17 using namespace phosphor::led::utils;
18 
19 static constexpr auto phyLedPath = "/xyz/openbmc_project/led/physical/";
20 static constexpr auto phyLedIntf = "xyz.openbmc_project.Led.Physical";
21 
22 /** @class Manager
23  *  @brief Manages group of LEDs and applies action on the elements of group
24  */
25 class Manager
26 {
27   public:
28     /** @brief Only need the default Manager */
29     Manager() = delete;
30     ~Manager() = default;
31     Manager(const Manager&) = delete;
32     Manager& operator=(const Manager&) = delete;
33     Manager(Manager&&) = delete;
34     Manager& operator=(Manager&&) = delete;
35 
36     /** @brief Special comparator for finding set difference */
ledComp(const phosphor::led::Layout::LedAction & left,const phosphor::led::Layout::LedAction & right)37     static bool ledComp(const phosphor::led::Layout::LedAction& left,
38                         const phosphor::led::Layout::LedAction& right)
39     {
40         // Example :
41         // If FIRST_1 is {fan0, 1, 1} and FIRST_2 is {fan0, 2, 2},
42         // with default priority of Blink, this comparator would return
43         // false. But considering the priority, this comparator would need
44         // to return true so that we consider appropriate set and in
45         // this case its {fan0, 1, 1}
46         if (left.name == right.name)
47         {
48             if (left.action == right.action)
49             {
50                 return false;
51             }
52             else
53             {
54                 return true;
55             }
56         }
57         return left.name < right.name;
58     }
59 
60     /** @brief Comparator for finding LEDs to be DeAsserted */
ledLess(const phosphor::led::Layout::LedAction & left,const phosphor::led::Layout::LedAction & right)61     static bool ledLess(const phosphor::led::Layout::LedAction& left,
62                         const phosphor::led::Layout::LedAction& right)
63     {
64         return left.name < right.name;
65     }
66 
67     /** @brief Comparator for helping unique_copy */
ledEqual(const phosphor::led::Layout::LedAction & left,const phosphor::led::Layout::LedAction & right)68     static bool ledEqual(const phosphor::led::Layout::LedAction& left,
69                          const phosphor::led::Layout::LedAction& right)
70     {
71         return left.name == right.name;
72     }
73 
74     /** @brief static global map constructed at compile time */
75     const GroupMap& ledMap;
76 
77     /** @brief Refer the user supplied LED layout and sdbusplus handler
78      *
79      *  @param [in] bus       - sdbusplus handler
80      *  @param [in] GroupMap - LEDs group layout
81      *  @param [in] Event    - sd event handler
82      */
Manager(sdbusplus::bus_t & bus,const GroupMap & ledLayout,const sdeventplus::Event & event=sdeventplus::Event::get_default ())83     Manager(
84         sdbusplus::bus_t& bus, const GroupMap& ledLayout,
85         const sdeventplus::Event& event = sdeventplus::Event::get_default()) :
86         ledMap(ledLayout),
87         bus(bus), timer(event, [this](auto&) { driveLedsHandler(); })
88     {
89         // Nothing here
90     }
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, const 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     /** @brief sdbusplus handler */
138     sdbusplus::bus_t& bus;
139 
140     /** Map of physical LED path to service name */
141     std::unordered_map<std::string, std::string> phyLeds{};
142 
143     /** DBusHandler class handles the D-Bus operations */
144     DBusHandler dBusHandler;
145 
146     /** @brief Pointers to groups that are in asserted state */
147     std::set<const ActionSet*> assertedGroups;
148 
149     /** @brief Contains the highest priority actions for all
150      *         asserted LEDs.
151      */
152     ActionSet currentState;
153 
154     /** @brief Contains the set of all actions for asserted LEDs */
155     ActionSet combinedState;
156 
157     /** @brief Custom callback when enabled lamp test */
158     std::function<bool(ActionSet& ledsAssert, ActionSet& ledsDeAssert)>
159         lampTestCallBack;
160 
161     /** @brief Timer used for LEDs handler callback*/
162     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
163 
164     /** @brief Contains the required set of assert LEDs action */
165     ActionSet reqLedsAssert;
166 
167     /** @brief Contains the required set of deassert LEDs action */
168     ActionSet reqLedsDeAssert;
169 
170     /** @brief LEDs handler callback */
171     void driveLedsHandler();
172 
173     /** @brief Returns action string based on enum
174      *
175      *  @param[in]  action - Action enum
176      *
177      *  @return string equivalent of the passed in enumeration
178      */
179     static std::string getPhysicalAction(Layout::Action action);
180 };
181 
182 } // namespace led
183 } // namespace phosphor
184