blob: 05b0157cee82a0c03ca80f7180f3d695c9c93502 [file] [log] [blame]
Alexander Hansen638d1482024-08-21 17:39:57 +02001#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
9using namespace phosphor::led;
10
11namespace phosphor
12{
13namespace led
14{
15
16// Priority for a particular LED needs to stay SAME across all groups
17using PriorityMap =
18 std::unordered_map<std::string,
19 std::optional<phosphor::led::Layout::Action>>;
20
21static 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
33static 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 */
60void 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
82static 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
108static 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
118static 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
140static 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
162void 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