aboutsummaryrefslogtreecommitdiff
path: root/example
diff options
context:
space:
mode:
authorBertrand SIMONNET <bsimonnet@google.com>2016-03-07 14:22:09 -0800
committerBertrand Simonnet <bsimonnet@google.com>2016-03-10 21:01:57 +0000
commitd3cafe115bdde62957bd3b95fd000e6dae1b1c49 (patch)
tree05f16cb18c36f2423310fb523b0e7834bf58807b /example
parent0a407224a1e2b6f15fb56386f8a2633a703417e3 (diff)
downloadperipheralmanager-d3cafe115bdde62957bd3b95fd000e6dae1b1c49.tar.gz
Add a helper to acknowledge a GPIO interrupt.
When an interrupt triggers on a GPIO, we must lseek and read the value in order to be able to poll again. As we don't guarantee that the file descriptor we use to poll will be the value file, add a convenience function to reset the file descriptor's state. To illustrate how to use it, we provide an example that will watch a GPIO for interrupt and print a message when the GPIO's value changes. This is implemented with both select and poll. Bug: 26778811 Change-Id: Ib25338599a8e08d7734839171da6204bb64a2ded
Diffstat (limited to 'example')
-rw-r--r--example/Android.mk27
-rw-r--r--example/gpio_flip_example.cc (renamed from example/peripheralmanager_example.cc)0
-rw-r--r--example/gpio_interrupt_example.cc114
3 files changed, 138 insertions, 3 deletions
diff --git a/example/Android.mk b/example/Android.mk
index c3e1ddd..56b5cb0 100644
--- a/example/Android.mk
+++ b/example/Android.mk
@@ -16,11 +16,11 @@
LOCAL_PATH := $(call my-dir)
-# peripheralmanager_example executable
+# Flips a GPIO on and off.
# ========================================================
include $(CLEAR_VARS)
-LOCAL_MODULE := peripheralmanager_example
+LOCAL_MODULE := peripheralman_gpio_flip
LOCAL_CPP_EXTENSION := .cc
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
LOCAL_CFLAGS += -Wno-sign-promo # for libchrome
@@ -33,7 +33,28 @@ LOCAL_SHARED_LIBRARIES := \
libutils \
LOCAL_SRC_FILES := \
- peripheralmanager_example.cc \
+ gpio_flip_example.cc \
+
+include $(BUILD_EXECUTABLE)
+
+# Watches the state of a gpio with interrupts.
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := peripheralman_gpio_interrupt
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libbinderwrapper \
+ libbrillo \
+ libchrome \
+ libperipheralman \
+ libutils \
+
+LOCAL_SRC_FILES := \
+ gpio_interrupt_example.cc \
include $(BUILD_EXECUTABLE)
diff --git a/example/peripheralmanager_example.cc b/example/gpio_flip_example.cc
index 36f5979..36f5979 100644
--- a/example/peripheralmanager_example.cc
+++ b/example/gpio_flip_example.cc
diff --git a/example/gpio_interrupt_example.cc b/example/gpio_interrupt_example.cc
new file mode 100644
index 0000000..e681fa5
--- /dev/null
+++ b/example/gpio_interrupt_example.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <poll.h>
+#include <sys/select.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include <base/at_exit.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <base/sys_info.h>
+#include <base/time/time.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+int main(int argc, char* argv[]) {
+ DEFINE_string(pin, "", "Pin to watch");
+ DEFINE_bool(select, false, "Use select instead of poll");
+ brillo::FlagHelper::Init(argc, argv, "Watches a GPIO.");
+ logging::InitLogging(logging::LoggingSettings());
+ android::BinderWrapper::Create();
+
+ std::string pin_name = "IO1";
+ if (!FLAGS_pin.empty())
+ pin_name = FLAGS_pin;
+
+ // Get a client to the PeripheralManager.
+ BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+ if (!client) {
+ LOG(ERROR) << "Failed to connect to client";
+ return 1;
+ }
+
+ // Open GPIO pin.
+ BGpio* my_gpio;
+ if (BPeripheralManagerClient_openGpio(client, pin_name.c_str(), &my_gpio)) {
+ LOG(ERROR) << "Failed to open Gpio";
+ return 1;
+ }
+
+ // Set the direction to in.
+ if (BGpio_setDirection(my_gpio, DIRECTION_IN)) {
+ LOG(ERROR) << "Failed to set gpio pin direction";
+ return 1;
+ }
+
+ // Set the edge trigger type for interrupts.
+ if (BGpio_setEdgeTriggerType(my_gpio, BOTH_EDGE)) {
+ LOG(ERROR) << "failed to set the edge type";
+ return 1;
+ }
+
+ // Get the file descriptor used to poll for data.
+ int fd = -1;
+ if (BGpio_getPollingFd(my_gpio, &fd)) {
+ LOG(ERROR) << "failed to get the fd";
+ return 1;
+ }
+
+ if (FLAGS_select) {
+ fd_set ifds;
+ FD_ZERO(&ifds);
+ FD_SET(fd, &ifds);
+
+ for (int i = 0; i < 30; i++) {
+ select(fd + 1, NULL, NULL, &ifds, NULL);
+ LOG(INFO) << "received event";
+ BGpio_ackInterruptEvent(fd);
+ }
+ } else {
+ struct pollfd poller = {
+ .fd = fd,
+ .events = POLLPRI | POLLERR,
+ .revents = 0,
+ };
+
+ for (int i = 0; i < 30; i++) {
+ // Poll with no timeout.
+ poll(&poller, 1, -1);
+ LOG(INFO) << "received an event ";
+ BGpio_ackInterruptEvent(fd);
+ poller.revents = 0;
+ }
+ }
+
+ close(fd);
+
+ // Release the gpio pin
+ BGpio_delete(my_gpio);
+
+ // Close the connection to PeripheralManager.
+ BPeripheralManagerClient_delete(client);
+
+ LOG(INFO) << "Exiting";
+ return 0;
+}