Support event multi targets
Description:
- Support event multi targets.
Design:
- The origin multi-gpio-monitor doesn't detect the comming events are
rising or falling and it can only start one service after events
triggered.
- We need to do corresponding actions when gpio pin rising or falling.
So we modify multi-gpio-monitor config json and read the rising
actions and falling actions in it.
- When service monitored one gpio status is changed,
service will detect that it is a rising or falling event and then
call systemd startUnit to start services that set in config json.
- For example with config json below:
When PowerGood is falling, "PowerGoodFalling.service"
and "PowerOff.service" will start.
[
{
"Name": "PowerGood",
"ChipId": "0",
"GpioNum": 14,
"EventMon": "BOTH",
"Targets": {
"FALLING": ["PowerGoodFalling.service", "PowerOff.service"],
"RISING": ["PowerGoodRising.service", "PowerOn.service"]
},
"Continue": true
}
]
Test Case:
Check that corresponding targets start or not - pass
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@wiwynn.com>
Change-Id: I043d4385b91a04d360a4d50048320db15e63ac74
diff --git a/README.md b/README.md
index 695cdf8..7851995 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,10 @@
6. Target: This is an optional systemd service which will get started after
triggering event. A journal entry will be added for every event occurs
irrespective of this definition.
-7. Continue: This is a optional flag and if it is defined as true then this gpio
+7. Targets: This is an optional systemd service which will get started after
+ triggering corresponding event(RASING or FALLING). A journal entry will be
+ added for every event occurs irrespective of this definition.
+8. Continue: This is a optional flag and if it is defined as true then this gpio
will be monitored continously. If not defined then monitoring of this gpio
will stop after first event.
@@ -53,13 +56,18 @@
"LineName": "POWER_BUTTON",
"GpioNum": 34,
"ChipId": "gpiochip0",
- "EventMon": "BOTH",
+ "EventMon": "FALLING",
+ "Target": "PowerButtonDown.service",
"Continue": true
},
{
"Name": "PowerGood",
"LineName": "PS_PWROK",
- "EventMon": "FALLING",
+ "EventMon": "BOTH",
+ "Targets": {
+ "FALLING": ["PowerGoodFalling.service", "PowerOff.service"],
+ "RISING": ["PowerGoodRising.service", "PowerOn.service"]
+ },
"Continue": false
},
{ "Name": "SystemReset", "GpioNum": 46, "ChipId": "0" }
diff --git a/gpioMon.cpp b/gpioMon.cpp
index 2ab079a..fcdf8f5 100644
--- a/gpioMon.cpp
+++ b/gpioMon.cpp
@@ -29,6 +29,9 @@
constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
+constexpr auto falling = "FALLING";
+constexpr auto rising = "RISING";
+
using namespace phosphor::logging;
void GpioMonitor::scheduleEventHandler()
@@ -79,6 +82,37 @@
bus.call_noreply(method);
}
+ std::vector<std::string> targetsToStart;
+ if (gpioLineEvent.event_type == GPIOD_LINE_EVENT_RISING_EDGE)
+ {
+ auto risingFind = targets.find(rising);
+ if (risingFind != targets.end())
+ {
+ targetsToStart = risingFind->second;
+ }
+ }
+ else
+ {
+ auto fallingFind = targets.find(falling);
+ if (fallingFind != targets.end())
+ {
+ targetsToStart = fallingFind->second;
+ }
+ }
+
+ /* Execute the multi targets if it is defined. */
+ if (!targetsToStart.empty())
+ {
+ auto bus = sdbusplus::bus::new_default();
+ for (auto& tar : targetsToStart)
+ {
+ auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
+ SYSTEMD_INTERFACE, "StartUnit");
+ method.append(tar, "replace");
+ bus.call_noreply(method);
+ }
+ }
+
/* if not required to continue monitoring then return */
if (!continueAfterEvent)
{
diff --git a/gpioMon.hpp b/gpioMon.hpp
index 51772ab..5750d39 100644
--- a/gpioMon.hpp
+++ b/gpioMon.hpp
@@ -4,6 +4,8 @@
#include <boost/asio/io_context.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
+#include <map>
+#include <vector>
namespace phosphor
{
@@ -31,15 +33,18 @@
* @param[in] io - io service
* @param[in] target - systemd unit to be started on GPIO
* value change
+ * @param[in] targets - systemd units to be started on GPIO
+ * value change
* @param[in] lineMsg - GPIO line message to be used for log
* @param[in] continueRun - Whether to continue after event occur
*/
GpioMonitor(gpiod_line* line, gpiod_line_request_config& config,
boost::asio::io_context& io, const std::string& target,
+ const std::map<std::string, std::vector<std::string>>& targets,
const std::string& lineMsg, bool continueRun) :
gpioLine(line),
gpioConfig(config), gpioEventDescriptor(io), target(target),
- gpioLineMsg(lineMsg), continueAfterEvent(continueRun)
+ targets(targets), gpioLineMsg(lineMsg), continueAfterEvent(continueRun)
{
requestGPIOEvents();
};
@@ -57,6 +62,9 @@
/** @brief Systemd unit to be started when the condition is met */
const std::string target;
+ /** @brief Multi systemd units to be started when the condition is met */
+ std::map<std::string, std::vector<std::string>> targets;
+
/** @brief GPIO line name message */
std::string gpioLineMsg;
diff --git a/gpioMonMain.cpp b/gpioMonMain.cpp
index bb30a8e..8530ffc 100644
--- a/gpioMonMain.cpp
+++ b/gpioMonMain.cpp
@@ -103,6 +103,9 @@
/* target to start */
std::string target;
+ /* multi targets to start */
+ std::map<std::string, std::vector<std::string>> targets;
+
if (obj.find("LineName") == obj.end())
{
/* If there is no line Name defined then gpio num nd chip
@@ -173,9 +176,15 @@
target = obj["Target"];
}
+ /* Parse out the targets argument if multi-targets are needed.*/
+ if (obj.find("Targets") != obj.end())
+ {
+ obj.at("Targets").get_to(targets);
+ }
+
/* Create a monitor object and let it do all the rest */
gpios.push_back(std::make_unique<phosphor::gpio::GpioMonitor>(
- line, config, io, target, lineMsg, flag));
+ line, config, io, target, targets, lineMsg, flag));
}
io.run();