diff options
author | ChromeOS Developer <dparker@chromium.org> | 2014-01-11 11:13:39 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-02-07 04:13:18 +0000 |
commit | 86eea83ceee8004c6120a759b35cf88745e548a7 (patch) | |
tree | 78791b1e8858015af5683f15bcd659002a612927 /common/button.c | |
parent | 4015172ed1b8a93350e433deb3399693ff4e00ed (diff) | |
download | chrome-ec-86eea83ceee8004c6120a759b35cf88745e548a7.tar.gz |
Add support for extra buttons not on the keyboard
BUG=chrome-os-partner:24370
BRANCH=tot
TEST=Run button unit test.
Orig-Change-Id: I61b4a6624d62831ce0bfdf7a0f36a45349b37f96
Signed-off-by: Dave Parker <dparker@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/184544
Reviewed-by: Randall Spangler <rspangler@chromium.org>
(cherry picked from commit f6426cc21c20a4f876cff28b9ce7e3115f0b054a)
Change-Id: I4face9bf0797a91ec8bef390093aab8e3d8f97ab
Reviewed-on: https://chromium-review.googlesource.com/185243
Tested-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Queue: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common/button.c')
-rw-r--r-- | common/button.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/common/button.c b/common/button.c new file mode 100644 index 0000000000..2e48102dd3 --- /dev/null +++ b/common/button.c @@ -0,0 +1,127 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Button module for Chrome EC */ + +#include "button.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "keyboard_protocol.h" +#include "timer.h" +#include "util.h" + +/* Console output macro */ +#define CPRINTF(format, args...) cprintf(CC_SWITCH, format, ## args) + +struct button_state_t { + uint64_t debounce_time; + int debounced_pressed; +}; + +static struct button_state_t state[CONFIG_BUTTON_COUNT]; + +static uint64_t next_deferred_time; + +/* + * Whether a button is currently pressed. + */ +static int raw_button_pressed(const struct button_config *button) +{ + int raw_value = gpio_get_level(button->gpio); + + return button->flags & BUTTON_FLAG_ACTIVE_HIGH ? + raw_value : !raw_value; +} + +/* + * Button initialization. + */ +static void button_init(void) +{ + int i; + + CPRINTF("[%T (re)initializing buttons and interrupts.]\n"); + next_deferred_time = 0; + for (i = 0; i < CONFIG_BUTTON_COUNT; i++) { + state[i].debounced_pressed = raw_button_pressed(&buttons[i]); + state[i].debounce_time = 0; + gpio_enable_interrupt(buttons[i].gpio); + } +} +DECLARE_HOOK(HOOK_INIT, button_init, HOOK_PRIO_DEFAULT); + +/* + * Handle debounced button changing state. + */ +static void button_change_deferred(void) +{ + int i; + int new_pressed; + uint64_t soonest_debounce_time = 0; + uint64_t time_now = get_time().val; + + for (i = 0; i < CONFIG_BUTTON_COUNT; i++) { + /* Skip this button if we are not waiting to debounce */ + if (state[i].debounce_time == 0) + continue; + + if (state[i].debounce_time <= time_now) { + /* Check if the state has changed */ + new_pressed = raw_button_pressed(&buttons[i]); + if (state[i].debounced_pressed != new_pressed) { + state[i].debounced_pressed = new_pressed; + CPRINTF("[%T Button '%s' was %s]\n", + buttons[i].name, new_pressed ? + "pressed" : "released"); + keyboard_update_button(buttons[i].type, + new_pressed); + } + + /* Clear the debounce time to stop checking it */ + state[i].debounce_time = 0; + } else { + /* + * Make sure the next deferred call happens on or before + * each button needs it. + */ + soonest_debounce_time = (soonest_debounce_time == 0) ? + state[i].debounce_time : + MIN(soonest_debounce_time, + state[i].debounce_time); + } + } + + if (soonest_debounce_time != 0) { + next_deferred_time = soonest_debounce_time; + hook_call_deferred(button_change_deferred, + next_deferred_time - time_now); + } +} +DECLARE_DEFERRED(button_change_deferred); + +/* + * Handle a button interrupt. + */ +void button_interrupt(enum gpio_signal signal) +{ + int i; + uint64_t time_now = get_time().val; + + for (i = 0; i < CONFIG_BUTTON_COUNT; i++) { + if (buttons[i].gpio != signal) + continue; + + state[i].debounce_time = time_now + buttons[i].debounce_us; + if (next_deferred_time <= time_now || + next_deferred_time > state[i].debounce_time) { + next_deferred_time = state[i].debounce_time; + hook_call_deferred(button_change_deferred, + next_deferred_time - time_now); + } + break; + } +} |