Add ability to set LED colors in DBus
phosphor-led-sysfs parses sysfs LED node names
in the form of "devicename:colour:function" as
described in
https://github.com/torvalds/linux/blob/master/Documentation/leds/leds-class.txt#L46
and then converts the "colour" part into the proper
value of the DBus 'Color' property using the
xyz.openbmc_project.Led.Physical.Palette interface.
In order for the led nodes to have their Color set,
the corresponding led nodes in devicetree must have
correct 'label' properties, e.g.:
leds {
compatible = "gpio-leds";
heartbeat {
label = "bmc:green:hearbeat";
gpios = <&gpio ASPEED_GPIO(R, 4) GPIO_ACTIVE_LOW>;
};
power_red {
label = "system:red:power";
gpios = <&gpio ASPEED_GPIO(N, 1) GPIO_ACTIVE_LOW>;
};
}
Change-Id: I094f0e434bdd262995752576a3c792ccd5dbb3e2
Signed-off-by: Alexander Soldatov <a.soldatov@yadro.com>
Signed-off-by: Alexander Amelkin <a.amelkin@yadro.com>
diff --git a/controller.cpp b/controller.cpp
index 82430a7..8b9a22d 100644
--- a/controller.cpp
+++ b/controller.cpp
@@ -21,6 +21,7 @@
#include "sysfs.hpp"
#include <algorithm>
+#include <boost/algorithm/string.hpp>
#include <iostream>
#include <string>
@@ -32,6 +33,53 @@
exit(-1);
}
+struct LedDescr
+{
+ std::string devicename;
+ std::string color;
+ std::string function;
+};
+
+/** @brief parse LED name in sysfs
+ * Parse sysfs LED name in format "devicename:colour:function"
+ * or "devicename:colour" or "devicename" and sets corresponding
+ * fields in LedDescr struct.
+ *
+ * @param[in] name - LED name in sysfs
+ * @param[out] ledDescr - LED description
+ */
+void getLedDescr(const std::string& name, LedDescr& ledDescr)
+{
+ std::vector<std::string> words;
+ boost::split(words, name, boost::is_any_of(":"));
+ try
+ {
+ ledDescr.devicename = words.at(0);
+ ledDescr.color = words.at(1);
+ ledDescr.function = words.at(2);
+ }
+ catch (const std::out_of_range&)
+ {
+ return;
+ }
+}
+
+/** @brief generates LED DBus name from LED description
+ *
+ * @param[in] name - LED description
+ * @return - DBus LED name
+ */
+std::string getDbusName(const LedDescr& ledDescr)
+{
+ std::vector<std::string> words;
+ words.emplace_back(ledDescr.devicename);
+ if (!ledDescr.function.empty())
+ words.emplace_back(ledDescr.function);
+ if (!ledDescr.color.empty())
+ words.emplace_back(ledDescr.color);
+ return boost::join(words, "_");
+}
+
int main(int argc, char** argv)
{
namespace fs = std::experimental::filesystem;
@@ -53,7 +101,7 @@
// Since this application always gets invoked as part of a udev rule,
// it is always guaranteed to get /sys/class/leds/one/two
- // and we can go beyond leds/ to get the actual led name.
+ // and we can go beyond leds/ to get the actual LED name.
// Refer: systemd/systemd#5072
// On an error, this throws an exception and terminates.
@@ -72,6 +120,11 @@
// dbus paths and hence need to convert them to underscores.
std::replace(name.begin(), name.end(), '-', '_');
+ // Convert LED name in sysfs into DBus name
+ LedDescr ledDescr;
+ getLedDescr(name, ledDescr);
+ name = getDbusName(ledDescr);
+
// Unique bus name representing a single LED.
auto busName = std::string(BUSNAME) + '.' + name;
auto objPath = std::string(OBJPATH) + '/' + name;
@@ -85,7 +138,7 @@
// Create the Physical LED objects for directing actions.
// Need to save this else sdbusplus destructor will wipe this off.
phosphor::led::SysfsLed sled{fs::path(path)};
- phosphor::led::Physical led(bus, objPath, sled);
+ phosphor::led::Physical led(bus, objPath, sled, ledDescr.color);
/** @brief Claim the bus */
bus.request_name(busName.c_str());