Add sd_event loop and callback handler

Change-Id: I032d1156be2b8082fdf347a60ec883a9bc0038ae
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/monitor.hpp b/monitor.hpp
index 9e3992d..1027714 100644
--- a/monitor.hpp
+++ b/monitor.hpp
@@ -3,11 +3,33 @@
 #include <unistd.h>
 #include <string>
 #include <linux/input.h>
+#include <systemd/sd-event.h>
 #include "file.hpp"
 namespace phosphor
 {
 namespace gpio
 {
+
+/* Need a custom deleter for freeing up sd_event */
+struct EventDeleter
+{
+    void operator()(sd_event* event) const
+    {
+        event = sd_event_unref(event);
+    }
+};
+using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
+
+/* Need a custom deleter for freeing up sd_event_source */
+struct EventSourceDeleter
+{
+    void operator()(sd_event_source* eventSource) const
+    {
+        eventSource = sd_event_source_unref(eventSource);
+    }
+};
+using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
+
 /** @class Monitor
  *  @brief Responsible for catching GPIO state change
  *  condition and taking actions
@@ -16,6 +38,7 @@
 {
     public:
         Monitor() = delete;
+        ~Monitor() = default;
         Monitor(const Monitor&) = delete;
         Monitor& operator=(const Monitor&) = delete;
         Monitor(Monitor&&) = delete;
@@ -28,20 +51,41 @@
          *  @param[in] polarity - GPIO assertion polarity to look for
          *  @param[in] target   - systemd unit to be started on GPIO
          *                        value change
+         *  @param[in] event    - sd_event handler
+         *  @param[in] handler  - IO callback handler. Defaults to one in this
+         *                        class
          */
         Monitor(const std::string& path,
                 decltype(input_event::code) key,
                 decltype(input_event::value) polarity,
-                const std::string& target)
+                const std::string& target,
+                EventPtr& event,
+                sd_event_io_handler_t handler = Monitor::processEvents)
             : path(path),
               key(key),
               polarity(polarity),
               target(target),
+              event(event),
+              callbackHandler(handler),
               fd(openDevice())
         {
-            // Nothing
+            // And register callback handler when FD has some data
+            registerCallback();
         }
 
+        /** @brief Callback handler when the FD has some activity on it
+         *
+         *  @param[in] es       - Populated event source
+         *  @param[in] fd       - Associated File descriptor
+         *  @param[in] revents  - Type of event
+         *  @param[in] userData - User data that was passed during registration
+         *
+         *  @return             - 0 or positive number on success and negative
+         *                        errno otherwise
+         */
+        static int processEvents(sd_event_source* es, int fd,
+                                 uint32_t revents, void* userData);
+
     private:
         /** @brief Absolute path of GPIO input device */
         const std::string& path;
@@ -55,11 +99,23 @@
         /** @brief Systemd unit to be started when the condition is met */
         const std::string& target;
 
-        /** @brief Manages File descriptor */
+        /** @brief Monitor to sd_event */
+        EventPtr& event;
+
+        /** @brief event source */
+        EventSourcePtr eventSource;
+
+        /** @brief Callback handler when the FD has some data */
+        sd_event_io_handler_t callbackHandler;
+
+        /** @brief File descriptor manager */
         FileDescriptor fd;
 
         /** @brief Opens the device and populates the descriptor */
         int openDevice();
+
+        /** @brief attaches FD to events and sets up callback handler */
+        void registerCallback();
 };
 
 } // namespace gpio