From 77ec47996d0c8b78d0f08d17fed8ff03107a1e03 Mon Sep 17 00:00:00 2001 From: Vishwanatha Subbanna Date: Mon, 10 Apr 2017 15:43:47 +0530 Subject: Use libevdev for monitoring GPIO state change Change-Id: I962af3034586f027e6ba74387dcda6ef0cf3672e Signed-off-by: Vishwanatha Subbanna --- monitor.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 18 deletions(-) (limited to 'monitor.cpp') 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("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("GPIO line altered"); auto monitor = static_cast(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 -- cgit v1.2.1