-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathlamptest.cpp
300 lines (255 loc) · 8.16 KB
/
lamptest.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#include "lamptest.hpp"
#include <phosphor-logging/lg2.hpp>
namespace phosphor
{
namespace led
{
using Json = nlohmann::json;
bool LampTest::processLEDUpdates(const Manager::group& ledsAssert,
const Manager::group& ledsDeAssert)
{
// If the physical LED status is updated during the lamp test, it should be
// saved to Queue, and the queue will be processed after the lamp test is
// stopped.
if (isLampTestRunning)
{
// Physical LEDs will be updated during lamp test
for (const auto& it : ledsDeAssert)
{
std::string path = std::string(PHY_LED_PATH) + it.name;
auto iter = std::find_if(
forceUpdateLEDs.begin(), forceUpdateLEDs.end(),
[&path](const auto& name) { return name == path; });
if (iter != forceUpdateLEDs.end())
{
manager.drivePhysicalLED(path, Layout::Action::Off, it.dutyOn,
it.period);
}
}
for (const auto& it : ledsAssert)
{
std::string path = std::string(PHY_LED_PATH) + it.name;
auto iter = std::find_if(
forceUpdateLEDs.begin(), forceUpdateLEDs.end(),
[&path](const auto& name) { return name == path; });
if (iter != forceUpdateLEDs.end())
{
manager.drivePhysicalLED(path, it.action, it.dutyOn, it.period);
}
}
updatedLEDsDuringLampTest.emplace(
std::make_pair(ledsAssert, ledsDeAssert));
return true;
}
return false;
}
void LampTest::stop()
{
if (!isLampTestRunning)
{
return;
}
timer.setEnabled(false);
// Stop host lamp test
doHostLampTest(false);
// Set all the Physical action to Off
for (const auto& path : physicalLEDPaths)
{
auto iter =
std::find_if(skipUpdateLEDs.begin(), skipUpdateLEDs.end(),
[&path](const auto& skip) { return skip == path; });
if (iter != skipUpdateLEDs.end())
{
// Skip update physical path
continue;
}
manager.drivePhysicalLED(path, Layout::Action::Off, 0, 0);
}
isLampTestRunning = false;
restorePhysicalLedStates();
}
Layout::Action LampTest::getActionFromString(const std::string& str)
{
Layout::Action action = Layout::Off;
if (str == "xyz.openbmc_project.Led.Physical.Action.On")
{
action = Layout::On;
}
else if (str == "xyz.openbmc_project.Led.Physical.Action.Blink")
{
action = Layout::Blink;
}
return action;
}
void LampTest::storePhysicalLEDsStates()
{
physicalLEDStatesPriorToLampTest.clear();
for (const auto& path : physicalLEDPaths)
{
auto iter = std::find_if(
skipUpdateLEDs.begin(), skipUpdateLEDs.end(),
[&path](const auto& skipLed) { return skipLed == path; });
if (iter != skipUpdateLEDs.end())
{
// Physical LEDs will be skipped
continue;
}
// Reverse intercept path, Get the name of each member of physical led
// e.g: path = /xyz/openbmc_project/led/physical/front_fan
// name = front_fan
sdbusplus::message::object_path object_path(path);
auto name = object_path.filename();
if (name.empty())
{
lg2::error(
"Failed to get the name of member of physical LED path, PATH = {PATH}, NAME = {NAME}",
"PATH", path, "NAME", name);
continue;
}
std::string state{};
uint16_t period{};
uint8_t dutyOn{};
try
{
auto properties = dBusHandler.getAllProperties(path, PHY_LED_IFACE);
state = std::get<std::string>(properties["State"]);
period = std::get<uint16_t>(properties["Period"]);
dutyOn = std::get<uint8_t>(properties["DutyOn"]);
}
catch (const sdbusplus::exception::exception& e)
{
lg2::error(
"Failed to get All properties, ERROR = {ERROR}, PATH = {PATH}",
"ERROR", e, "PATH", path);
continue;
}
phosphor::led::Layout::Action action = getActionFromString(state);
if (action != phosphor::led::Layout::Off)
{
phosphor::led::Layout::LedAction ledAction{
name, action, dutyOn, period, phosphor::led::Layout::On};
physicalLEDStatesPriorToLampTest.emplace(ledAction);
}
}
}
void LampTest::start()
{
if (isLampTestRunning)
{
// reset the timer and then return
timer.restart(std::chrono::seconds(LAMP_TEST_TIMEOUT_IN_SECS));
return;
}
// Get paths of all the Physical LED objects
physicalLEDPaths = dBusHandler.getSubTreePaths(PHY_LED_PATH, PHY_LED_IFACE);
// Get physical LEDs states before lamp test
storePhysicalLEDsStates();
// restart lamp test, it contains initiate or reset the timer.
timer.restart(std::chrono::seconds(LAMP_TEST_TIMEOUT_IN_SECS));
isLampTestRunning = true;
// Notify PHYP to start the lamp test
doHostLampTest(true);
// Set all the Physical action to On for lamp test
for (const auto& path : physicalLEDPaths)
{
auto iter =
std::find_if(skipUpdateLEDs.begin(), skipUpdateLEDs.end(),
[&path](const auto& skip) { return skip == path; });
if (iter != skipUpdateLEDs.end())
{
// Skip update physical path
continue;
}
manager.drivePhysicalLED(path, Layout::Action::On, 0, 0);
}
}
void LampTest::timeOutHandler()
{
// set the Asserted property of lamp test to false
if (!groupObj)
{
lg2::error("the Group object is nullptr");
throw std::runtime_error("the Group object is nullptr");
}
groupObj->asserted(false);
}
void LampTest::requestHandler(Group* group, bool value)
{
if (groupObj == NULL)
{
groupObj = std::move(group);
}
if (value)
{
start();
}
else
{
stop();
}
}
void LampTest::restorePhysicalLedStates()
{
// restore physical LEDs states before lamp test
Manager::group ledsDeAssert{};
manager.driveLEDs(physicalLEDStatesPriorToLampTest, ledsDeAssert);
physicalLEDStatesPriorToLampTest.clear();
// restore physical LEDs states during lamp test
while (!updatedLEDsDuringLampTest.empty())
{
auto& [ledsAssert, ledsDeAssert] = updatedLEDsDuringLampTest.front();
manager.driveLEDs(ledsAssert, ledsDeAssert);
updatedLEDsDuringLampTest.pop();
}
}
void LampTest::doHostLampTest(bool value)
{
try
{
PropertyValue assertedValue{value};
dBusHandler.setProperty(HOST_LAMP_TEST_OBJECT,
"xyz.openbmc_project.Led.Group", "Asserted",
assertedValue);
}
catch (const sdbusplus::exception::exception& e)
{
lg2::error(
"Failed to set Asserted property, ERROR = {ERROR}, PATH = {PATH}",
"ERROR", e, "PATH", std::string(HOST_LAMP_TEST_OBJECT));
}
}
void LampTest::getPhysicalLEDNamesFromJson(const fs::path& path)
{
if (!fs::exists(path) || fs::is_empty(path))
{
lg2::info("The file does not exist or is empty, FILE_PATH = {PATH}",
"PATH", path);
return;
}
try
{
std::ifstream jsonFile(path);
auto json = Json::parse(jsonFile);
// define the default JSON as empty
const std::vector<std::string> empty{};
auto forceLEDs = json.value("forceLEDs", empty);
for (auto& member : forceLEDs)
{
forceUpdateLEDs.push_back(PHY_LED_PATH + member);
}
auto skipLEDs = json.value("skipLEDs", empty);
for (auto& member : skipLEDs)
{
skipUpdateLEDs.push_back(PHY_LED_PATH + member);
}
}
catch (const std::exception& e)
{
lg2::error(
"Failed to parse config file, ERROR = {ERROR}, FILE_PATH = {PATH}",
"ERROR", e, "PATH", path);
}
return;
}
} // namespace led
} // namespace phosphor