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