blob: a1c4175575f64a11ccff1326394388945a63d26a [file] [log] [blame]
Patrick Venture91ac8d32018-11-01 17:03:22 -07001#include "manager.hpp"
2
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +05303#include <phosphor-logging/log.hpp>
William A. Kennington III151122a2018-05-15 12:00:32 -07004#include <sdbusplus/exception.hpp>
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +05305#include <xyz/openbmc_project/Led/Physical/server.hpp>
George Liua6c18f82020-06-22 10:50:04 +08006
7#include <algorithm>
8#include <iostream>
9#include <string>
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053010namespace phosphor
11{
12namespace led
13{
14
George Liu1c737af2020-10-16 09:07:02 +080015using namespace phosphor::logging;
16
17static constexpr auto PHY_LED_PATH = "/xyz/openbmc_project/led/physical/";
18static constexpr auto PHY_LED_IFACE = "xyz.openbmc_project.Led.Physical";
19
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053020// Assert -or- De-assert
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053021bool Manager::setGroupState(const std::string& path, bool assert,
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053022 group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053023{
24 if (assert)
25 {
26 assertedGroups.insert(&ledMap.at(path));
27 }
28 else
29 {
30 auto search = assertedGroups.find(&ledMap.at(path));
31 if (search != assertedGroups.end())
32 {
33 assertedGroups.erase(&ledMap.at(path));
34 }
35 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053036
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053037 // This will contain the union of what's already in the asserted group
Patrick Venture91ac8d32018-11-01 17:03:22 -070038 group desiredState{};
39 for (const auto& grp : assertedGroups)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053040 {
41 desiredState.insert(grp->cbegin(), grp->cend());
42 }
43
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053044 // Find difference between Combined and Desired to identify
45 // which LEDs are getting altered
Patrick Venture91ac8d32018-11-01 17:03:22 -070046 group transient{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053047 std::set_difference(combinedState.begin(), combinedState.end(),
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053048 desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070049 std::inserter(transient, transient.begin()), ledComp);
50 if (transient.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053051 {
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053052 // Find common LEDs between transient and Desired to know if some LEDs
53 // are changing state and not really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070054 group ledsTransient{};
55 std::set_intersection(
56 transient.begin(), transient.end(), desiredState.begin(),
57 desiredState.end(),
58 std::inserter(ledsTransient, ledsTransient.begin()), ledLess);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053059
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053060 // Find difference between above 2 to identify those LEDs which are
61 // really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070062 std::set_difference(transient.begin(), transient.end(),
63 ledsTransient.begin(), ledsTransient.end(),
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053064 std::inserter(ledsDeAssert, ledsDeAssert.begin()),
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053065 ledLess);
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053066
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053067 // Remove the elements from Current that are being DeAsserted.
Patrick Venture91ac8d32018-11-01 17:03:22 -070068 if (ledsDeAssert.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053069 {
70 // Power off LEDs that are to be really DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070071 for (auto& it : ledsDeAssert)
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053072 {
73 // Update LEDs in "physically asserted" set by removing those
74 // LEDs which are De-Asserted
75 auto found = currentState.find(it);
76 if (found != currentState.end())
77 {
78 currentState.erase(found);
79 }
80 }
81 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053082 }
83
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053084 // Now LEDs that are to be Asserted. These could either be fresh asserts
85 // -or- change between [On]<-->[Blink]
Patrick Venture91ac8d32018-11-01 17:03:22 -070086 group temp{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053087 std::unique_copy(desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070088 std::inserter(temp, temp.begin()), ledEqual);
89 if (temp.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053090 {
91 // Find difference between [desired to be Asserted] and those LEDs
92 // that are physically asserted currently.
Patrick Venture91ac8d32018-11-01 17:03:22 -070093 std::set_difference(
94 temp.begin(), temp.end(), currentState.begin(), currentState.end(),
95 std::inserter(ledsAssert, ledsAssert.begin()), ledComp);
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053096 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053097
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053098 // Update the current actual and desired(the virtual actual)
99 currentState = std::move(temp);
100 combinedState = std::move(desiredState);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530101
102 // If we survive, then set the state accordingly.
103 return assert;
104}
105
106/** @brief Run through the map and apply action on the LEDs */
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +0530107void Manager::driveLEDs(group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530108{
109 // This order of LED operation is important.
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530110 if (ledsDeAssert.size())
111 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700112 for (const auto& it : ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530113 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530114 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700115 log<level::DEBUG>("De-Asserting LED",
116 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800117 drivePhysicalLED(objPath, Layout::Action::Off, it.dutyOn,
118 it.period);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530119 }
120 }
121
Patrick Venture91ac8d32018-11-01 17:03:22 -0700122 if (ledsAssert.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530123 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700124 for (const auto& it : ledsAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530125 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530126 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700127 log<level::DEBUG>("Asserting LED",
128 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800129 drivePhysicalLED(objPath, it.action, it.dutyOn, it.period);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530130 }
131 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530132 return;
133}
134
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530135// Calls into driving physical LED post choosing the action
136void Manager::drivePhysicalLED(const std::string& objPath,
tony lee6fd9e442019-04-23 09:09:15 +0800137 Layout::Action action, uint8_t dutyOn,
138 const uint16_t period)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530139{
George Liu1c737af2020-10-16 09:07:02 +0800140 try
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530141 {
George Liu1c737af2020-10-16 09:07:02 +0800142 // If Blink, set its property
143 if (action == Layout::Action::Blink)
144 {
145 PropertyValue dutyOnValue{dutyOn};
146 PropertyValue periodValue{period};
147
148 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "DutyOn",
149 dutyOnValue);
150 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "Period",
151 periodValue);
152 }
153
154 PropertyValue actionValue{getPhysicalAction(action)};
155 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "State", actionValue);
156 }
157 catch (const std::exception& e)
158 {
159 log<level::ERR>("Error setting property for physical LED",
160 entry("ERROR=%s", e.what()),
161 entry("OBJECT_PATH=%s", objPath.c_str()));
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530162 }
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530163
Patrick Venture91ac8d32018-11-01 17:03:22 -0700164 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530165}
166
167/** @brief Returns action string based on enum */
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530168std::string Manager::getPhysicalAction(Layout::Action action)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530169{
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530170 namespace server = sdbusplus::xyz::openbmc_project::Led::server;
171
172 // TODO: openbmc/phosphor-led-manager#5
173 // Somehow need to use the generated Action enum than giving one
174 // in ledlayout.
Patrick Venture91ac8d32018-11-01 17:03:22 -0700175 if (action == Layout::Action::On)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530176 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530177 return server::convertForMessage(server::Physical::Action::On);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530178 }
Patrick Venture91ac8d32018-11-01 17:03:22 -0700179 else if (action == Layout::Action::Blink)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530180 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530181 return server::convertForMessage(server::Physical::Action::Blink);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530182 }
183 else
184 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530185 return server::convertForMessage(server::Physical::Action::Off);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530186 }
187}
188
George Liu4c5f5332020-10-10 17:04:28 +0800189// Set OperationalStatus functional according to the asserted state of the group
190void Manager::setOperationalStatus(const std::string& path, bool value) const
191{
192 using namespace phosphor::logging;
193
194 // Get endpoints from the rType
195 std::string fru = path + "/fru_fault";
196
197 // endpoint contains the vector of strings, where each string is a Inventory
198 // D-Bus object that this, associated with this LED Group D-Bus object
199 // pointed to by fru_fault
200 PropertyValue endpoint{};
201
202 try
203 {
204 endpoint = dBusHandler.getProperty(
205 fru, "xyz.openbmc_project.Association", "endpoints");
206 }
207 catch (const sdbusplus::exception::SdBusError& e)
208 {
209 log<level::ERR>("Failed to get endpoints property",
210 entry("ERROR=%s", e.what()),
211 entry("PATH=%s", fru.c_str()));
212 return;
213 }
214
215 auto& endpoints = std::get<std::vector<std::string>>(endpoint);
216 if (endpoints.empty())
217 {
218 return;
219 }
220
221 for (const auto& fruInstancePath : endpoints)
222 {
223 // Set OperationalStatus by fru instance path
224 try
225 {
226 PropertyValue functionalValue{value};
227 dBusHandler.setProperty(
228 fruInstancePath,
229 "xyz.openbmc_project.State.Decorator.OperationalStatus",
230 "Functional", functionalValue);
231 }
232 catch (const sdbusplus::exception::SdBusError& e)
233 {
234 log<level::ERR>("Failed to set Functional property",
235 entry("ERROR=%s", e.what()),
236 entry("PATH=%s", fruInstancePath.c_str()));
237 }
238 }
239}
240
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530241} // namespace led
242} // namespace phosphor