diff options
Diffstat (limited to 'led-manager.cpp')
-rw-r--r-- | led-manager.cpp | 166 |
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) { |