summaryrefslogtreecommitdiffstats
path: root/monitor.cpp
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 /monitor.cpp
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>
Diffstat (limited to 'monitor.cpp')
-rw-r--r--monitor.cpp95
1 files changed, 77 insertions, 18 deletions
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
OpenPOWER on IntegriCloud