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 */
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             if (left.action == right.action)
53             {
54                 return false;
55             }
56             else
57             {
58                 return true;
59             }
60         }
61         return left.name < right.name;
62     }
63 
64     /** @brief Comparator for finding LEDs to be DeAsserted */
65     static bool ledLess(const phosphor::led::Layout::LedAction& left,
66                         const phosphor::led::Layout::LedAction& right)
67     {
68         return left.name < right.name;
69     }
70 
71     /** @brief Comparator for helping unique_copy */
72     static bool ledEqual(const phosphor::led::Layout::LedAction& left,
73                          const phosphor::led::Layout::LedAction& right)
74     {
75         return left.name == right.name;
76     }
77 
78     /** @brief static global map constructed at compile time */
79     const GroupMap& ledMap;
80 
81     /** @brief Refer the user supplied LED layout and sdbusplus handler
82      *
83      *  @param [in] bus       - sdbusplus handler
84      *  @param [in] GroupMap - LEDs group layout
85      *  @param [in] Event    - sd event handler
86      */
87     Manager(
88         sdbusplus::bus_t& bus, const GroupMap& ledLayout,
89         const sdeventplus::Event& event = sdeventplus::Event::get_default()) :
90         ledMap(ledLayout), bus(bus),
91         timer(event, [this](auto&) { driveLedsHandler(); })
92     {
93         // Nothing here
94     }
95 
96     /* create the resulting map from all currently asserted groups */
97     static auto getNewMap(std::set<const Layout::GroupLayout*> assertedGroups)
98         -> std::map<LedName, Layout::LedAction>;
99 
100     /** @brief Given a group name, applies the action on the group
101      *
102      *  @param[in]  path          -  dbus path of group
103      *  @param[in]  assert        -  Could be true or false
104      *  @param[in]  ledsAssert    -  LEDs that are to be asserted new
105      *                               or to a different state
106      *  @param[in]  ledsDeAssert  -  LEDs that are to be Deasserted
107      *
108      *  @return                   -  Success or exception thrown
109      */
110     bool setGroupState(const std::string& path, bool assert,
111                        ActionSet& ledsAssert, ActionSet& ledsDeAssert);
112 
113     /** @brief Finds the set of LEDs to operate on and executes action
114      *
115      *  @param[in]  ledsAssert    -  LEDs that are to be asserted newly
116      *                               or to a different state
117      *  @param[in]  ledsDeAssert  -  LEDs that are to be Deasserted
118      *
119      *  @return: None
120      */
121     void driveLEDs(ActionSet& ledsAssert, ActionSet& ledsDeAssert);
122 
123     /** @brief Chooses appropriate action to be triggered on physical LED
124      *  and calls into function that applies the actual action.
125      *
126      *  @param[in]  objPath   -  D-Bus object path
127      *  @param[in]  action    -  Intended action to be triggered
128      *  @param[in]  dutyOn    -  Duty Cycle ON percentage
129      *  @param[in]  period    -  Time taken for one blink cycle
130      *
131      *  @return:              -  0: success, -1: LED set failed
132      */
133     int drivePhysicalLED(const std::string& objPath, Layout::Action action,
134                          uint8_t dutyOn, const uint16_t period);
135 
136     /** @brief Set lamp test callback when enabled lamp test.
137      *
138      *  @param[in]  callBack   -  Custom callback when enabled lamp test
139      */
140     void setLampTestCallBack(
141         std::function<bool(ActionSet& ledsAssert, ActionSet& ledsDeAssert)>
142             callBack);
143 
144   private:
145     /** @brief sdbusplus handler */
146     sdbusplus::bus_t& bus;
147 
148     /** Map of physical LED path to service name */
149     std::unordered_map<std::string, std::string> phyLeds{};
150 
151     /** DBusHandler class handles the D-Bus operations */
152     DBusHandler dBusHandler;
153 
154     /** @brief Pointers to groups that are in asserted state */
155     std::set<const Layout::GroupLayout*> assertedGroups;
156 
157     /** Map of led name to current state */
158     std::map<std::string, Layout::LedAction> ledStateMap;
159 
160     /** @brief Custom callback when enabled lamp test */
161     std::function<bool(ActionSet& ledsAssert, ActionSet& ledsDeAssert)>
162         lampTestCallBack;
163 
164     /** @brief Timer used for LEDs handler callback*/
165     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
166 
167     /** @brief Contains the required set of assert LEDs action */
168     ActionSet reqLedsAssert;
169 
170     /** @brief Contains the required set of deassert LEDs action */
171     ActionSet reqLedsDeAssert;
172 
173     /** @brief LEDs handler callback */
174     void driveLedsHandler();
175 
176     /** @brief Returns action string based on enum
177      *
178      *  @param[in]  action - Action enum
179      *
180      *  @return string equivalent of the passed in enumeration
181      */
182     static std::string getPhysicalAction(Layout::Action action);
183 };
184 
185 } // namespace led
186 } // namespace phosphor
187