blob: 572ef68242dabea7baaee651c25cec1fde6d3244 [file] [log] [blame]
George Liuc777bef2020-11-23 17:04:21 +08001#include "config.h"
2
3#include "lamptest.hpp"
4
George Liu87fd11c2020-11-23 16:40:14 +08005#include <phosphor-logging/log.hpp>
6
George Liuc777bef2020-11-23 17:04:21 +08007namespace phosphor
8{
9namespace led
10{
11
George Liub6151622020-11-23 18:16:18 +080012using namespace phosphor::logging;
13
14bool LampTest::processLEDUpdates(const Manager::group& ledsAssert,
15 const Manager::group& ledsDeAssert)
16{
17 // If the physical LED status is updated during the lamp test, it should be
18 // saved to Queue, and the queue will be processed after the lamp test is
19 // stopped.
20 if (isLampTestRunning)
21 {
22 updatedLEDsDuringLampTest.emplace(
23 std::make_pair(ledsAssert, ledsDeAssert));
24 return true;
25 }
26 return false;
27}
28
George Liuc777bef2020-11-23 17:04:21 +080029void LampTest::stop()
30{
George Liub6151622020-11-23 18:16:18 +080031 if (!isLampTestRunning)
32 {
33 return;
34 }
35
George Liuc777bef2020-11-23 17:04:21 +080036 timer.setEnabled(false);
George Liu87fd11c2020-11-23 16:40:14 +080037
38 // Set all the Physical action to Off
39 for (const auto& path : physicalLEDPaths)
40 {
41 manager.drivePhysicalLED(path, Layout::Action::Off, 0, 0);
42 }
George Liub6151622020-11-23 18:16:18 +080043
44 isLampTestRunning = false;
45 restorePhysicalLedStates();
46}
47
48Layout::Action LampTest::getActionFromString(const std::string& str)
49{
50 Layout::Action action = Layout::Off;
51
52 if (str == "xyz.openbmc_project.Led.Physical.Action.On")
53 {
54 action = Layout::On;
55 }
56 else if (str == "xyz.openbmc_project.Led.Physical.Action.Blink")
57 {
58 action = Layout::Blink;
59 }
60
61 return action;
62}
63
64void LampTest::storePhysicalLEDsStates()
65{
66 physicalLEDStatesPriorToLampTest.clear();
67
68 for (const auto& path : physicalLEDPaths)
69 {
70 // Reverse intercept path, Get the name of each member of physical led
71 // e.g: path = /xyz/openbmc_project/led/physical/front_fan
72 // name = front_fan
73 sdbusplus::message::object_path object_path(path);
74 auto name = object_path.filename();
75 if (name.empty())
76 {
77 log<level::ERR>(
78 "Failed to get the name of member of physical LED path",
79 entry("PATH=%s", path.c_str()), entry("NAME=%s", name.c_str()));
80 continue;
81 }
82
83 std::string state{};
84 uint16_t period{};
85 uint8_t dutyOn{};
86 try
87 {
88 auto properties = dBusHandler.getAllProperties(path, PHY_LED_IFACE);
89
90 state = std::get<std::string>(properties["State"]);
91 period = std::get<uint16_t>(properties["Period"]);
92 dutyOn = std::get<uint8_t>(properties["DutyOn"]);
93 }
94 catch (const sdbusplus::exception::SdBusError& e)
95 {
96 log<level::ERR>("Failed to get All properties",
97 entry("ERROR=%s", e.what()),
98 entry("PATH=%s", path.c_str()));
99 continue;
100 }
101
102 phosphor::led::Layout::Action action = getActionFromString(state);
103 if (action != phosphor::led::Layout::Off)
104 {
105 phosphor::led::Layout::LedAction ledAction{
106 name, action, dutyOn, period, phosphor::led::Layout::On};
107 physicalLEDStatesPriorToLampTest.emplace(ledAction);
108 }
109 }
George Liuc777bef2020-11-23 17:04:21 +0800110}
111
112void LampTest::start()
113{
George Liub6151622020-11-23 18:16:18 +0800114 if (isLampTestRunning)
115 {
116 // reset the timer and then return
117 timer.restart(std::chrono::seconds(LAMP_TEST_TIMEOUT_IN_SECS));
118 return;
119 }
120
George Liu87fd11c2020-11-23 16:40:14 +0800121 // Get paths of all the Physical LED objects
122 physicalLEDPaths = dBusHandler.getSubTreePaths(PHY_LED_PATH, PHY_LED_IFACE);
123
George Liub6151622020-11-23 18:16:18 +0800124 // Get physical LEDs states before lamp test
125 storePhysicalLEDsStates();
126
George Liuc777bef2020-11-23 17:04:21 +0800127 // restart lamp test, it contains initiate or reset the timer.
128 timer.restart(std::chrono::seconds(LAMP_TEST_TIMEOUT_IN_SECS));
George Liub6151622020-11-23 18:16:18 +0800129 isLampTestRunning = true;
George Liu87fd11c2020-11-23 16:40:14 +0800130
131 // Set all the Physical action to On for lamp test
132 for (const auto& path : physicalLEDPaths)
133 {
134 manager.drivePhysicalLED(path, Layout::Action::On, 0, 0);
135 }
George Liuc777bef2020-11-23 17:04:21 +0800136}
137
138void LampTest::timeOutHandler()
139{
140 // set the Asserted property of lamp test to false
George Liu87fd11c2020-11-23 16:40:14 +0800141 if (!groupObj)
142 {
143 log<level::ERR>("the Group object is nullptr");
144 throw std::runtime_error("the Group object is nullptr");
145 }
146
147 groupObj->asserted(false);
George Liuc777bef2020-11-23 17:04:21 +0800148}
149
George Liu87fd11c2020-11-23 16:40:14 +0800150void LampTest::requestHandler(Group* group, bool value)
George Liuc777bef2020-11-23 17:04:21 +0800151{
George Liu87fd11c2020-11-23 16:40:14 +0800152 if (groupObj == NULL)
153 {
154 groupObj = std::move(group);
155 }
156
George Liuc777bef2020-11-23 17:04:21 +0800157 if (value)
158 {
159 start();
160 }
161 else
162 {
163 stop();
164 }
165}
166
George Liub6151622020-11-23 18:16:18 +0800167void LampTest::restorePhysicalLedStates()
168{
169 // restore physical LEDs states before lamp test
170 Manager::group savedLEDStatesDeAssert{};
171 manager.driveLEDs(physicalLEDStatesPriorToLampTest, savedLEDStatesDeAssert);
172 physicalLEDStatesPriorToLampTest.clear();
173
174 // restore physical LEDs states during lamp test
175 while (!updatedLEDsDuringLampTest.empty())
176 {
177 auto& [ledsAssert, ledsDeAssert] = updatedLEDsDuringLampTest.front();
178 manager.driveLEDs(ledsAssert, ledsDeAssert);
179 updatedLEDsDuringLampTest.pop();
180 }
181}
182
George Liuc777bef2020-11-23 17:04:21 +0800183} // namespace led
184} // namespace phosphor