summaryrefslogtreecommitdiffstats
path: root/led-manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'led-manager.cpp')
-rw-r--r--led-manager.cpp166
1 files changed, 124 insertions, 42 deletions
diff --git a/led-manager.cpp b/led-manager.cpp
index 8bc1751..bfbf426 100644
--- a/led-manager.cpp
+++ b/led-manager.cpp
@@ -1,17 +1,19 @@
#include <iostream>
#include <cstring>
+#include <algorithm>
#include <sdbusplus/vtable.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/bus.hpp>
#include "led-manager.hpp"
#include "led-gen.hpp"
-
namespace phosphor
{
-
namespace led
{
+std::set<const Group::group*> Group::assertedGroups;
+Group::group Group::currentState;
+
/** @brief Called when the group's property is read
* Signature as needed by sd_bus
*/
@@ -19,16 +21,10 @@ int getGroupState(sd_bus *bus, const char *path, const char *interface,
const char *property, sd_bus_message *reply,
void *data, sd_bus_error* error)
{
- auto group = strrchr(path, '/');
- if (group)
- {
- // Removing the starting '/' in /group
- group++;
- }
+ auto ledMgr = static_cast<Group*>(data);
+ auto state = ledMgr->getGroupState(path);
- //TODO : Need to see how to represent group specific asserted state
- // May be a new tuple / map ?
- sd_bus_message_append(reply, "b", 0);
+ sd_bus_message_append(reply, "b", state);
return 0;
}
@@ -40,49 +36,135 @@ int setGroupState(sd_bus *bus, const char *path, const char *interface,
void *data, sd_bus_error* error)
{
bool state {};
- auto group = strrchr(path, '/');
- if (group)
- {
- // Removing the starting '/' in /group
- group++;
- }
-
auto msg = sdbusplus::message::message(value);
sd_bus_message_ref(value);
msg.read(state);
- //TODO : Need to see how to represent group specific asserted state
- // May be a new tuple / map ?
- return 1;
+ auto ledMgr = static_cast<Group*>(data);
+ return ledMgr->setGroupState(path, state);
+}
+
+// Get the asserted state
+bool Group::getGroupState(const std::string& path)
+{
+ return assertedGroups.find(&ledMap.at(path)) != assertedGroups.end();
}
-/** @brief Users having to assert a group will just turn this property to 1
- * similarly, setting this property to 0 will deassert the group
+// Assert -or- De-assert
+int Group::setGroupState(const std::string& path, bool assert)
+{
+ if (assert)
+ {
+ assertedGroups.insert(&ledMap.at(path));
+ }
+ else
+ {
+ auto search = assertedGroups.find(&ledMap.at(path));
+ if (search != assertedGroups.end())
+ {
+ assertedGroups.erase(&ledMap.at(path));
+ }
+ else
+ {
+ std::cout << "Group [ " << path << " ] Not present\n";
+ }
+ }
+ return driveLEDs();
+}
+
+// Run through the map and apply action
+int Group::driveLEDs()
+{
+ // This will contain the union of what's already in the asserted group
+ group desiredState {};
+ for(const auto& grp : assertedGroups)
+ {
+ desiredState.insert(grp->cbegin(), grp->cend());
+ }
+
+ // Always Do execute Turn Off and then Turn on since we have the Blink
+ // taking priority over -on-
+ group ledsToDeAssert {};
+
+ std::set_difference(currentState.begin(), currentState.end(),
+ desiredState.begin(), desiredState.end(),
+ std::inserter(ledsToDeAssert, ledsToDeAssert.begin()));
+ if(ledsToDeAssert.size())
+ {
+ // We really do not want the Group Manager to know how a particular LED
+ // transitions from State-A --> State-B and all this must be handled by
+ // the physical LED controller implementation.
+ // So in this case, Group Manager really does not want to turn off the
+ // LEDs and then turning it back on and let the physical LED controller
+ // handle that.
+
+ // If we previously had a FRU in ON state , and then if there was a
+ // request to make it blink, the end state would now be blink.
+ // If we either turn off blink / fault, then we need to go back to its
+ // previous state.
+ group ledsToReAssert {};
+ std::set_intersection(desiredState.begin(), desiredState.end(),
+ ledsToDeAssert.begin(), ledsToDeAssert.end(),
+ std::inserter(ledsToReAssert, ledsToReAssert.begin()),
+ ledComp);
+
+ if (ledsToReAssert.size())
+ {
+ std::cout << "Asserting LEDs again" << std::endl;
+ for (const auto& it: ledsToReAssert)
+ {
+ std::cout << "\t{" << it.name << "::" << it.action << "}"
+ << std::endl;
+ }
+ }
+ }
+
+ // Turn on these
+ group ledsToAssert {};
+ std::set_difference(desiredState.begin(), desiredState.end(),
+ currentState.begin(), currentState.end(),
+ std::inserter(ledsToAssert, ledsToAssert.begin()));
+
+ if(ledsToAssert.size())
+ {
+ std::cout << "Asserting LEDs" << std::endl;
+ for (const auto& it: ledsToAssert)
+ {
+ std::cout << "\t{" << it.name << "::" << it.action << "}"
+ << std::endl;
+ }
+ }
+
+ // Done.. Save the latest and greatest.
+ currentState = std::move(desiredState);
+
+ return 0;
+}
+
+/** @brief Users having to assert a group will just turn this property to TRUE
+ * similarly, setting this property to FALSE will deassert the group
*/
constexpr sdbusplus::vtable::vtable_t led_vtable[] =
{
sdbusplus::vtable::start(),
- sdbusplus::vtable::property("Assert", "b",
- getGroupState, setGroupState, sdbusplus::vtable::property_::emits_change),
- sdbusplus::vtable::end()
+ sdbusplus::vtable::property("Asserted", "b",
+ getGroupState, setGroupState,
+ sdbusplus::vtable::property_::emits_change),
+ sdbusplus::vtable::end()
};
/** @brief Initialize the bus and announce services */
-Manager::Manager(const char* busName,
- const char* objPath,
- const char* intfName) :
- iv_bus(sdbusplus::bus::new_system()),
- objManager(iv_bus, objPath)
+Group::Group(const char* busName,
+ const char* objPath,
+ const char* intfName) :
+ bus(sdbusplus::bus::new_system()),
+ objManager(bus, objPath)
{
- // Like /org/openbmc/ledmanager/groups/
- auto path = std::string(objPath) + "/";
-
/** Now create so many dbus objects as there are groups */
- for (auto &grp: Manager::cv_LedMap)
+ for (auto &grp: Group::ledMap)
{
- auto grpPath = path + grp.first;
- intfContainer.emplace_back(sdbusplus::server::interface::interface(
- iv_bus, grpPath.c_str(), intfName, led_vtable, this));
+ intfContainer.emplace_back(bus, grp.first.c_str(),
+ intfName, led_vtable, this);
// These are now set of structs having LED name and the action. Do not
// have anything to be done here at the moment but need to create a
@@ -94,18 +176,18 @@ Manager::Manager(const char* busName,
}
// Once done, claim the bus and systemd will
// consider this service started
- iv_bus.request_name(busName);
+ bus.request_name(busName);
}
/** @brief Wait for client requests */
-void Manager::run()
+void Group::run()
{
while(true)
{
try
{
- iv_bus.process_discard();
- iv_bus.wait();
+ bus.process_discard();
+ bus.wait();
}
catch (std::exception &e)
{
OpenPOWER on IntegriCloud