diff options
author | Bertrand SIMONNET <bsimonnet@google.com> | 2016-03-07 14:22:09 -0800 |
---|---|---|
committer | Bertrand Simonnet <bsimonnet@google.com> | 2016-03-10 21:01:57 +0000 |
commit | d3cafe115bdde62957bd3b95fd000e6dae1b1c49 (patch) | |
tree | 05f16cb18c36f2423310fb523b0e7834bf58807b /example | |
parent | 0a407224a1e2b6f15fb56386f8a2633a703417e3 (diff) | |
download | peripheralmanager-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.mk | 27 | ||||
-rw-r--r-- | example/gpio_flip_example.cc (renamed from example/peripheralmanager_example.cc) | 0 | ||||
-rw-r--r-- | example/gpio_interrupt_example.cc | 114 |
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; +} |