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