1 #include "config-validator.hpp" 2 3 #include "grouplayout.hpp" 4 #include "ledlayout.hpp" 5 6 #include <phosphor-logging/lg2.hpp> 7 #include <sdbusplus/bus.hpp> 8 9 using namespace phosphor::led; 10 11 namespace phosphor 12 { 13 namespace led 14 { 15 16 // Priority for a particular LED needs to stay SAME across all groups 17 using PriorityMap = 18 std::unordered_map<std::string, 19 std::optional<phosphor::led::Layout::Action>>; 20 21 static bool isUsingGroupPriority(const phosphor::led::GroupMap& ledMap) 22 { 23 for (const auto& [_, group] : ledMap) 24 { 25 if (group.priority != 0) 26 { 27 return true; 28 } 29 } 30 return false; 31 } 32 33 static std::string priorityToString( 34 const std::optional<phosphor::led::Layout::Action>& priority) 35 { 36 if (!priority.has_value()) 37 { 38 return "none"; 39 } 40 switch (priority.value()) 41 { 42 case phosphor::led::Layout::Action::Off: 43 return "Off"; 44 case phosphor::led::Layout::Action::On: 45 return "On"; 46 case phosphor::led::Layout::Action::Blink: 47 return "Blink"; 48 } 49 return "?"; 50 } 51 52 /** @brief Validate the Priority of an LED is same across ALL groups 53 * 54 * @param[in] name - led name member of each group 55 * @param[in] priority - member priority of each group 56 * @param[out] priorityMap - std::unordered_map, key:name, value:priority 57 * 58 * @return 59 */ 60 void validatePriority( 61 const std::string& name, 62 const std::optional<phosphor::led::Layout::Action>& priority, 63 PriorityMap& priorityMap) 64 { 65 auto iter = priorityMap.find(name); 66 if (iter == priorityMap.end()) 67 { 68 priorityMap.emplace(name, priority); 69 return; 70 } 71 72 if (iter->second != priority) 73 { 74 throw ConfigValidationException( 75 error::LedPriorityMismatch, "?", name, 76 "Priority of the LED is not same across groups. Old Priority = " + 77 priorityToString(iter->second) + 78 ", New Priority = " + priorityToString(priority)); 79 } 80 } 81 82 static void validateConfigV1GroupForLedPriority( 83 const std::string groupName, 84 const phosphor::led::Layout::GroupLayout& group, PriorityMap& priorityMap) 85 { 86 if (group.priority != 0) 87 { 88 throw ConfigValidationException( 89 error::MixedLedAndGroupPriority, groupName, 90 "Cannot mix group priority and led priority"); 91 } 92 93 for (const auto& ledAction : group.actionSet) 94 { 95 if (ledAction.priority == std::nullopt) 96 { 97 throw ConfigValidationException(error::MissingLedPriority, 98 groupName, ledAction.name, 99 "Need valid led priority"); 100 } 101 102 // Same LEDs can be part of multiple groups. However, their 103 // priorities across groups need to match. 104 validatePriority(ledAction.name, ledAction.priority, priorityMap); 105 } 106 } 107 108 static void 109 validateConfigV1ForLedPriority(const phosphor::led::GroupMap& ledMap) 110 { 111 PriorityMap priorityMap{}; 112 for (const auto& [groupName, group] : ledMap) 113 { 114 validateConfigV1GroupForLedPriority(groupName, group, priorityMap); 115 } 116 } 117 118 static void validateConfigV1GroupForGroupPriority( 119 const std::string groupName, 120 const phosphor::led::Layout::GroupLayout& group) 121 { 122 for (const auto& led : group.actionSet) 123 { 124 if (led.priority != std::nullopt) 125 { 126 throw ConfigValidationException( 127 error::MixedLedAndGroupPriority, groupName, led.name, 128 "Cannot mix group priority and led priority for LED"); 129 } 130 } 131 132 if (group.priority == 0) 133 { 134 // group priority 0 is for internal use 135 throw ConfigValidationException(error::InvalidGroupPriority, groupName, 136 "Group Priority cannot be 0"); 137 } 138 } 139 140 static void 141 validateConfigV1ForGroupPriority(const phosphor::led::GroupMap& ledMap) 142 { 143 std::set<int> groupPriorities; 144 for (const auto& [_, group] : ledMap) 145 { 146 groupPriorities.insert(group.priority); 147 } 148 149 if (groupPriorities.size() != ledMap.size()) 150 { 151 throw ConfigValidationException( 152 error::DuplicateGroupPriority, 153 "When using Group Priority, no 2 Groups may have the same priority"); 154 } 155 156 for (const auto& [groupName, group] : ledMap) 157 { 158 validateConfigV1GroupForGroupPriority(groupName, group); 159 } 160 } 161 162 void validateConfigV1(const GroupMap& ledMap) 163 { 164 const bool useGroupPriority = isUsingGroupPriority(ledMap); 165 166 if (useGroupPriority) 167 { 168 validateConfigV1ForGroupPriority(ledMap); 169 } 170 else 171 { 172 validateConfigV1ForLedPriority(ledMap); 173 } 174 } 175 176 } // namespace led 177 } // namespace phosphor 178