summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-04-10 15:43:47 +0530
committerVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-04-27 14:42:10 +0530
commit77ec47996d0c8b78d0f08d17fed8ff03107a1e03 (patch)
tree2167a88b66797894a78cd2dbd39c0ba949194712
parentd7f9cd1f7033e4a544d14a91546e26cabe84d7af (diff)
downloadphosphor-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.am11
-rw-r--r--configure.ac1
-rw-r--r--monitor.cpp95
-rw-r--r--monitor.hpp24
-rw-r--r--test/Makefile.am5
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
OpenPOWER on IntegriCloud