#include "config-validator.hpp" #include "grouplayout.hpp" #include "ledlayout.hpp" #include #include using namespace phosphor::led; namespace phosphor { namespace led { // Priority for a particular LED needs to stay SAME across all groups using PriorityMap = std::unordered_map>; static bool isUsingGroupPriority(const phosphor::led::GroupMap& ledMap) { for (const auto& [_, group] : ledMap) { if (group.priority != 0) { return true; } } return false; } static std::string priorityToString( const std::optional& priority) { if (!priority.has_value()) { return "none"; } switch (priority.value()) { case phosphor::led::Layout::Action::Off: return "Off"; case phosphor::led::Layout::Action::On: return "On"; case phosphor::led::Layout::Action::Blink: return "Blink"; } return "?"; } /** @brief Validate the Priority of an LED is same across ALL groups * * @param[in] name - led name member of each group * @param[in] priority - member priority of each group * @param[out] priorityMap - std::unordered_map, key:name, value:priority * * @return */ void validatePriority( const std::string& name, const std::optional& priority, PriorityMap& priorityMap) { auto iter = priorityMap.find(name); if (iter == priorityMap.end()) { priorityMap.emplace(name, priority); return; } if (iter->second != priority) { throw ConfigValidationException( error::LedPriorityMismatch, "?", name, "Priority of the LED is not same across groups. Old Priority = " + priorityToString(iter->second) + ", New Priority = " + priorityToString(priority)); } } static void validateConfigV1GroupForLedPriority( const std::string groupName, const phosphor::led::Layout::GroupLayout& group, PriorityMap& priorityMap) { if (group.priority != 0) { throw ConfigValidationException( error::MixedLedAndGroupPriority, groupName, "Cannot mix group priority and led priority"); } for (const auto& ledAction : group.actionSet) { if (ledAction.priority == std::nullopt) { throw ConfigValidationException(error::MissingLedPriority, groupName, ledAction.name, "Need valid led priority"); } // Same LEDs can be part of multiple groups. However, their // priorities across groups need to match. validatePriority(ledAction.name, ledAction.priority, priorityMap); } } static void validateConfigV1ForLedPriority(const phosphor::led::GroupMap& ledMap) { PriorityMap priorityMap{}; for (const auto& [groupName, group] : ledMap) { validateConfigV1GroupForLedPriority(groupName, group, priorityMap); } } static void validateConfigV1GroupForGroupPriority( const std::string groupName, const phosphor::led::Layout::GroupLayout& group) { for (const auto& led : group.actionSet) { if (led.priority != std::nullopt) { throw ConfigValidationException( error::MixedLedAndGroupPriority, groupName, led.name, "Cannot mix group priority and led priority for LED"); } } if (group.priority == 0) { // group priority 0 is for internal use throw ConfigValidationException(error::InvalidGroupPriority, groupName, "Group Priority cannot be 0"); } } static void validateConfigV1ForGroupPriority(const phosphor::led::GroupMap& ledMap) { std::set groupPriorities; for (const auto& [_, group] : ledMap) { groupPriorities.insert(group.priority); } if (groupPriorities.size() != ledMap.size()) { throw ConfigValidationException( error::DuplicateGroupPriority, "When using Group Priority, no 2 Groups may have the same priority"); } for (const auto& [groupName, group] : ledMap) { validateConfigV1GroupForGroupPriority(groupName, group); } } void validateConfigV1(const GroupMap& ledMap) { const bool useGroupPriority = isUsingGroupPriority(ledMap); if (useGroupPriority) { validateConfigV1ForGroupPriority(ledMap); } else { validateConfigV1ForLedPriority(ledMap); } } } // namespace led } // namespace phosphor