blob: aaf73deb3e024674ca77f067de313530b2f4d7e7 [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
George Liuce4d1c52021-01-25 11:32:37 +080038 // Stop host lamp test
39 doHostLampTest(false);
40
George Liu87fd11c2020-11-23 16:40:14 +080041 // Set all the Physical action to Off
42 for (const auto& path : physicalLEDPaths)
43 {
44 manager.drivePhysicalLED(path, Layout::Action::Off, 0, 0);
45 }
George Liub6151622020-11-23 18:16:18 +080046
47 isLampTestRunning = false;
48 restorePhysicalLedStates();
49}
50
51Layout::Action LampTest::getActionFromString(const std::string& str)
52{
53 Layout::Action action = Layout::Off;
54
55 if (str == "xyz.openbmc_project.Led.Physical.Action.On")
56 {
57 action = Layout::On;
58 }
59 else if (str == "xyz.openbmc_project.Led.Physical.Action.Blink")
60 {
61 action = Layout::Blink;
62 }
63
64 return action;
65}
66
67void LampTest::storePhysicalLEDsStates()
68{
69 physicalLEDStatesPriorToLampTest.clear();
70
71 for (const auto& path : physicalLEDPaths)
72 {
73 // Reverse intercept path, Get the name of each member of physical led
74 // e.g: path = /xyz/openbmc_project/led/physical/front_fan
75 // name = front_fan
76 sdbusplus::message::object_path object_path(path);
77 auto name = object_path.filename();
78 if (name.empty())
79 {
80 log<level::ERR>(
81 "Failed to get the name of member of physical LED path",
82 entry("PATH=%s", path.c_str()), entry("NAME=%s", name.c_str()));
83 continue;
84 }
85
86 std::string state{};
87 uint16_t period{};
88 uint8_t dutyOn{};
89 try
90 {
91 auto properties = dBusHandler.getAllProperties(path, PHY_LED_IFACE);
92
93 state = std::get<std::string>(properties["State"]);
94 period = std::get<uint16_t>(properties["Period"]);
95 dutyOn = std::get<uint8_t>(properties["DutyOn"]);
96 }
97 catch (const sdbusplus::exception::SdBusError& e)
98 {
99 log<level::ERR>("Failed to get All properties",
100 entry("ERROR=%s", e.what()),
101 entry("PATH=%s", path.c_str()));
102 continue;
103 }
104
105 phosphor::led::Layout::Action action = getActionFromString(state);
106 if (action != phosphor::led::Layout::Off)
107 {
108 phosphor::led::Layout::LedAction ledAction{
109 name, action, dutyOn, period, phosphor::led::Layout::On};
110 physicalLEDStatesPriorToLampTest.emplace(ledAction);
111 }
112 }
George Liuc777bef2020-11-23 17:04:21 +0800113}
114
115void LampTest::start()
116{
George Liub6151622020-11-23 18:16:18 +0800117 if (isLampTestRunning)
118 {
119 // reset the timer and then return
120 timer.restart(std::chrono::seconds(LAMP_TEST_TIMEOUT_IN_SECS));
121 return;
122 }
123
George Liu87fd11c2020-11-23 16:40:14 +0800124 // Get paths of all the Physical LED objects
125 physicalLEDPaths = dBusHandler.getSubTreePaths(PHY_LED_PATH, PHY_LED_IFACE);
126
George Liub6151622020-11-23 18:16:18 +0800127 // Get physical LEDs states before lamp test
128 storePhysicalLEDsStates();
129
George Liuc777bef2020-11-23 17:04:21 +0800130 // restart lamp test, it contains initiate or reset the timer.
131 timer.restart(std::chrono::seconds(LAMP_TEST_TIMEOUT_IN_SECS));
George Liub6151622020-11-23 18:16:18 +0800132 isLampTestRunning = true;
George Liu87fd11c2020-11-23 16:40:14 +0800133
George Liuce4d1c52021-01-25 11:32:37 +0800134 // Notify PHYP to start the lamp test
135 doHostLampTest(true);
136
George Liu87fd11c2020-11-23 16:40:14 +0800137 // Set all the Physical action to On for lamp test
138 for (const auto& path : physicalLEDPaths)
139 {
140 manager.drivePhysicalLED(path, Layout::Action::On, 0, 0);
141 }
George Liuc777bef2020-11-23 17:04:21 +0800142}
143
144void LampTest::timeOutHandler()
145{
146 // set the Asserted property of lamp test to false
George Liu87fd11c2020-11-23 16:40:14 +0800147 if (!groupObj)
148 {
149 log<level::ERR>("the Group object is nullptr");
150 throw std::runtime_error("the Group object is nullptr");
151 }
152
153 groupObj->asserted(false);
George Liuc777bef2020-11-23 17:04:21 +0800154}
155
George Liu87fd11c2020-11-23 16:40:14 +0800156void LampTest::requestHandler(Group* group, bool value)
George Liuc777bef2020-11-23 17:04:21 +0800157{
George Liu87fd11c2020-11-23 16:40:14 +0800158 if (groupObj == NULL)
159 {
160 groupObj = std::move(group);
161 }
162
George Liuc777bef2020-11-23 17:04:21 +0800163 if (value)
164 {
165 start();
166 }
167 else
168 {
169 stop();
170 }
171}
172
George Liub6151622020-11-23 18:16:18 +0800173void LampTest::restorePhysicalLedStates()
174{
175 // restore physical LEDs states before lamp test
176 Manager::group savedLEDStatesDeAssert{};
177 manager.driveLEDs(physicalLEDStatesPriorToLampTest, savedLEDStatesDeAssert);
178 physicalLEDStatesPriorToLampTest.clear();
179
180 // restore physical LEDs states during lamp test
181 while (!updatedLEDsDuringLampTest.empty())
182 {
183 auto& [ledsAssert, ledsDeAssert] = updatedLEDsDuringLampTest.front();
184 manager.driveLEDs(ledsAssert, ledsDeAssert);
185 updatedLEDsDuringLampTest.pop();
186 }
187}
188
George Liuce4d1c52021-01-25 11:32:37 +0800189void LampTest::doHostLampTest(bool value)
190{
191 try
192 {
193 PropertyValue assertedValue{value};
194 dBusHandler.setProperty(HOST_LAMP_TEST_OBJECT,
195 "xyz.openbmc_project.Led.Group", "Asserted",
196 assertedValue);
197 }
198 catch (const sdbusplus::exception::SdBusError& e)
199 {
200 log<level::ERR>("Failed to set Asserted property",
201 entry("ERROR=%s", e.what()),
202 entry("PATH=%s", HOST_LAMP_TEST_OBJECT));
203 }
204}
205
George Liuc777bef2020-11-23 17:04:21 +0800206} // namespace led
207} // namespace phosphor