blob: 6219091324f35f0e9f4375e80557757901c9e9d5 [file] [log] [blame]
George Liub6151622020-11-23 18:16:18 +08001#include "config.h"
2
Patrick Venture91ac8d32018-11-01 17:03:22 -07003#include "manager.hpp"
4
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +05305#include <phosphor-logging/log.hpp>
William A. Kennington III151122a2018-05-15 12:00:32 -07006#include <sdbusplus/exception.hpp>
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +05307#include <xyz/openbmc_project/Led/Physical/server.hpp>
George Liua6c18f82020-06-22 10:50:04 +08008
9#include <algorithm>
10#include <iostream>
11#include <string>
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053012namespace phosphor
13{
14namespace led
15{
16
George Liu1c737af2020-10-16 09:07:02 +080017using namespace phosphor::logging;
18
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053019// Assert -or- De-assert
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053020bool Manager::setGroupState(const std::string& path, bool assert,
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053021 group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053022{
23 if (assert)
24 {
25 assertedGroups.insert(&ledMap.at(path));
26 }
27 else
28 {
29 auto search = assertedGroups.find(&ledMap.at(path));
30 if (search != assertedGroups.end())
31 {
32 assertedGroups.erase(&ledMap.at(path));
33 }
34 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053035
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053036 // This will contain the union of what's already in the asserted group
Patrick Venture91ac8d32018-11-01 17:03:22 -070037 group desiredState{};
38 for (const auto& grp : assertedGroups)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053039 {
40 desiredState.insert(grp->cbegin(), grp->cend());
41 }
42
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053043 // Find difference between Combined and Desired to identify
44 // which LEDs are getting altered
Patrick Venture91ac8d32018-11-01 17:03:22 -070045 group transient{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053046 std::set_difference(combinedState.begin(), combinedState.end(),
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053047 desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070048 std::inserter(transient, transient.begin()), ledComp);
49 if (transient.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053050 {
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053051 // Find common LEDs between transient and Desired to know if some LEDs
52 // are changing state and not really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070053 group ledsTransient{};
54 std::set_intersection(
55 transient.begin(), transient.end(), desiredState.begin(),
56 desiredState.end(),
57 std::inserter(ledsTransient, ledsTransient.begin()), ledLess);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053058
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053059 // Find difference between above 2 to identify those LEDs which are
60 // really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070061 std::set_difference(transient.begin(), transient.end(),
62 ledsTransient.begin(), ledsTransient.end(),
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053063 std::inserter(ledsDeAssert, ledsDeAssert.begin()),
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053064 ledLess);
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053065
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053066 // Remove the elements from Current that are being DeAsserted.
Patrick Venture91ac8d32018-11-01 17:03:22 -070067 if (ledsDeAssert.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053068 {
69 // Power off LEDs that are to be really DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070070 for (auto& it : ledsDeAssert)
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053071 {
72 // Update LEDs in "physically asserted" set by removing those
73 // LEDs which are De-Asserted
74 auto found = currentState.find(it);
75 if (found != currentState.end())
76 {
77 currentState.erase(found);
78 }
79 }
80 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053081 }
82
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053083 // Now LEDs that are to be Asserted. These could either be fresh asserts
84 // -or- change between [On]<-->[Blink]
Patrick Venture91ac8d32018-11-01 17:03:22 -070085 group temp{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053086 std::unique_copy(desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070087 std::inserter(temp, temp.begin()), ledEqual);
88 if (temp.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053089 {
90 // Find difference between [desired to be Asserted] and those LEDs
91 // that are physically asserted currently.
Patrick Venture91ac8d32018-11-01 17:03:22 -070092 std::set_difference(
93 temp.begin(), temp.end(), currentState.begin(), currentState.end(),
94 std::inserter(ledsAssert, ledsAssert.begin()), ledComp);
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053095 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053096
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053097 // Update the current actual and desired(the virtual actual)
98 currentState = std::move(temp);
99 combinedState = std::move(desiredState);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530100
101 // If we survive, then set the state accordingly.
102 return assert;
103}
104
George Liub6151622020-11-23 18:16:18 +0800105void Manager::setLampTestCallBack(
106 std::function<bool(group& ledsAssert, group& ledsDeAssert)> callBack)
107{
108 lampTestCallBack = callBack;
109}
110
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530111/** @brief Run through the map and apply action on the LEDs */
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +0530112void Manager::driveLEDs(group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530113{
George Liub6151622020-11-23 18:16:18 +0800114#ifdef USE_LAMP_TEST
115 // Use the lampTestCallBack method and trigger the callback method in the
116 // lamp test(processLEDUpdates), in this way, all lamp test operations
117 // are performed in the lamp test class.
118 if (lampTestCallBack(ledsAssert, ledsDeAssert))
119 {
120 return;
121 }
122#endif
123
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530124 // This order of LED operation is important.
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530125 if (ledsDeAssert.size())
126 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700127 for (const auto& it : ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530128 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530129 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700130 log<level::DEBUG>("De-Asserting LED",
131 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800132 drivePhysicalLED(objPath, Layout::Action::Off, it.dutyOn,
133 it.period);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530134 }
135 }
136
Patrick Venture91ac8d32018-11-01 17:03:22 -0700137 if (ledsAssert.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530138 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700139 for (const auto& it : ledsAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530140 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530141 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700142 log<level::DEBUG>("Asserting LED",
143 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800144 drivePhysicalLED(objPath, it.action, it.dutyOn, it.period);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530145 }
146 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530147 return;
148}
149
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530150// Calls into driving physical LED post choosing the action
151void Manager::drivePhysicalLED(const std::string& objPath,
tony lee6fd9e442019-04-23 09:09:15 +0800152 Layout::Action action, uint8_t dutyOn,
153 const uint16_t period)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530154{
George Liu1c737af2020-10-16 09:07:02 +0800155 try
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530156 {
George Liu1c737af2020-10-16 09:07:02 +0800157 // If Blink, set its property
158 if (action == Layout::Action::Blink)
159 {
160 PropertyValue dutyOnValue{dutyOn};
161 PropertyValue periodValue{period};
162
163 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "DutyOn",
164 dutyOnValue);
165 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "Period",
166 periodValue);
167 }
168
169 PropertyValue actionValue{getPhysicalAction(action)};
170 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "State", actionValue);
171 }
172 catch (const std::exception& e)
173 {
174 log<level::ERR>("Error setting property for physical LED",
175 entry("ERROR=%s", e.what()),
176 entry("OBJECT_PATH=%s", objPath.c_str()));
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530177 }
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530178
Patrick Venture91ac8d32018-11-01 17:03:22 -0700179 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530180}
181
182/** @brief Returns action string based on enum */
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530183std::string Manager::getPhysicalAction(Layout::Action action)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530184{
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530185 namespace server = sdbusplus::xyz::openbmc_project::Led::server;
186
187 // TODO: openbmc/phosphor-led-manager#5
188 // Somehow need to use the generated Action enum than giving one
189 // in ledlayout.
Patrick Venture91ac8d32018-11-01 17:03:22 -0700190 if (action == Layout::Action::On)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530191 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530192 return server::convertForMessage(server::Physical::Action::On);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530193 }
Patrick Venture91ac8d32018-11-01 17:03:22 -0700194 else if (action == Layout::Action::Blink)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530195 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530196 return server::convertForMessage(server::Physical::Action::Blink);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530197 }
198 else
199 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530200 return server::convertForMessage(server::Physical::Action::Off);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530201 }
202}
203
George Liu4c5f5332020-10-10 17:04:28 +0800204// Set OperationalStatus functional according to the asserted state of the group
205void Manager::setOperationalStatus(const std::string& path, bool value) const
206{
207 using namespace phosphor::logging;
208
209 // Get endpoints from the rType
210 std::string fru = path + "/fru_fault";
211
212 // endpoint contains the vector of strings, where each string is a Inventory
213 // D-Bus object that this, associated with this LED Group D-Bus object
214 // pointed to by fru_fault
215 PropertyValue endpoint{};
216
217 try
218 {
219 endpoint = dBusHandler.getProperty(
220 fru, "xyz.openbmc_project.Association", "endpoints");
221 }
222 catch (const sdbusplus::exception::SdBusError& e)
223 {
224 log<level::ERR>("Failed to get endpoints property",
225 entry("ERROR=%s", e.what()),
226 entry("PATH=%s", fru.c_str()));
227 return;
228 }
229
230 auto& endpoints = std::get<std::vector<std::string>>(endpoint);
231 if (endpoints.empty())
232 {
233 return;
234 }
235
236 for (const auto& fruInstancePath : endpoints)
237 {
238 // Set OperationalStatus by fru instance path
239 try
240 {
241 PropertyValue functionalValue{value};
242 dBusHandler.setProperty(
243 fruInstancePath,
244 "xyz.openbmc_project.State.Decorator.OperationalStatus",
245 "Functional", functionalValue);
246 }
247 catch (const sdbusplus::exception::SdBusError& e)
248 {
249 log<level::ERR>("Failed to set Functional property",
250 entry("ERROR=%s", e.what()),
251 entry("PATH=%s", fruInstancePath.c_str()));
252 }
253 }
254}
255
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530256} // namespace led
257} // namespace phosphor