blob: bfbf426ec8bf3fb053d66e3ac900f89044fc1275 [file] [log] [blame]
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +05301#include <iostream>
2#include <cstring>
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +05303#include <algorithm>
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +05304#include <sdbusplus/vtable.hpp>
5#include <sdbusplus/message.hpp>
6#include <sdbusplus/bus.hpp>
7#include "led-manager.hpp"
8#include "led-gen.hpp"
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +05309namespace phosphor
10{
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +053011namespace led
12{
13
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +053014std::set<const Group::group*> Group::assertedGroups;
15Group::group Group::currentState;
16
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +053017/** @brief Called when the group's property is read
18 * Signature as needed by sd_bus
19 */
20int getGroupState(sd_bus *bus, const char *path, const char *interface,
21 const char *property, sd_bus_message *reply,
22 void *data, sd_bus_error* error)
23{
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +053024 auto ledMgr = static_cast<Group*>(data);
25 auto state = ledMgr->getGroupState(path);
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +053026
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +053027 sd_bus_message_append(reply, "b", state);
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +053028 return 0;
29}
30
31/** @brief Called when the group's asserted state is updated
32 * Signature as needed by sd_bus
33 */
34int setGroupState(sd_bus *bus, const char *path, const char *interface,
35 const char *property, sd_bus_message *value,
36 void *data, sd_bus_error* error)
37{
38 bool state {};
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +053039 auto msg = sdbusplus::message::message(value);
40 sd_bus_message_ref(value);
41 msg.read(state);
42
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +053043 auto ledMgr = static_cast<Group*>(data);
44 return ledMgr->setGroupState(path, state);
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +053045}
46
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +053047// Get the asserted state
48bool Group::getGroupState(const std::string& path)
49{
50 return assertedGroups.find(&ledMap.at(path)) != assertedGroups.end();
51}
52
53// Assert -or- De-assert
54int Group::setGroupState(const std::string& path, bool assert)
55{
56 if (assert)
57 {
58 assertedGroups.insert(&ledMap.at(path));
59 }
60 else
61 {
62 auto search = assertedGroups.find(&ledMap.at(path));
63 if (search != assertedGroups.end())
64 {
65 assertedGroups.erase(&ledMap.at(path));
66 }
67 else
68 {
69 std::cout << "Group [ " << path << " ] Not present\n";
70 }
71 }
72 return driveLEDs();
73}
74
75// Run through the map and apply action
76int Group::driveLEDs()
77{
78 // This will contain the union of what's already in the asserted group
79 group desiredState {};
80 for(const auto& grp : assertedGroups)
81 {
82 desiredState.insert(grp->cbegin(), grp->cend());
83 }
84
85 // Always Do execute Turn Off and then Turn on since we have the Blink
86 // taking priority over -on-
87 group ledsToDeAssert {};
88
89 std::set_difference(currentState.begin(), currentState.end(),
90 desiredState.begin(), desiredState.end(),
91 std::inserter(ledsToDeAssert, ledsToDeAssert.begin()));
92 if(ledsToDeAssert.size())
93 {
94 // We really do not want the Group Manager to know how a particular LED
95 // transitions from State-A --> State-B and all this must be handled by
96 // the physical LED controller implementation.
97 // So in this case, Group Manager really does not want to turn off the
98 // LEDs and then turning it back on and let the physical LED controller
99 // handle that.
100
101 // If we previously had a FRU in ON state , and then if there was a
102 // request to make it blink, the end state would now be blink.
103 // If we either turn off blink / fault, then we need to go back to its
104 // previous state.
105 group ledsToReAssert {};
106 std::set_intersection(desiredState.begin(), desiredState.end(),
107 ledsToDeAssert.begin(), ledsToDeAssert.end(),
108 std::inserter(ledsToReAssert, ledsToReAssert.begin()),
109 ledComp);
110
111 if (ledsToReAssert.size())
112 {
113 std::cout << "Asserting LEDs again" << std::endl;
114 for (const auto& it: ledsToReAssert)
115 {
116 std::cout << "\t{" << it.name << "::" << it.action << "}"
117 << std::endl;
118 }
119 }
120 }
121
122 // Turn on these
123 group ledsToAssert {};
124 std::set_difference(desiredState.begin(), desiredState.end(),
125 currentState.begin(), currentState.end(),
126 std::inserter(ledsToAssert, ledsToAssert.begin()));
127
128 if(ledsToAssert.size())
129 {
130 std::cout << "Asserting LEDs" << std::endl;
131 for (const auto& it: ledsToAssert)
132 {
133 std::cout << "\t{" << it.name << "::" << it.action << "}"
134 << std::endl;
135 }
136 }
137
138 // Done.. Save the latest and greatest.
139 currentState = std::move(desiredState);
140
141 return 0;
142}
143
144/** @brief Users having to assert a group will just turn this property to TRUE
145 * similarly, setting this property to FALSE will deassert the group
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530146 */
147constexpr sdbusplus::vtable::vtable_t led_vtable[] =
148{
149 sdbusplus::vtable::start(),
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530150 sdbusplus::vtable::property("Asserted", "b",
151 getGroupState, setGroupState,
152 sdbusplus::vtable::property_::emits_change),
153 sdbusplus::vtable::end()
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530154};
155
156/** @brief Initialize the bus and announce services */
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530157Group::Group(const char* busName,
158 const char* objPath,
159 const char* intfName) :
160 bus(sdbusplus::bus::new_system()),
161 objManager(bus, objPath)
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530162{
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530163 /** Now create so many dbus objects as there are groups */
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530164 for (auto &grp: Group::ledMap)
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530165 {
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530166 intfContainer.emplace_back(bus, grp.first.c_str(),
167 intfName, led_vtable, this);
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530168
169 // These are now set of structs having LED name and the action. Do not
170 // have anything to be done here at the moment but need to create a
171 // mapping between led names to device strigs eventually
172 //for (auto &set: grp.second)
173 //{
174
175 //}
176 }
177 // Once done, claim the bus and systemd will
178 // consider this service started
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530179 bus.request_name(busName);
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530180}
181
182/** @brief Wait for client requests */
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530183void Group::run()
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530184{
185 while(true)
186 {
187 try
188 {
Vishwanatha Subbannabb8fe0b2016-11-12 18:29:38 +0530189 bus.process_discard();
190 bus.wait();
Vishwanatha Subbannab21fda72016-10-17 17:46:37 +0530191 }
192 catch (std::exception &e)
193 {
194 std::cerr << e.what() << std::endl;
195 }
196 }
197}
198
199} // namespace led
200
201} // namespace phosphor