Add capability of handling GPIO initial values

The edge handling currently allows us to monitor
changes after the service has started. But, a GPIO
could have changed state when the BMC/service is
down and thus potentially missing an error condition.

To address this, two additional keys "INIT_HIGH" and
"INIT_LOW" are added. which will be called at start-up
depending on the current GPIO value.

Tested: Tested on QEMU with a test configuration
and ensured that the systemd units are called
correctly.

Change-Id: I8a6c969b9609080cf0846611831206376fd96c7d
Signed-off-by: Amithash Prasad <amithash@meta.com>
diff --git a/README.md b/README.md
index f66fc1a..b8d9704 100644
--- a/README.md
+++ b/README.md
@@ -41,10 +41,12 @@
    triggering event. A journal entry will be added for every event occurs
    irrespective of this definition.
 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.
+   triggering corresponding event(RISING or FALLING). A journal entry will be
+   added for every event occurs irrespective of this definition. Upon start up,
+   depending on the current GPIO value, the systemd services for INIT_HIGH and
+   INIT_LOW will be called (if defined).
 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 be monitored continuously. If not defined then monitoring of this gpio
    will stop after first event.
 
 #### Sample config file
diff --git a/gpioMon.cpp b/gpioMon.cpp
index 3648556..20805cd 100644
--- a/gpioMon.cpp
+++ b/gpioMon.cpp
@@ -31,6 +31,8 @@
 
 constexpr auto falling = "FALLING";
 constexpr auto rising = "RISING";
+constexpr auto init_high = "INIT_HIGH";
+constexpr auto init_low = "INIT_LOW";
 
 void GpioMonitor::scheduleEventHandler()
 {
@@ -120,6 +122,22 @@
     scheduleEventHandler();
 }
 
+void GpioMonitor::gpioHandleInitialState(bool value)
+{
+    if (auto itr = targets.find(value ? init_high : init_low);
+        itr != targets.end())
+    {
+        auto bus = sdbusplus::bus::new_default();
+        for (const auto& tar : itr->second)
+        {
+            auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
+                                              SYSTEMD_INTERFACE, "StartUnit");
+            method.append(tar, "replace");
+            bus.call_noreply(method);
+        }
+    }
+}
+
 int GpioMonitor::requestGPIOEvents()
 {
     /* Request an event to monitor for respected gpio line */
@@ -136,6 +154,17 @@
         return -1;
     }
 
+    int value = gpiod_line_get_value(gpioLine);
+    if (value < 0)
+    {
+        lg2::error("Failed to get value for {GPIO} Error: {ERROR}", "GPIO",
+                   gpioLineMsg, "ERROR", strerror(errno));
+    }
+    else
+    {
+        gpioHandleInitialState(value != 0);
+    }
+
     lg2::info("{GPIO} monitoring started", "GPIO", gpioLineMsg);
 
     /* Assign line fd to descriptor for monitoring */
diff --git a/gpioMon.hpp b/gpioMon.hpp
index 9f059f0..2add08c 100644
--- a/gpioMon.hpp
+++ b/gpioMon.hpp
@@ -83,6 +83,9 @@
 
     /** @brief Handle the GPIO event and starts configured target */
     void gpioEventHandler();
+
+    /** @brief handle current gpio value */
+    void gpioHandleInitialState(bool value);
 };
 
 } // namespace gpio