blob: 4ebc0246d5e36bb6eb196cf6e05b872d38eee3bf [file] [log] [blame]
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +05301#include <iostream>
2#include <string>
3#include <algorithm>
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +05304#include <phosphor-logging/log.hpp>
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +05305#include <xyz/openbmc_project/Led/Physical/server.hpp>
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +05306#include "manager.hpp"
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +05307namespace phosphor
8{
9namespace led
10{
11
12// Assert -or- De-assert
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053013bool Manager::setGroupState(const std::string& path, bool assert,
14 group& ledsAssert, group& ledsDeAssert,
15 group& ledsUpdate)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053016{
17 if (assert)
18 {
19 assertedGroups.insert(&ledMap.at(path));
20 }
21 else
22 {
23 auto search = assertedGroups.find(&ledMap.at(path));
24 if (search != assertedGroups.end())
25 {
26 assertedGroups.erase(&ledMap.at(path));
27 }
28 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053029
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053030 // This will contain the union of what's already in the asserted group
31 group desiredState {};
32 for(const auto& grp : assertedGroups)
33 {
34 desiredState.insert(grp->cbegin(), grp->cend());
35 }
36
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053037 // Has the LEDs that are either to be turned off -or- want a new assertion
38 group transient {};
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053039 std::set_difference(currentState.begin(), currentState.end(),
40 desiredState.begin(), desiredState.end(),
Vishwanatha Subbannacd569d22017-05-03 12:46:14 +053041 std::inserter(transient, transient.begin()),
42 ledComp);
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053043 if(transient.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053044 {
45 // We really do not want the Manager to know how a particular LED
46 // transitions from State-A --> State-B and all this must be handled by
47 // the physical LED controller implementation.
48 // So in this case, Manager really does not want to turn off the
49 // LEDs and then turning it back on and let the physical LED controller
50 // handle that.
51
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053052 // If we previously had a FRU in ON state , and then if there was a
53 // request to make it blink, the end state would now be blink.
54 // If we either turn off blink / fault, then we need to go back to its
55 // previous state.
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053056 std::set_intersection(desiredState.begin(), desiredState.end(),
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053057 transient.begin(), transient.end(),
58 std::inserter(ledsUpdate, ledsUpdate.begin()),
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053059 ledComp);
60
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053061 // These LEDs are only to be De-Asserted.
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053062 std::set_difference(transient.begin(), transient.end(),
63 ledsUpdate.begin(), ledsUpdate.end(),
64 std::inserter(ledsDeAssert, ledsDeAssert.begin()),
65 ledComp);
66
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053067 }
68
69 // Turn on these
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053070 std::set_difference(desiredState.begin(), desiredState.end(),
71 currentState.begin(), currentState.end(),
Vishwanatha Subbannacd569d22017-05-03 12:46:14 +053072 std::inserter(ledsAssert, ledsAssert.begin()),
73 ledComp);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053074
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053075
76 // Done.. Save the latest and greatest.
77 currentState = std::move(desiredState);
78
79 // If we survive, then set the state accordingly.
80 return assert;
81}
82
83/** @brief Run through the map and apply action on the LEDs */
84void Manager::driveLEDs(group& ledsAssert, group& ledsDeAssert,
85 group& ledsUpdate)
86{
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +053087 // Map of physical LED dbus paths to their Service providers
88 populateObjectMap();
89
90 if (phyLeds.empty())
91 {
92 // Error message is inside the map construction logic.
93 return;
94 }
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +053095
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053096 // This order of LED operation is important.
97 if (ledsUpdate.size())
98 {
99 std::cout << "Updating LED states between (On <--> Blink)"
100 << std::endl;
101 for (const auto& it: ledsUpdate)
102 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530103 std::string objPath = std::string(PHY_LED_PATH) + it.name;
104 drivePhysicalLED(objPath, it.action, it.dutyOn);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530105 }
106 }
107
108 if (ledsDeAssert.size())
109 {
110 std::cout << "De-Asserting LEDs" << std::endl;
111 for (const auto& it: ledsDeAssert)
112 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530113 std::string objPath = std::string(PHY_LED_PATH) + it.name;
114 drivePhysicalLED(objPath, Layout::Action::Off, it.dutyOn);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530115 }
116 }
117
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +0530118 if(ledsAssert.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530119 {
120 std::cout << "Asserting LEDs" << std::endl;
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +0530121 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;
124 drivePhysicalLED(objPath, it.action, it.dutyOn);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530125 }
126 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530127 return;
128}
129
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530130// Calls into driving physical LED post choosing the action
131void Manager::drivePhysicalLED(const std::string& objPath,
132 Layout::Action action,
133 uint8_t dutyOn)
134{
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530135 using namespace phosphor::logging;
136
137 auto service = phyLeds.find(objPath);
138 if (service == phyLeds.end() || service->second.empty())
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530139 {
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530140 log<level::ERR>("No service providers for physical LED",
141 entry("PATH=%s",objPath.c_str()));
142 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530143 }
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530144
145 // If Blink, set its property
146 if (action == Layout::Action::Blink)
147 {
148 drivePhysicalLED(service->second, objPath, "DutyOn", dutyOn);
149 }
150 drivePhysicalLED(service->second, objPath, "State",
151 getPhysicalAction(action));
152 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530153}
154
155/** @brief Returns action string based on enum */
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530156std::string Manager::getPhysicalAction(Layout::Action action)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530157{
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530158 namespace server = sdbusplus::xyz::openbmc_project::Led::server;
159
160 // TODO: openbmc/phosphor-led-manager#5
161 // Somehow need to use the generated Action enum than giving one
162 // in ledlayout.
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530163 if(action == Layout::Action::On)
164 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530165 return server::convertForMessage(server::Physical::Action::On);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530166 }
167 else if(action == Layout::Action::Blink)
168 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530169 return server::convertForMessage(server::Physical::Action::Blink);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530170 }
171 else
172 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530173 return server::convertForMessage(server::Physical::Action::Off);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530174 }
175}
176
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530177/** Populates a map with physical LED paths to its service providers */
178void Manager::populateObjectMap()
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530179{
180 using namespace phosphor::logging;
181
182 // Mapper dbus constructs
183 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
Leonel Gonzalez76f58342017-03-16 13:47:52 -0500184 constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530185 constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
186
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530187 // Needed to be passed to get the SubTree level
188 auto depth = 0;
189
190 // Clean start
191 phyLeds.clear();
192
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530193 // Make a mapper call
194 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530195 MAPPER_IFACE, "GetSubTree");
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530196 // Cook rest of the things.
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530197 mapperCall.append(PHY_LED_PATH);
198 mapperCall.append(depth);
199 mapperCall.append(std::vector<std::string>({PHY_LED_IFACE}));
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530200
201 auto reply = bus.call(mapperCall);
202 if (reply.is_method_error())
203 {
204 // Its okay if we do not see a corresponding physical LED.
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530205 log<level::INFO>("Error looking up Physical LED services",
206 entry("PATH=%s",PHY_LED_PATH));
207 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530208 }
209
210 // Response by mapper in the case of success
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530211 std::map<std::string, std::map<std::string,
212 std::vector<std::string>>> objectTree;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530213
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530214 // This is the dict of object paths - service names - interfaces
215 reply.read(objectTree);
216 if (objectTree.empty())
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530217 {
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530218 log<level::INFO>("Physical LED lookup did not return any services",
219 entry("PATH=%s",PHY_LED_PATH));
220 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530221 }
222
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530223 // Now construct our path -> Service name map.
224 for (const auto& iter : objectTree)
225 {
226 phyLeds.emplace(iter.first, iter.second.begin()->first);
227 }
228 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530229}
230
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530231} // namespace led
232} // namespace phosphor