blob: 05b0157cee82a0c03ca80f7180f3d695c9c93502 [file] [log] [blame]
#include "config-validator.hpp"
#include "grouplayout.hpp"
#include "ledlayout.hpp"
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/bus.hpp>
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<std::string,
std::optional<phosphor::led::Layout::Action>>;
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<phosphor::led::Layout::Action>& 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<phosphor::led::Layout::Action>& 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<int> 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