blob: 04398e425982eaa0e2f79f0d78bf5176b4ada113 [file] [log] [blame]
Patrick Venture91ac8d32018-11-01 17:03:22 -07001#include "manager.hpp"
2
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +05303#include <algorithm>
Patrick Venture91ac8d32018-11-01 17:03:22 -07004#include <iostream>
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>
Patrick Venture91ac8d32018-11-01 17:03:22 -07007#include <string>
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +05308#include <xyz/openbmc_project/Led/Physical/server.hpp>
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +05309namespace phosphor
10{
11namespace led
12{
13
14// Assert -or- De-assert
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053015bool Manager::setGroupState(const std::string& path, bool assert,
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053016 group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053017{
18 if (assert)
19 {
20 assertedGroups.insert(&ledMap.at(path));
21 }
22 else
23 {
24 auto search = assertedGroups.find(&ledMap.at(path));
25 if (search != assertedGroups.end())
26 {
27 assertedGroups.erase(&ledMap.at(path));
28 }
29 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053030
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053031 // This will contain the union of what's already in the asserted group
Patrick Venture91ac8d32018-11-01 17:03:22 -070032 group desiredState{};
33 for (const auto& grp : assertedGroups)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053034 {
35 desiredState.insert(grp->cbegin(), grp->cend());
36 }
37
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053038 // Find difference between Combined and Desired to identify
39 // which LEDs are getting altered
Patrick Venture91ac8d32018-11-01 17:03:22 -070040 group transient{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053041 std::set_difference(combinedState.begin(), combinedState.end(),
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053042 desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070043 std::inserter(transient, transient.begin()), ledComp);
44 if (transient.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053045 {
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053046 // Find common LEDs between transient and Desired to know if some LEDs
47 // are changing state and not really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070048 group ledsTransient{};
49 std::set_intersection(
50 transient.begin(), transient.end(), desiredState.begin(),
51 desiredState.end(),
52 std::inserter(ledsTransient, ledsTransient.begin()), ledLess);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053053
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053054 // Find difference between above 2 to identify those LEDs which are
55 // really getting DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070056 std::set_difference(transient.begin(), transient.end(),
57 ledsTransient.begin(), ledsTransient.end(),
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053058 std::inserter(ledsDeAssert, ledsDeAssert.begin()),
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053059 ledLess);
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053060
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053061 // Remove the elements from Current that are being DeAsserted.
Patrick Venture91ac8d32018-11-01 17:03:22 -070062 if (ledsDeAssert.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053063 {
64 // Power off LEDs that are to be really DeAsserted
Patrick Venture91ac8d32018-11-01 17:03:22 -070065 for (auto& it : ledsDeAssert)
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053066 {
67 // Update LEDs in "physically asserted" set by removing those
68 // LEDs which are De-Asserted
69 auto found = currentState.find(it);
70 if (found != currentState.end())
71 {
72 currentState.erase(found);
73 }
74 }
75 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053076 }
77
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053078 // Now LEDs that are to be Asserted. These could either be fresh asserts
79 // -or- change between [On]<-->[Blink]
Patrick Venture91ac8d32018-11-01 17:03:22 -070080 group temp{};
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053081 std::unique_copy(desiredState.begin(), desiredState.end(),
Patrick Venture91ac8d32018-11-01 17:03:22 -070082 std::inserter(temp, temp.begin()), ledEqual);
83 if (temp.size())
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053084 {
85 // Find difference between [desired to be Asserted] and those LEDs
86 // that are physically asserted currently.
Patrick Venture91ac8d32018-11-01 17:03:22 -070087 std::set_difference(
88 temp.begin(), temp.end(), currentState.begin(), currentState.end(),
89 std::inserter(ledsAssert, ledsAssert.begin()), ledComp);
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053090 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053091
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +053092 // Update the current actual and desired(the virtual actual)
93 currentState = std::move(temp);
94 combinedState = std::move(desiredState);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053095
96 // If we survive, then set the state accordingly.
97 return assert;
98}
99
100/** @brief Run through the map and apply action on the LEDs */
Vishwanatha Subbanna4b000d82017-05-03 18:44:16 +0530101void Manager::driveLEDs(group& ledsAssert, group& ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530102{
Alexander Soldatovf3c03412018-04-12 14:40:23 +0300103 using namespace phosphor::logging;
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530104 // Map of physical LED dbus paths to their Service providers
105 populateObjectMap();
106
107 if (phyLeds.empty())
108 {
109 // Error message is inside the map construction logic.
110 return;
111 }
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530112
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530113 // This order of LED operation is important.
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530114 if (ledsDeAssert.size())
115 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700116 for (const auto& it : ledsDeAssert)
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530117 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530118 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700119 log<level::DEBUG>("De-Asserting LED",
120 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800121 drivePhysicalLED(objPath, Layout::Action::Off, it.dutyOn,
122 it.period);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530123 }
124 }
125
Patrick Venture91ac8d32018-11-01 17:03:22 -0700126 if (ledsAssert.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530127 {
Patrick Venture91ac8d32018-11-01 17:03:22 -0700128 for (const auto& it : ledsAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530129 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530130 std::string objPath = std::string(PHY_LED_PATH) + it.name;
Patrick Venture91ac8d32018-11-01 17:03:22 -0700131 log<level::DEBUG>("Asserting LED",
132 entry("NAME=%s", it.name.c_str()));
tony lee6fd9e442019-04-23 09:09:15 +0800133 drivePhysicalLED(objPath, it.action, it.dutyOn, it.period);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530134 }
135 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530136 return;
137}
138
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530139// Calls into driving physical LED post choosing the action
140void Manager::drivePhysicalLED(const std::string& objPath,
tony lee6fd9e442019-04-23 09:09:15 +0800141 Layout::Action action, uint8_t dutyOn,
142 const uint16_t period)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530143{
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530144 using namespace phosphor::logging;
145
146 auto service = phyLeds.find(objPath);
147 if (service == phyLeds.end() || service->second.empty())
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530148 {
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530149 log<level::ERR>("No service providers for physical LED",
Patrick Venture91ac8d32018-11-01 17:03:22 -0700150 entry("PATH=%s", objPath.c_str()));
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530151 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530152 }
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530153
Patrick Venture91ac8d32018-11-01 17:03:22 -0700154 // If Blink, set its property
155 if (action == Layout::Action::Blink)
156 {
157 drivePhysicalLED(service->second, objPath, "DutyOn", dutyOn);
tony lee6fd9e442019-04-23 09:09:15 +0800158 drivePhysicalLED(service->second, objPath, "Period", period);
Patrick Venture91ac8d32018-11-01 17:03:22 -0700159 }
160 drivePhysicalLED(service->second, objPath, "State",
161 getPhysicalAction(action));
162 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530163}
164
165/** @brief Returns action string based on enum */
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530166std::string Manager::getPhysicalAction(Layout::Action action)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530167{
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530168 namespace server = sdbusplus::xyz::openbmc_project::Led::server;
169
170 // TODO: openbmc/phosphor-led-manager#5
171 // Somehow need to use the generated Action enum than giving one
172 // in ledlayout.
Patrick Venture91ac8d32018-11-01 17:03:22 -0700173 if (action == Layout::Action::On)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530174 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530175 return server::convertForMessage(server::Physical::Action::On);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530176 }
Patrick Venture91ac8d32018-11-01 17:03:22 -0700177 else if (action == Layout::Action::Blink)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530178 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530179 return server::convertForMessage(server::Physical::Action::Blink);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530180 }
181 else
182 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530183 return server::convertForMessage(server::Physical::Action::Off);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530184 }
185}
186
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530187/** Populates a map with physical LED paths to its service providers */
188void Manager::populateObjectMap()
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530189{
190 using namespace phosphor::logging;
191
192 // Mapper dbus constructs
Patrick Venture91ac8d32018-11-01 17:03:22 -0700193 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
194 constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
195 constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530196
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530197 // Needed to be passed to get the SubTree level
198 auto depth = 0;
199
200 // Clean start
201 phyLeds.clear();
202
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530203 // Make a mapper call
204 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530205 MAPPER_IFACE, "GetSubTree");
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530206 // Cook rest of the things.
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530207 mapperCall.append(PHY_LED_PATH);
208 mapperCall.append(depth);
209 mapperCall.append(std::vector<std::string>({PHY_LED_IFACE}));
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530210
211 auto reply = bus.call(mapperCall);
212 if (reply.is_method_error())
213 {
214 // Its okay if we do not see a corresponding physical LED.
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530215 log<level::INFO>("Error looking up Physical LED services",
Patrick Venture91ac8d32018-11-01 17:03:22 -0700216 entry("PATH=%s", PHY_LED_PATH));
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530217 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530218 }
219
220 // Response by mapper in the case of success
Patrick Venture91ac8d32018-11-01 17:03:22 -0700221 std::map<std::string, std::map<std::string, std::vector<std::string>>>
222 objectTree;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530223
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530224 // This is the dict of object paths - service names - interfaces
William A. Kennington III151122a2018-05-15 12:00:32 -0700225 try
226 {
227 reply.read(objectTree);
228 }
229 catch (const sdbusplus::exception::SdBusError& e)
230 {
231 log<level::ERR>("Failed to parse Physical LED service lookup",
232 entry("ERROR=%s", e.what()),
233 entry("REPLY_SIG=%s", reply.get_signature()));
234 return;
235 }
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530236 if (objectTree.empty())
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530237 {
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530238 log<level::INFO>("Physical LED lookup did not return any services",
Patrick Venture91ac8d32018-11-01 17:03:22 -0700239 entry("PATH=%s", PHY_LED_PATH));
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530240 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530241 }
242
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530243 // Now construct our path -> Service name map.
244 for (const auto& iter : objectTree)
245 {
246 phyLeds.emplace(iter.first, iter.second.begin()->first);
247 }
248 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530249}
250
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530251} // namespace led
252} // namespace phosphor