summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-04-04 14:07:25 +0530
committerVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-04-27 14:42:05 +0530
commit0b95603eb48a72234b8fc618dcc4db13b6f4d079 (patch)
tree627c1ce7766aa3ace52aa6782bbf96fb4cdc9028
parent4902a10c9fabcdf5e1f2868f28cba2d571d55f03 (diff)
downloadphosphor-gpio-monitor-0b95603eb48a72234b8fc618dcc4db13b6f4d079.tar.gz
phosphor-gpio-monitor-0b95603eb48a72234b8fc618dcc4db13b6f4d079.zip
Add sd_event loop and callback handler
Change-Id: I032d1156be2b8082fdf347a60ec883a9bc0038ae Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac1
-rw-r--r--mainapp.cpp19
-rw-r--r--monitor.cpp27
-rw-r--r--monitor.hpp62
5 files changed, 106 insertions, 7 deletions
diff --git a/Makefile.am b/Makefile.am
index 3fe7742..89fa2e4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,5 +7,5 @@ phosphor_gpio_monitor_SOURCES = \
monitor.cpp \
mainapp.cpp
-phosphor_gpio_monitor_LDFLAGS = $(PHOSPHOR_LOGGING_LIBS)
-phosphor_gpio_monitor_CFLAGS = $(PHOSPHOR_LOGGING_CFLAGS)
+phosphor_gpio_monitor_LDFLAGS = $(SYSTEMD_LIBS) $(PHOSPHOR_LOGGING_LIBS)
+phosphor_gpio_monitor_CFLAGS = $(SYSTEMD_CFLAGS) $(PHOSPHOR_LOGGING_CFLAGS)
diff --git a/configure.ac b/configure.ac
index 40100c7..709ed05 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,6 +19,7 @@ AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
LT_INIT
# 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])])
# Create configured output
diff --git a/mainapp.cpp b/mainapp.cpp
index 18bc4ca..6290366 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -16,9 +16,12 @@
#include <iostream>
#include <string>
+#include <systemd/sd-event.h>
+#include <phosphor-logging/log.hpp>
#include "argument.hpp"
#include "monitor.hpp"
+using namespace phosphor::logging;
static void exitWithError(const char* err, char** argv)
{
phosphor::gpio::ArgumentParser::usage(argv);
@@ -59,9 +62,21 @@ int main(int argc, char** argv)
// on meeting a condition.
auto target = (options)["target"];
- // Create a GPIO monitor object and let it do all the rest
+ sd_event* event = nullptr;
+ auto r = sd_event_default(&event);
+ if (r < 0)
+ {
+ log<level::ERR>("Error creating a default sd_event handler");
+ return r;
+ }
+ phosphor::gpio::EventPtr eventP{event};
+ event = nullptr;
+
+ // Create a monitor object and let it do all the rest
phosphor::gpio::Monitor monitor(path, std::stoi(key),
- std::stoi(polarity),target);
+ std::stoi(polarity), target, eventP);
+ // Wait for events
+ sd_event_loop(eventP.get());
return 0;
}
diff --git a/monitor.cpp b/monitor.cpp
index 29d9d6d..5428c09 100644
--- a/monitor.cpp
+++ b/monitor.cpp
@@ -22,6 +22,8 @@ namespace phosphor
namespace gpio
{
+using namespace phosphor::logging;
+
// Populate the file descriptor for passed in device
int Monitor::openDevice()
{
@@ -37,5 +39,30 @@ int Monitor::openDevice()
return fd;
}
+// Attaches the FD to event loop and registers the callback handler
+void Monitor::registerCallback()
+{
+ decltype(eventSource.get()) sourcePtr = nullptr;
+ auto r = sd_event_add_io(event.get(), &sourcePtr, (fd)(),
+ EPOLLIN, callbackHandler, this);
+ eventSource.reset(sourcePtr);
+
+ if (r < 0)
+ {
+ log<level::ERR>("Failed to register callback handler",
+ entry("ERROR=%s", strerror(-r)));
+ throw std::runtime_error("Failed to register callback handler");
+ }
+}
+
+// Callback handler when there is an activity on the FD
+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");
+ return 0;
+}
+
} // namespace gpio
} // namespace phosphor
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 @@ class Monitor
{
public:
Monitor() = delete;
+ ~Monitor() = default;
Monitor(const Monitor&) = delete;
Monitor& operator=(const Monitor&) = delete;
Monitor(Monitor&&) = delete;
@@ -28,20 +51,41 @@ class Monitor
* @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 @@ class Monitor
/** @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
OpenPOWER on IntegriCloud