blob: c3c142f06bc16f6ce67c0f146c7d69b222278ced [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
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053017// Assert -or- De-assert
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053018bool Manager::setGroupState(const std::string& path, bool assert,
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053019 group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053020{
21 if (assert)
22 {
23 assertedGroups.insert(&ledMap.at(path));
24 }
25 else
26 {
27 auto search = assertedGroups.find(&ledMap.at(path));
28 if (search != assertedGroups.end())
29 {
30 assertedGroups.erase(&ledMap.at(path));
31 }
32 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053033
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053034 // This will contain the union of what's already in the asserted group
Patrick Venture91ac8d32018-11-01 17:03:22 -070035 group desiredState{};
36 for (const auto& grp : assertedGroups)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053037 {
38 desiredState.insert(grp->cbegin(), grp->cend());
39 }
40
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053041 // Find difference between Combined and Desired to identify
42 // which LEDs are getting altered
Patrick Venture91ac8d32018-11-01 17:03:22 -070043 group transient{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053044 std::set_difference(combinedState.begin(), combinedState.end(),
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053045 desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070046 std::inserter(transient, transient.begin()), ledComp);
47 if (transient.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053048 {
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053049 // Find common LEDs between transient and Desired to know if some LEDs
50 // are changing state and not really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070051 group ledsTransient{};
52 std::set_intersection(
53 transient.begin(), transient.end(), desiredState.begin(),
54 desiredState.end(),
55 std::inserter(ledsTransient, ledsTransient.begin()), ledLess);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053056
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053057 // Find difference between above 2 to identify those LEDs which are
58 // really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070059 std::set_difference(transient.begin(), transient.end(),
60 ledsTransient.begin(), ledsTransient.end(),
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053061 std::inserter(ledsDeAssert, ledsDeAssert.begin()),
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053062 ledLess);
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053063
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053064 // Remove the elements from Current that are being DeAsserted.
Patrick Venture91ac8d32018-11-01 17:03:22 -070065 if (ledsDeAssert.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053066 {
67 // Power off LEDs that are to be really DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070068 for (auto& it : ledsDeAssert)
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053069 {
70 // Update LEDs in "physically asserted" set by removing those
71 // LEDs which are De-Asserted
72 auto found = currentState.find(it);
73 if (found != currentState.end())
74 {
75 currentState.erase(found);
76 }
77 }
78 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053079 }
80
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053081 // Now LEDs that are to be Asserted. These could either be fresh asserts
82 // -or- change between [On]<-->[Blink]
Patrick Venture91ac8d32018-11-01 17:03:22 -070083 group temp{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053084 std::unique_copy(desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070085 std::inserter(temp, temp.begin()), ledEqual);
86 if (temp.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053087 {
88 // Find difference between [desired to be Asserted] and those LEDs
89 // that are physically asserted currently.
Patrick Venture91ac8d32018-11-01 17:03:22 -070090 std::set_difference(
91 temp.begin(), temp.end(), currentState.begin(), currentState.end(),
92 std::inserter(ledsAssert, ledsAssert.begin()), ledComp);
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053093 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053094
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053095 // Update the current actual and desired(the virtual actual)
96 currentState = std::move(temp);
97 combinedState = std::move(desiredState);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053098
99 // If we survive, then set the state accordingly.
100 return assert;
101}
102
103/** @brief Run through the map and apply action on the LEDs */
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +0530104void Manager::driveLEDs(group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530105{
106 // This order of LED operation is important.
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530107 if (ledsDeAssert.size())
108 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700109 for (const auto& it : ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530110 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530111 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700112 log<level::DEBUG>("De-Asserting LED",
113 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800114 drivePhysicalLED(objPath, Layout::Action::Off, it.dutyOn,
115 it.period);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530116 }
117 }
118
Patrick Venture91ac8d32018-11-01 17:03:22 -0700119 if (ledsAssert.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530120 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700121 for (const auto& it : ledsAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530122 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530123 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700124 log<level::DEBUG>("Asserting LED",
125 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800126 drivePhysicalLED(objPath, it.action, it.dutyOn, it.period);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530127 }
128 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530129 return;
130}
131
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530132// Calls into driving physical LED post choosing the action
133void Manager::drivePhysicalLED(const std::string& objPath,
tony lee6fd9e442019-04-23 09:09:15 +0800134 Layout::Action action, uint8_t dutyOn,
135 const uint16_t period)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530136{
George Liu1c737af2020-10-16 09:07:02 +0800137 try
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530138 {
George Liu1c737af2020-10-16 09:07:02 +0800139 // If Blink, set its property
140 if (action == Layout::Action::Blink)
141 {
142 PropertyValue dutyOnValue{dutyOn};
143 PropertyValue periodValue{period};
144
145 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "DutyOn",
146 dutyOnValue);
147 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "Period",
148 periodValue);
149 }
150
151 PropertyValue actionValue{getPhysicalAction(action)};
152 dBusHandler.setProperty(objPath, PHY_LED_IFACE, "State", actionValue);
153 }
154 catch (const std::exception& e)
155 {
156 log<level::ERR>("Error setting property for physical LED",
157 entry("ERROR=%s", e.what()),
158 entry("OBJECT_PATH=%s", objPath.c_str()));
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530159 }
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530160
Patrick Venture91ac8d32018-11-01 17:03:22 -0700161 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530162}
163
164/** @brief Returns action string based on enum */
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530165std::string Manager::getPhysicalAction(Layout::Action action)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530166{
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530167 namespace server = sdbusplus::xyz::openbmc_project::Led::server;
168
169 // TODO: openbmc/phosphor-led-manager#5
170 // Somehow need to use the generated Action enum than giving one
171 // in ledlayout.
Patrick Venture91ac8d32018-11-01 17:03:22 -0700172 if (action == Layout::Action::On)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530173 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530174 return server::convertForMessage(server::Physical::Action::On);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530175 }
Patrick Venture91ac8d32018-11-01 17:03:22 -0700176 else if (action == Layout::Action::Blink)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530177 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530178 return server::convertForMessage(server::Physical::Action::Blink);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530179 }
180 else
181 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530182 return server::convertForMessage(server::Physical::Action::Off);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530183 }
184}
185
George Liu4c5f5332020-10-10 17:04:28 +0800186// Set OperationalStatus functional according to the asserted state of the group
187void Manager::setOperationalStatus(const std::string& path, bool value) const
188{
189 using namespace phosphor::logging;
190
191 // Get endpoints from the rType
192 std::string fru = path + "/fru_fault";
193
194 // endpoint contains the vector of strings, where each string is a Inventory
195 // D-Bus object that this, associated with this LED Group D-Bus object
196 // pointed to by fru_fault
197 PropertyValue endpoint{};
198
199 try
200 {
201 endpoint = dBusHandler.getProperty(
202 fru, "xyz.openbmc_project.Association", "endpoints");
203 }
204 catch (const sdbusplus::exception::SdBusError& e)
205 {
206 log<level::ERR>("Failed to get endpoints property",
207 entry("ERROR=%s", e.what()),
208 entry("PATH=%s", fru.c_str()));
209 return;
210 }
211
212 auto& endpoints = std::get<std::vector<std::string>>(endpoint);
213 if (endpoints.empty())
214 {
215 return;
216 }
217
218 for (const auto& fruInstancePath : endpoints)
219 {
220 // Set OperationalStatus by fru instance path
221 try
222 {
223 PropertyValue functionalValue{value};
224 dBusHandler.setProperty(
225 fruInstancePath,
226 "xyz.openbmc_project.State.Decorator.OperationalStatus",
227 "Functional", functionalValue);
228 }
229 catch (const sdbusplus::exception::SdBusError& e)
230 {
231 log<level::ERR>("Failed to set Functional property",
232 entry("ERROR=%s", e.what()),
233 entry("PATH=%s", fruInstancePath.c_str()));
234 }
235 }
236}
237
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530238} // namespace led
239} // namespace phosphor