blob: 26f00a523e3f9059117d08301eb6b7bfd607eaa1 [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 Subbanna447d0c82016-12-19 14:12:42 +053041 std::inserter(transient, transient.begin()));
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053042 if(transient.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053043 {
44 // We really do not want the Manager to know how a particular LED
45 // transitions from State-A --> State-B and all this must be handled by
46 // the physical LED controller implementation.
47 // So in this case, Manager really does not want to turn off the
48 // LEDs and then turning it back on and let the physical LED controller
49 // handle that.
50
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053051 // If we previously had a FRU in ON state , and then if there was a
52 // request to make it blink, the end state would now be blink.
53 // If we either turn off blink / fault, then we need to go back to its
54 // previous state.
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053055 std::set_intersection(desiredState.begin(), desiredState.end(),
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053056 transient.begin(), transient.end(),
57 std::inserter(ledsUpdate, ledsUpdate.begin()),
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053058 ledComp);
59
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053060 // These LEDs are only to be De-Asserted.
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053061 std::set_difference(transient.begin(), transient.end(),
62 ledsUpdate.begin(), ledsUpdate.end(),
63 std::inserter(ledsDeAssert, ledsDeAssert.begin()),
64 ledComp);
65
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053066 }
67
68 // Turn on these
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053069 std::set_difference(desiredState.begin(), desiredState.end(),
70 currentState.begin(), currentState.end(),
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +053071 std::inserter(ledsAssert, ledsAssert.begin()));
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +053072
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053073
74 // Done.. Save the latest and greatest.
75 currentState = std::move(desiredState);
76
77 // If we survive, then set the state accordingly.
78 return assert;
79}
80
81/** @brief Run through the map and apply action on the LEDs */
82void Manager::driveLEDs(group& ledsAssert, group& ledsDeAssert,
83 group& ledsUpdate)
84{
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +053085 // Map of physical LED dbus paths to their Service providers
86 populateObjectMap();
87
88 if (phyLeds.empty())
89 {
90 // Error message is inside the map construction logic.
91 return;
92 }
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +053093
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053094 // This order of LED operation is important.
95 if (ledsUpdate.size())
96 {
97 std::cout << "Updating LED states between (On <--> Blink)"
98 << std::endl;
99 for (const auto& it: ledsUpdate)
100 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530101 std::string objPath = std::string(PHY_LED_PATH) + it.name;
102 drivePhysicalLED(objPath, it.action, it.dutyOn);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530103 }
104 }
105
106 if (ledsDeAssert.size())
107 {
108 std::cout << "De-Asserting LEDs" << std::endl;
109 for (const auto& it: ledsDeAssert)
110 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530111 std::string objPath = std::string(PHY_LED_PATH) + it.name;
112 drivePhysicalLED(objPath, Layout::Action::Off, it.dutyOn);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530113 }
114 }
115
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +0530116 if(ledsAssert.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530117 {
118 std::cout << "Asserting LEDs" << std::endl;
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +0530119 for (const auto& it: ledsAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530120 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530121 std::string objPath = std::string(PHY_LED_PATH) + it.name;
122 drivePhysicalLED(objPath, it.action, it.dutyOn);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530123 }
124 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530125 return;
126}
127
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530128// Calls into driving physical LED post choosing the action
129void Manager::drivePhysicalLED(const std::string& objPath,
130 Layout::Action action,
131 uint8_t dutyOn)
132{
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530133 using namespace phosphor::logging;
134
135 auto service = phyLeds.find(objPath);
136 if (service == phyLeds.end() || service->second.empty())
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530137 {
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530138 log<level::ERR>("No service providers for physical LED",
139 entry("PATH=%s",objPath.c_str()));
140 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530141 }
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530142
143 // If Blink, set its property
144 if (action == Layout::Action::Blink)
145 {
146 drivePhysicalLED(service->second, objPath, "DutyOn", dutyOn);
147 }
148 drivePhysicalLED(service->second, objPath, "State",
149 getPhysicalAction(action));
150 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530151}
152
153/** @brief Returns action string based on enum */
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530154std::string Manager::getPhysicalAction(Layout::Action action)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530155{
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530156 namespace server = sdbusplus::xyz::openbmc_project::Led::server;
157
158 // TODO: openbmc/phosphor-led-manager#5
159 // Somehow need to use the generated Action enum than giving one
160 // in ledlayout.
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530161 if(action == Layout::Action::On)
162 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530163 return server::convertForMessage(server::Physical::Action::On);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530164 }
165 else if(action == Layout::Action::Blink)
166 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530167 return server::convertForMessage(server::Physical::Action::Blink);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530168 }
169 else
170 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530171 return server::convertForMessage(server::Physical::Action::Off);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530172 }
173}
174
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530175/** Populates a map with physical LED paths to its service providers */
176void Manager::populateObjectMap()
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530177{
178 using namespace phosphor::logging;
179
180 // Mapper dbus constructs
181 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
Leonel Gonzalez76f58342017-03-16 13:47:52 -0500182 constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530183 constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
184
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530185 // Needed to be passed to get the SubTree level
186 auto depth = 0;
187
188 // Clean start
189 phyLeds.clear();
190
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530191 // Make a mapper call
192 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530193 MAPPER_IFACE, "GetSubTree");
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530194 // Cook rest of the things.
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530195 mapperCall.append(PHY_LED_PATH);
196 mapperCall.append(depth);
197 mapperCall.append(std::vector<std::string>({PHY_LED_IFACE}));
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530198
199 auto reply = bus.call(mapperCall);
200 if (reply.is_method_error())
201 {
202 // Its okay if we do not see a corresponding physical LED.
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530203 log<level::INFO>("Error looking up Physical LED services",
204 entry("PATH=%s",PHY_LED_PATH));
205 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530206 }
207
208 // Response by mapper in the case of success
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530209 std::map<std::string, std::map<std::string,
210 std::vector<std::string>>> objectTree;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530211
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530212 // This is the dict of object paths - service names - interfaces
213 reply.read(objectTree);
214 if (objectTree.empty())
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530215 {
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530216 log<level::INFO>("Physical LED lookup did not return any services",
217 entry("PATH=%s",PHY_LED_PATH));
218 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530219 }
220
Vishwanatha Subbannadcc3f382017-03-24 20:15:02 +0530221 // Now construct our path -> Service name map.
222 for (const auto& iter : objectTree)
223 {
224 phyLeds.emplace(iter.first, iter.second.begin()->first);
225 }
226 return;
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530227}
228
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530229} // namespace led
230} // namespace phosphor