blob: 7b5791a6db6e760811933fd9fb8922168b6289c6 [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 Subbanna11ca8f92017-02-27 19:33:45 +053085 // For now, physical LED is driven by xyz.openbmc_project.Led.Controller
86 // at /xyz/openbmc_project/led/physical. However, its possible that in the
87 // future, the physical LEDs are driven by different dbus services.
88 // when that happens, service name needs to be obtained everytime a
89 // particular LED would be targeted as opposed to getting one now and then
90 // using it for all
91
Vishwanatha Subbannaed490732016-12-20 15:59:29 +053092 // This order of LED operation is important.
93 if (ledsUpdate.size())
94 {
95 std::cout << "Updating LED states between (On <--> Blink)"
96 << std::endl;
97 for (const auto& it: ledsUpdate)
98 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +053099 std::string objPath = std::string(PHY_LED_PATH) + it.name;
100 drivePhysicalLED(objPath, it.action, it.dutyOn);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530101 }
102 }
103
104 if (ledsDeAssert.size())
105 {
106 std::cout << "De-Asserting LEDs" << std::endl;
107 for (const auto& it: ledsDeAssert)
108 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530109 std::string objPath = std::string(PHY_LED_PATH) + it.name;
110 drivePhysicalLED(objPath, Layout::Action::Off, it.dutyOn);
Vishwanatha Subbannaed490732016-12-20 15:59:29 +0530111 }
112 }
113
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +0530114 if(ledsAssert.size())
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530115 {
116 std::cout << "Asserting LEDs" << std::endl;
Vishwanatha Subbanna447d0c82016-12-19 14:12:42 +0530117 for (const auto& it: ledsAssert)
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530118 {
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530119 std::string objPath = std::string(PHY_LED_PATH) + it.name;
120 drivePhysicalLED(objPath, it.action, it.dutyOn);
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530121 }
122 }
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530123 return;
124}
125
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530126// Calls into driving physical LED post choosing the action
127void Manager::drivePhysicalLED(const std::string& objPath,
128 Layout::Action action,
129 uint8_t dutyOn)
130{
131 auto service = getServiceName(objPath, PHY_LED_IFACE);
132 if (!service.empty())
133 {
134 // If Blink, set its property
135 if (action == Layout::Action::Blink)
136 {
137 drivePhysicalLED(service, objPath, "DutyOn", dutyOn);
138 }
139 drivePhysicalLED(service, objPath, "State",
140 getPhysicalAction(action));
141 }
142}
143
144/** @brief Returns action string based on enum */
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530145std::string Manager::getPhysicalAction(Layout::Action action)
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530146{
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530147 namespace server = sdbusplus::xyz::openbmc_project::Led::server;
148
149 // TODO: openbmc/phosphor-led-manager#5
150 // Somehow need to use the generated Action enum than giving one
151 // in ledlayout.
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530152 if(action == Layout::Action::On)
153 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530154 return server::convertForMessage(server::Physical::Action::On);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530155 }
156 else if(action == Layout::Action::Blink)
157 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530158 return server::convertForMessage(server::Physical::Action::Blink);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530159 }
160 else
161 {
Vishwanatha Subbanna4fa92482017-03-10 14:39:20 +0530162 return server::convertForMessage(server::Physical::Action::Off);
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530163 }
164}
165
166/** Given the LED dbus path and interface, returns the service name */
167std::string Manager::getServiceName(const std::string& objPath,
168 const std::string& interface) const
169{
170 using namespace phosphor::logging;
171
172 // Mapper dbus constructs
173 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
Leonel Gonzalez76f58342017-03-16 13:47:52 -0500174 constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
Vishwanatha Subbanna11ca8f92017-02-27 19:33:45 +0530175 constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
176
177 // Make a mapper call
178 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
179 MAPPER_IFACE, "GetObject");
180 // Cook rest of the things.
181 mapperCall.append(objPath);
182 mapperCall.append(std::vector<std::string>({interface}));
183
184 auto reply = bus.call(mapperCall);
185 if (reply.is_method_error())
186 {
187 // Its okay if we do not see a corresponding physical LED.
188 log<level::INFO>("Error looking up Physical LED service",
189 entry("PATH=%s",objPath.c_str()));
190 return "";
191 }
192
193 // Response by mapper in the case of success
194 std::map<std::string, std::vector<std::string>> serviceNames;
195
196 // This is the service name for the passed in objpath
197 reply.read(serviceNames);
198 if (serviceNames.empty())
199 {
200 log<level::INFO>("Physical LED lookup did not return any service",
201 entry("PATH=%s",objPath.c_str()));
202 return "";
203 }
204
205 return serviceNames.begin()->first;
206}
207
Vishwanatha Subbanna4c8c72b2016-11-29 23:02:06 +0530208} // namespace led
209} // namespace phosphor