Call defined target when GPIO line is asserted

Change-Id: Ia5445a8d6585acfec69783ba158c8d866d526e97
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 89fa2e4..777dffc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,5 +7,9 @@
 				monitor.cpp \
 				mainapp.cpp
 
-phosphor_gpio_monitor_LDFLAGS = $(SYSTEMD_LIBS) $(PHOSPHOR_LOGGING_LIBS)
-phosphor_gpio_monitor_CFLAGS = $(SYSTEMD_CFLAGS) $(PHOSPHOR_LOGGING_CFLAGS)
+phosphor_gpio_monitor_LDFLAGS = $(SYSTEMD_LIBS) \
+                                $(SDBUSPLUS_LIBS) \
+                                $(PHOSPHOR_LOGGING_LIBS)
+phosphor_gpio_monitor_CFLAGS = $(SYSTEMD_CFLAGS) \
+                               $(SDBUSPLUS_CFLAGS) \
+                               $(PHOSPHOR_LOGGING_CFLAGS)
diff --git a/configure.ac b/configure.ac
index 709ed05..c80d778 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,6 +21,8 @@
 # Checks for modules
 PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221], ,[AC_MSG_ERROR([Could not find systemd...systemd developement package required])])
 PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],, [AC_MSG_ERROR([Could not find phosphor-logging...openbmc/phosphor-logging package required])])
+PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, [AC_MSG_ERROR([Could not find sdbusplus...openbmc/sdbusplus package required])])
+PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],, [AC_MSG_ERROR([Could not find phosphor-dbus-interfaces...openbmc/phosphor-dbus-interfaces package required])])
 
 # Create configured output
 AC_CONFIG_FILES([Makefile])
diff --git a/mainapp.cpp b/mainapp.cpp
index 6290366..1dd7e80 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -75,8 +75,20 @@
     // Create a monitor object and let it do all the rest
     phosphor::gpio::Monitor monitor(path, std::stoi(key),
                                     std::stoi(polarity), target, eventP);
-    // Wait for events
-    sd_event_loop(eventP.get());
+
+    // Wait for client requests until this application has processed
+    // at least one expected GPIO state change
+    while(!monitor.completed())
+    {
+        // -1 denotes wait for ever
+        r = sd_event_run(eventP.get(), (uint64_t)-1);
+        if (r < 0)
+        {
+            log<level::ERR>("Failure in processing request",
+                    entry("ERROR=%s", strerror(-r)));
+            break;
+        }
+    }
 
     return 0;
 }
diff --git a/monitor.cpp b/monitor.cpp
index 5428c09..99eed03 100644
--- a/monitor.cpp
+++ b/monitor.cpp
@@ -17,11 +17,18 @@
 #include <fcntl.h>
 #include <phosphor-logging/log.hpp>
 #include "monitor.hpp"
+#include "config.h"
+
 namespace phosphor
 {
 namespace gpio
 {
 
+// systemd service to kick start a target.
+constexpr auto SYSTEMD_SERVICE        = "org.freedesktop.systemd1";
+constexpr auto SYSTEMD_ROOT           = "/org/freedesktop/systemd1";
+constexpr auto SYSTEMD_INTERFACE      = "org.freedesktop.systemd1.Manager";
+
 using namespace phosphor::logging;
 
 // Populate the file descriptor for passed in device
@@ -59,8 +66,32 @@
 int Monitor::processEvents(sd_event_source* es, int fd,
                            uint32_t revents, void* userData)
 {
-    // TODO. This calls into starting configured target
-    log<level::INFO>("Callback handler called");
+    log<level::INFO>("GPIO line altered");
+    auto monitor = static_cast<Monitor*>(userData);
+    // TODO : Need a way to check if the GPIO state change is what we wanted
+    return monitor->analyzeEvent();
+}
+
+// Analyzes the GPIO event
+int Monitor::analyzeEvent()
+{
+    if(!target.empty())
+    {
+        auto bus = sdbusplus::bus::new_default();
+        auto method = bus.new_method_call(SYSTEMD_SERVICE,
+                                          SYSTEMD_ROOT,
+                                          SYSTEMD_INTERFACE,
+                                          "StartUnit");
+        method.append(target);
+        method.append("replace");
+
+        // If there is any error, an exception would be thrown from here.
+        bus.call_noreply(method);
+    }
+
+    // This marks the completion of handling the checkstop and app can exit
+    complete = true;
+
     return 0;
 }
 
diff --git a/monitor.hpp b/monitor.hpp
index 1027714..34803c1 100644
--- a/monitor.hpp
+++ b/monitor.hpp
@@ -4,6 +4,7 @@
 #include <string>
 #include <linux/input.h>
 #include <systemd/sd-event.h>
+#include <sdbusplus/bus.hpp>
 #include "file.hpp"
 namespace phosphor
 {
@@ -86,6 +87,12 @@
         static int processEvents(sd_event_source* es, int fd,
                                  uint32_t revents, void* userData);
 
+        /** @brief Returns the completion state of this handler */
+        inline auto completed() const
+        {
+            return complete;
+        }
+
     private:
         /** @brief Absolute path of GPIO input device */
         const std::string& path;
@@ -111,11 +118,20 @@
         /** @brief File descriptor manager */
         FileDescriptor fd;
 
+        /** @brief Completion indicator */
+        bool complete = false;
+
         /** @brief Opens the device and populates the descriptor */
         int openDevice();
 
         /** @brief attaches FD to events and sets up callback handler */
         void registerCallback();
+
+        /** @brief Analyzes the GPIO event and starts configured target
+         *
+         *  @return - For now, returns zero
+         */
+        int analyzeEvent();
 };
 
 } // namespace gpio