diff options
author | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2016-10-17 17:46:37 +0530 |
---|---|---|
committer | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2016-11-21 23:06:00 +0530 |
commit | b21fda795e15fb7ba3e74d63518ff2a112d4c875 (patch) | |
tree | b4aeb74af1ee8ae06244b8af5e8381c879f63c6d | |
parent | cbad1b9813b5005fe6a2af706d777464cab5b845 (diff) | |
download | phosphor-led-manager-b21fda795e15fb7ba3e74d63518ff2a112d4c875.tar.gz phosphor-led-manager-b21fda795e15fb7ba3e74d63518ff2a112d4c875.zip |
Add LED grouping support
This enables creating custom groups and participating LEDs so that it can later
be generated from MRW. For each of the group, a dbus object is created which
will announce LED actions.
Fixes openbmc/openbmc#550
Change-Id: I7a56d08755288dcfce45ee4c6d6b6c5e5aa454f7
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
-rw-r--r-- | Makefile.am | 17 | ||||
-rwxr-xr-x | bootstrap.sh | 16 | ||||
-rw-r--r-- | configure.ac | 42 | ||||
-rw-r--r-- | led-main.cpp | 9 | ||||
-rw-r--r-- | led-manager.cpp | 119 | ||||
-rw-r--r-- | led-manager.hpp | 99 | ||||
-rwxr-xr-x | led.yaml | 119 | ||||
-rwxr-xr-x | parse_led.py | 27 |
8 files changed, 448 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..c93a550 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,17 @@ +AM_DEFAULT_SOURCE_EXT = .cpp +AM_CPPFLAGS = -I$(top_srcdir)/../sdbusplus + +BUILT_SOURCES = led-gen.hpp +CLEANFILES = led-gen.hpp +PYTHON="/usr/bin/python" +led-gen.hpp: ${srcdir}/parse_led.py + ${AM_V_at}${PYTHON} $^ > $@ + +sbin_PROGRAMS = \ + ledmanager + +ledmanager_SOURCES = \ + led-manager.cpp \ + led-main.cpp + +ledmanager_LDFLAGS = $(SYSTEMD_LIBS) diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..412550f --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +AUTOCONF_FILES="Makefile.in aclocal.m4 ar-lib autom4te.cache compile config.* \ + configure depcomp install-sh ltmain.sh missing *libtool" + +case $1 in + clean) + test -f Makefile && make maintainer-clean + rm -rf ${AUTOCONF_FILES} + + exit 0 + ;; +esac + +autoreconf -i +echo 'Run "./configure ${CONFIGURE_FLAGS} && make"' diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..059f612 --- /dev/null +++ b/configure.ac @@ -0,0 +1,42 @@ +# Initialization +AC_PREREQ([2.69]) +AC_INIT([phosphor-led-manager], [1.0], [https://github.com/openbmc/phosphor-led-manager/issues]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz]) +AM_SILENT_RULES([yes]) + +# Checks for programs. +AC_PROG_CXX +AX_CXX_COMPILE_STDCXX_14([noext]) +AM_PROG_AR +AC_PROG_INSTALL +AC_PROG_MAKE_SET +LT_INIT + +# Python +AM_PATH_PYTHON([2.7], [AC_SUBST([PYTHON], [echo "$PYTHON"])], [AC_MSG_ERROR([Could not find python-2.7 installed...python-2.7 is required])]) + +# Checks for libraries. +PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221]) + +# Checks for header files. +AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd developement package required])]) +#AC_CHECK_HEADER(sdbusplus/vtable.hpp, ,[AC_MSG_ERROR([Could not find vtable.hpp...openbmc/sdbusplus package required])]) +#AC_CHECK_HEADER(dbusplus/message.hpp, ,[AC_MSG_ERROR([Could not find messsage.hpp...openbmc/sdbusplus package required])]) +#AC_CHECK_HEADER(sdbusplus/bus.hpp, ,[AC_MSG_ERROR([Could not find bus.hpp...openbmc/sdbusplus package required])]) + +# Checks for typedefs, structures, and compiler characteristics. +AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS]) +AC_ARG_VAR(BUSNAME, [The Dbus busname to own]) +AC_ARG_VAR(OBJPATH, [The Ledmanager Dbus root]) +AC_ARG_VAR(INTERFACE, [The Ledmanager Dbus interface]) +AS_IF([test "x$BUSNAME" == "x"], [BUSNAME="xyz.openbmc_project.ledmanager"]) +AS_IF([test "x$OBJPATH" == "x"], [OBJPATH="/xyz/openbmc_project/ledmanager/groups"]) +AS_IF([test "x$INTERFACE" == "x"], [INTERFACE="xyz.openbmc_project.Ledmanager"]) +AC_DEFINE_UNQUOTED([BUSNAME], ["$BUSNAME"], [The DBus busname to own]) +AC_DEFINE_UNQUOTED([OBJPATH], ["$OBJPATH"], [The Ledmanager Dbus root]) +AC_DEFINE_UNQUOTED([INTERFACE], ["$INTERFACE"], [The Ledmanager Dbus interface]) + +# Create configured output +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/led-main.cpp b/led-main.cpp new file mode 100644 index 0000000..e10c2fe --- /dev/null +++ b/led-main.cpp @@ -0,0 +1,9 @@ +#include "led-manager.hpp" +#include "config.h" + +int main(void) +{ + phosphor::led::Manager ledMgr(BUSNAME, OBJPATH, INTERFACE); + ledMgr.run(); + return 0; +} diff --git a/led-manager.cpp b/led-manager.cpp new file mode 100644 index 0000000..8bc1751 --- /dev/null +++ b/led-manager.cpp @@ -0,0 +1,119 @@ +#include <iostream> +#include <cstring> +#include <sdbusplus/vtable.hpp> +#include <sdbusplus/message.hpp> +#include <sdbusplus/bus.hpp> +#include "led-manager.hpp" +#include "led-gen.hpp" + +namespace phosphor +{ + +namespace led +{ + +/** @brief Called when the group's property is read + * Signature as needed by sd_bus + */ +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++; + } + + //TODO : Need to see how to represent group specific asserted state + // May be a new tuple / map ? + sd_bus_message_append(reply, "b", 0); + return 0; +} + +/** @brief Called when the group's asserted state is updated + * Signature as needed by sd_bus + */ +int setGroupState(sd_bus *bus, const char *path, const char *interface, + const char *property, sd_bus_message *value, + 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; +} + +/** @brief Users having to assert a group will just turn this property to 1 + * similarly, setting this property to 0 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() +}; + +/** @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) +{ + // 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) + { + auto grpPath = path + grp.first; + intfContainer.emplace_back(sdbusplus::server::interface::interface( + iv_bus, grpPath.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 + // mapping between led names to device strigs eventually + //for (auto &set: grp.second) + //{ + + //} + } + // Once done, claim the bus and systemd will + // consider this service started + iv_bus.request_name(busName); +} + +/** @brief Wait for client requests */ +void Manager::run() +{ + while(true) + { + try + { + iv_bus.process_discard(); + iv_bus.wait(); + } + catch (std::exception &e) + { + std::cerr << e.what() << std::endl; + } + } +} + +} // namespace led + +} // namespace phosphor diff --git a/led-manager.hpp b/led-manager.hpp new file mode 100644 index 0000000..1ff869b --- /dev/null +++ b/led-manager.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include <map> +#include <set> +#include <vector> +#include <sdbusplus/bus.hpp> +#include <sdbusplus/server/interface.hpp> +#include <sdbusplus/server/manager.hpp> + +namespace phosphor +{ + +namespace led +{ + +/** @class Manager + * @brief Manages group of LEDs and applies action on the elements of group + */ + +class Manager +{ +private: + + /** @brief Define possible actions on a given LED. + * For the BLINK operation, follow 50-50 duty cycle + */ + enum Action + { + OFF, + ON, + BLINK, + }; + + /** @brief Dbus constructs used by LED manager */ + sdbusplus::bus::bus iv_bus; + +public: + Manager() = delete; + ~Manager() = default; + Manager(const Manager&) = delete; + Manager& operator=(const Manager&) = delete; + Manager(Manager&&) = default; + Manager& operator=(Manager&&) = default; + + /** @brief Constructs LED manager + * + * @param[in] busName - The Dbus name to own + * @param[in] objPath - The Dbus path that hosts LED manager + * @param[in] intfName - The Dbus interface + */ + Manager(const char* busName, const char* objPath, const char* intfName); + + /** @brief Name of the LED and it's proposed action. + * This structure is supplied as configuration at build time + */ + struct LedAction + { + std::string name; + Action action; + + // Needed for inserting elements into sets + bool operator<(const LedAction& right) const + { + if (name == right.name) + { + return action < right.action; + } + return name < right.name; + } + + // Needed for set union / intersect + bool operator==(const LedAction& right) const + { + // Only if name and action are same, consider equal + if (name == right.name && + action == right.action) + { + return true; + } + return false; + } + }; + + /** @brief static global map constructed at compile time */ + static const std::map<std::string, + std::set<LedAction>> cv_LedMap; + + /** @brief sd_bus object manager */ + sdbusplus::server::manager::manager objManager; + + /** @brief Individual objects */ + std::vector<sdbusplus::server::interface::interface> intfContainer; + + void run(); +}; + +} // namespace led + +} // namespace phosphor diff --git a/led.yaml b/led.yaml new file mode 100755 index 0000000..0d01c96 --- /dev/null +++ b/led.yaml @@ -0,0 +1,119 @@ +EnclosureIdentify: + EnclosureIdentifyFront: + action: blink + EnclosureIdentifyBack: + action: blink + +EnclosureFault: + EnclosureFaultFront: + action: 'on' + EnclosureFaultBack: + action: 'on' + +PowerSupply1Identify: + PowerSupply_1: + action: blink + EnclosureIdentifyFront: + action: 'on' + EnclosureIdentifyBack: + action: 'on' + +PowerSupply1Fault: + PowerSupply_1: + action: 'on' + EnclosureFaultFront: + action: 'on' + EnclosureFaultBack: + action: 'on' + +PowerSupply2Identify: + PowerSupply_2: + action: blink + EnclosureIdentifyFront: + action: 'on' + EnclosureIdentifyBack: + action: 'on' + +PowerSupply2Fault: + PowerSupply_2: + action: 'on' + EnclosureFaultFront: + action: 'on' + EnclosureFaultBack: + action: 'on' + +FanA1Identify: + Fan_A1: + action: blink + EnclosureIdentifyFront: + action: 'on' + EnclosureIdentifyBack: + action: 'on' + +FanA1Fault: + Fan_A1: + action: 'on' + EnclosureFaultFront: + action: 'on' + EnclosureFaultBack: + action: 'on' + +FanA2Identify: + Fan_A2: + action: blink + EnclosureIdentifyFront: + action: 'on' + EnclosureIdentifyBack: + action: 'on' + +FanA2Fault: + Fan_A2: + action: 'on' + EnclosureFaultFront: + action: 'on' + EnclosureFaultBack: + action: 'on' + +FanA3Identify: + Fan_A3: + action: blink + EnclosureIdentifyFront: + action: 'on' + EnclosureIdentifyBack: + action: 'on' + +FanA3Fault: + Fan_A3: + action: 'on' + EnclosureFaultFront: + action: 'on' + EnclosureFaultBack: + action: 'on' + +FanA4Identify: + Fan_A4: + action: blink + EnclosureIdentifyFront: + action: 'on' + EnclosureIdentifyBack: + action: 'on' + +FanA4Fault: + Fan_A4: + action: 'on' + EnclosureFaultFront: + action: 'on' + EnclosureFaultBack: + action: 'on' + +PowerOn: + OpPanelFront: + action: 'on' + PanelPowerButtonNote1: + action: 'on' + +PowerOff: + OpPanelFront: + action: blink + PanelPowerButtonNote1: + action: blink diff --git a/parse_led.py b/parse_led.py new file mode 100755 index 0000000..96bcd5e --- /dev/null +++ b/parse_led.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +import yaml + +if __name__ == '__main__': + with open('led.yaml', 'r') as f: + ifile = yaml.safe_load(f) + + with open('led-gen.hpp', 'w') as ofile: + ofile.write('/* !!! WARNING: This is a GENERATED Code..') + ofile.write('Please do NOT Edit !!! */\n\n') + + ofile.write('const std::map<std::string,') + ofile.write(' std::set<phosphor::led::Manager::LedAction>>') + ofile.write(' phosphor::led::Manager::cv_LedMap = {\n\n') + for group in ifile.iterkeys(): + # Value of this group is a std::set<string, led structure> + ledset = ifile[group] + ofile.write(' {\"' + group + '\",{\n') + + for led_dict, list_dict in ledset.iteritems(): + for name, value in list_dict.iteritems(): + if group and led_dict and name and value: + ofile.write(' {\"' + led_dict + '\",') + ofile.write(value.upper() + '},\n') + ofile.write(' }},\n') + ofile.write('};\n') + |