diff options
author | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-04-10 15:43:47 +0530 |
---|---|---|
committer | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-04-27 14:42:10 +0530 |
commit | 77ec47996d0c8b78d0f08d17fed8ff03107a1e03 (patch) | |
tree | 2167a88b66797894a78cd2dbd39c0ba949194712 | |
parent | d7f9cd1f7033e4a544d14a91546e26cabe84d7af (diff) | |
download | phosphor-gpio-monitor-77ec47996d0c8b78d0f08d17fed8ff03107a1e03.tar.gz phosphor-gpio-monitor-77ec47996d0c8b78d0f08d17fed8ff03107a1e03.zip |
Use libevdev for monitoring GPIO state change
Change-Id: I962af3034586f027e6ba74387dcda6ef0cf3672e
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | monitor.cpp | 95 | ||||
-rw-r--r-- | monitor.hpp | 24 | ||||
-rw-r--r-- | test/Makefile.am | 5 |
5 files changed, 107 insertions, 29 deletions
diff --git a/Makefile.am b/Makefile.am index 93273d8..3e55c5b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,9 +9,12 @@ phosphor_gpio_monitor_SOURCES = \ phosphor_gpio_monitor_LDFLAGS = $(SYSTEMD_LIBS) \ $(SDBUSPLUS_LIBS) \ - $(PHOSPHOR_LOGGING_LIBS) -phosphor_gpio_monitor_CFLAGS = $(SYSTEMD_CFLAGS) \ - $(SDBUSPLUS_CFLAGS) \ - $(PHOSPHOR_LOGGING_CFLAGS) + $(PHOSPHOR_LOGGING_LIBS) \ + $(LIBEVDEV_LIBS) + +phosphor_gpio_monitor_CXXFLAGS = $(SYSTEMD_CFLAGS) \ + $(SDBUSPLUS_CFLAGS) \ + $(PHOSPHOR_LOGGING_CFLAGS) \ + $(LIBEVDEV_CFLAGS) SUBDIRS = test diff --git a/configure.ac b/configure.ac index 694d2b3..4a05a22 100644 --- a/configure.ac +++ b/configure.ac @@ -22,6 +22,7 @@ PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221], ,[AC_MSG_ERROR([Could not find 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])]) +PKG_CHECK_MODULES([LIBEVDEV], [libevdev],, [AC_MSG_ERROR([Could not find libevdev...libevdev package required])]) # Check/set gtest specific functions. AX_PTHREAD([GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=1"],[GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=0"]) diff --git a/monitor.cpp b/monitor.cpp index 99eed03..dfd9987 100644 --- a/monitor.cpp +++ b/monitor.cpp @@ -62,37 +62,96 @@ void Monitor::registerCallback() } } +// Initializes the event device with the fd +void Monitor::initEvDev() +{ + if (device) + { + // Init can be done only once per device + return; + } + + struct libevdev* evdev = nullptr; + auto rc = libevdev_new_from_fd((fd)(), &evdev); + if (rc < 0) + { + log<level::ERR>("Failed to initialize evdev"); + throw std::runtime_error("Failed to initialize evdev"); + } + + // Packing in the unique_ptr + device.reset(evdev); + evdev = nullptr; +} + // Callback handler when there is an activity on the FD int Monitor::processEvents(sd_event_source* es, int fd, uint32_t revents, void* userData) { 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(); + + // Initialize libevdev for this. Doing it here enables + // gtest to use this infrastructure on arbitrary device + // than /dev/input/ + monitor->initEvDev(); + monitor->analyzeEvent(); + return 0; } // Analyzes the GPIO event -int Monitor::analyzeEvent() +void Monitor::analyzeEvent() { - if(!target.empty()) + // Data returned + struct input_event ev{}; + int rc = 0; + + // While testing, observed that not having a loop here was leading + // into events being missed. + while (rc >= 0) { - 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); - } + // Wait until no more events are available on the device. + rc = libevdev_next_event(device.get(), + LIBEVDEV_READ_FLAG_NORMAL, &ev); + if (rc < 0) + { + // There was an error waiting for events, mostly that there are no + // events to be read.. So continue waiting... + return; + }; - // This marks the completion of handling the checkstop and app can exit - complete = true; + if (rc == LIBEVDEV_READ_STATUS_SUCCESS) + { + if (ev.type == EV_SYN && ev.code == SYN_REPORT) + { + continue; + } + else if (ev.code == key && ev.value == polarity) + { + // If the code/value is what we are interested in, declare done. + // User supplied systemd unit + 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"); - return 0; + bus.call_noreply(method); + } + + // This marks the completion of handling the gpio assertion + // and the app can exit + complete = true; + return; + } + } + }; + + return; } } // namespace gpio diff --git a/monitor.hpp b/monitor.hpp index 34803c1..68bf447 100644 --- a/monitor.hpp +++ b/monitor.hpp @@ -3,6 +3,7 @@ #include <unistd.h> #include <string> #include <linux/input.h> +#include <libevdev/libevdev.h> #include <systemd/sd-event.h> #include <sdbusplus/bus.hpp> #include "file.hpp" @@ -31,6 +32,16 @@ struct EventSourceDeleter }; using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>; +/* Need a custom deleter for freeing up evdev struct */ +struct EvdevDeleter +{ + void operator()(struct libevdev* device) const + { + libevdev_free(device); + } +}; +using EvdevPtr = std::unique_ptr<struct libevdev, EvdevDeleter>; + /** @class Monitor * @brief Responsible for catching GPIO state change * condition and taking actions @@ -118,6 +129,9 @@ class Monitor /** @brief File descriptor manager */ FileDescriptor fd; + /** event structure */ + EvdevPtr device; + /** @brief Completion indicator */ bool complete = false; @@ -127,11 +141,11 @@ class Monitor /** @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(); + /** @brief Analyzes the GPIO event and starts configured target */ + void analyzeEvent(); + + /** @brief Initializes evdev handle with the fd */ + void initEvDev(); }; } // namespace gpio diff --git a/test/Makefile.am b/test/Makefile.am index db82844..5bd15e7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,12 +1,13 @@ AM_CPPFLAGS = -I$(top_srcdir) +AM_CXXFLAGS = $(LIBEVDEV_CFLAGS) # Run all 'check' test programs TESTS = $(check_PROGRAMS) # # Build/add utest to test suite check_PROGRAMS = utest -utest_CPPFLAGS = -Igtest $(GTEST_CPPFLAGS) $(AM_CPPFLAGS) $(SDBUSPLUS_CFLAGS) $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) +utest_CPPFLAGS = -Igtest $(GTEST_CPPFLAGS) $(AM_CPPFLAGS) $(PHOSPHOR_LOGGING_CFLAGS) $(LIBEVDEV_CFLAGS) utest_CXXFLAGS = $(PTHREAD_CFLAGS) -utest_LDFLAGS = -lgtest_main -lgtest $(PTHREAD_LIBS) $(OESDK_TESTCASE_FLAGS) $(SYSTEMD_LIBS) $(SDBUSPLUS_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS) +utest_LDFLAGS = -lgtest_main -lgtest $(PTHREAD_LIBS) $(OESDK_TESTCASE_FLAGS) $(SYSTEMD_LIBS) $(PHOSPHOR_LOGGING_LIBS) $(LIBEVDEV_LIBS) utest_SOURCES = utest.cpp utest_LDADD = $(top_builddir)/monitor.o |