lamp test: Add vritual lamp test function
- This feature adds the functionality that enables force updating
certain physical LEDs and skip updating certain physical LEDs as
part of lamp test.
- This is a generic feature that gives more control over handing
physical LEDs.
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I6f06ed103b1ceefdaa774b7a74a4a392609000ed
diff --git a/configure.ac b/configure.ac
index 27d4d9d..4a50e38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,6 +101,9 @@
# lamp test timeout secs
AC_ARG_VAR(LAMP_TEST_TIMEOUT_IN_SECS, [The lamp test timeout in seconds])
+ # JSON file having LED names that will be force updated and/or skipped during lamp test
+ AC_ARG_VAR(LAMP_TEST_LED_OVERRIDES_JSON, [JSON file having LED names that will be force updated and/or skipped during lamp test])
+
AS_IF([test "x$LAMP_TEST_OBJECT" == "x"], [LAMP_TEST_OBJECT="/xyz/openbmc_project/led/groups/lamp_test"])
AC_DEFINE_UNQUOTED([LAMP_TEST_OBJECT], ["$LAMP_TEST_OBJECT"], [The lamp test D-Bus object])
@@ -109,6 +112,9 @@
AS_IF([test "x$LAMP_TEST_TIMEOUT_IN_SECS" == "x"], [LAMP_TEST_TIMEOUT_IN_SECS=240])
AC_DEFINE_UNQUOTED([LAMP_TEST_TIMEOUT_IN_SECS], [$LAMP_TEST_TIMEOUT_IN_SECS], [The lamp test timeout in seconds])
+
+ AS_IF([test "x$LAMP_TEST_LED_OVERRIDES_JSON" == "x"], [LAMP_TEST_LED_OVERRIDES_JSON="/usr/share/phosphor-led-manager/lamp-test-led-overrides.json"])
+ AC_DEFINE_UNQUOTED([LAMP_TEST_LED_OVERRIDES_JSON], ["$LAMP_TEST_LED_OVERRIDES_JSON"], [JSON file having LED names that will be force updated and/or skipped during lamp test])
)
# Path of file for storing the names of asserted groups
diff --git a/lamptest.cpp b/lamptest.cpp
index aaf73de..8220f96 100644
--- a/lamptest.cpp
+++ b/lamptest.cpp
@@ -1,5 +1,3 @@
-#include "config.h"
-
#include "lamptest.hpp"
#include <phosphor-logging/log.hpp>
@@ -10,6 +8,7 @@
{
using namespace phosphor::logging;
+using Json = nlohmann::json;
bool LampTest::processLEDUpdates(const Manager::group& ledsAssert,
const Manager::group& ledsDeAssert)
@@ -19,6 +18,34 @@
// stopped.
if (isLampTestRunning)
{
+ // Physical LEDs will be updated during lamp test
+ for (const auto& it : ledsDeAssert)
+ {
+ std::string path = std::string(PHY_LED_PATH) + it.name;
+ auto iter = std::find_if(
+ forceUpdateLEDs.begin(), forceUpdateLEDs.end(),
+ [&path](const auto& name) { return name == path; });
+
+ if (iter != forceUpdateLEDs.end())
+ {
+ manager.drivePhysicalLED(path, Layout::Action::Off, it.dutyOn,
+ it.period);
+ }
+ }
+
+ for (const auto& it : ledsAssert)
+ {
+ std::string path = std::string(PHY_LED_PATH) + it.name;
+ auto iter = std::find_if(
+ forceUpdateLEDs.begin(), forceUpdateLEDs.end(),
+ [&path](const auto& name) { return name == path; });
+
+ if (iter != forceUpdateLEDs.end())
+ {
+ manager.drivePhysicalLED(path, it.action, it.dutyOn, it.period);
+ }
+ }
+
updatedLEDsDuringLampTest.emplace(
std::make_pair(ledsAssert, ledsDeAssert));
return true;
@@ -41,6 +68,16 @@
// Set all the Physical action to Off
for (const auto& path : physicalLEDPaths)
{
+ auto iter =
+ std::find_if(skipUpdateLEDs.begin(), skipUpdateLEDs.end(),
+ [&path](const auto& skip) { return skip == path; });
+
+ if (iter != skipUpdateLEDs.end())
+ {
+ // Skip update physical path
+ continue;
+ }
+
manager.drivePhysicalLED(path, Layout::Action::Off, 0, 0);
}
@@ -70,6 +107,16 @@
for (const auto& path : physicalLEDPaths)
{
+ auto iter = std::find_if(
+ skipUpdateLEDs.begin(), skipUpdateLEDs.end(),
+ [&path](const auto& skipLed) { return skipLed == path; });
+
+ if (iter != skipUpdateLEDs.end())
+ {
+ // Physical LEDs will be skipped
+ continue;
+ }
+
// Reverse intercept path, Get the name of each member of physical led
// e.g: path = /xyz/openbmc_project/led/physical/front_fan
// name = front_fan
@@ -137,6 +184,16 @@
// Set all the Physical action to On for lamp test
for (const auto& path : physicalLEDPaths)
{
+ auto iter =
+ std::find_if(skipUpdateLEDs.begin(), skipUpdateLEDs.end(),
+ [&path](const auto& skip) { return skip == path; });
+
+ if (iter != skipUpdateLEDs.end())
+ {
+ // Skip update physical path
+ continue;
+ }
+
manager.drivePhysicalLED(path, Layout::Action::On, 0, 0);
}
}
@@ -173,8 +230,8 @@
void LampTest::restorePhysicalLedStates()
{
// restore physical LEDs states before lamp test
- Manager::group savedLEDStatesDeAssert{};
- manager.driveLEDs(physicalLEDStatesPriorToLampTest, savedLEDStatesDeAssert);
+ Manager::group ledsDeAssert{};
+ manager.driveLEDs(physicalLEDStatesPriorToLampTest, ledsDeAssert);
physicalLEDStatesPriorToLampTest.clear();
// restore physical LEDs states during lamp test
@@ -203,5 +260,42 @@
}
}
+void LampTest::getPhysicalLEDNamesFromJson(const fs::path& path)
+{
+ if (!fs::exists(path) || fs::is_empty(path))
+ {
+ log<level::INFO>("The file does not exist or is empty",
+ entry("FILE_PATH=%s", path.c_str()));
+ return;
+ }
+
+ try
+ {
+ std::ifstream jsonFile(path);
+ auto json = Json::parse(jsonFile);
+
+ // define the default JSON as empty
+ const std::vector<std::string> empty{};
+ auto forceLEDs = json.value("forceLEDs", empty);
+ for (auto& member : forceLEDs)
+ {
+ forceUpdateLEDs.push_back(PHY_LED_PATH + member);
+ }
+
+ auto skipLEDs = json.value("skipLEDs", empty);
+ for (auto& member : skipLEDs)
+ {
+ skipUpdateLEDs.push_back(PHY_LED_PATH + member);
+ }
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>("Failed to parse config file",
+ entry("ERROR=%s", e.what()),
+ entry("FILE_PATH=%s", path.c_str()));
+ }
+ return;
+}
+
} // namespace led
} // namespace phosphor
diff --git a/lamptest.hpp b/lamptest.hpp
index 1797dce..d69667a 100644
--- a/lamptest.hpp
+++ b/lamptest.hpp
@@ -1,8 +1,11 @@
#pragma once
+#include "config.h"
+
#include "group.hpp"
#include "manager.hpp"
+#include <nlohmann/json.hpp>
#include <sdeventplus/utility/timer.hpp>
#include <queue>
@@ -37,7 +40,11 @@
LampTest(const sdeventplus::Event& event, Manager& manager) :
timer(event, std::bind(std::mem_fn(&LampTest::timeOutHandler), this)),
manager(manager), groupObj(NULL)
- {}
+ {
+ // Get the force update and/or skipped physical LEDs names from the
+ // lamp-test-led-overrides.json file during lamp
+ getPhysicalLEDNamesFromJson(LAMP_TEST_LED_OVERRIDES_JSON);
+ }
/** @brief the lamp test request handler
*
@@ -86,6 +93,14 @@
/** @brief Physical LED states prior to lamp test */
Manager::group physicalLEDStatesPriorToLampTest;
+ /** @brief Vector of names of physical LEDs, whose changes will be forcibly
+ * updated even during lamp test. */
+ std::vector<std::string> forceUpdateLEDs;
+
+ /** @brief Vector of names of physical LEDs, that will be exempted from lamp
+ * test */
+ std::vector<std::string> skipUpdateLEDs;
+
/** @brief Start and restart lamp test depending on what is the current
* state. */
void start();
@@ -116,6 +131,14 @@
* @param[in] value - the Asserted property value
*/
void doHostLampTest(bool value);
+
+ /** @brief Get physical LED names from lamp test JSON config file
+ *
+ * @param[in] path - path of LED JSON file
+ *
+ * return
+ */
+ void getPhysicalLEDNamesFromJson(const fs::path& path);
};
} // namespace led
diff --git a/manager.cpp b/manager.cpp
index 6219091..eccbc36 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -120,7 +120,6 @@
return;
}
#endif
-
// This order of LED operation is important.
if (ledsDeAssert.size())
{