summaryrefslogtreecommitdiff
path: root/common/capsense.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/capsense.c')
-rw-r--r--common/capsense.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/common/capsense.c b/common/capsense.c
new file mode 100644
index 0000000000..e0df749933
--- /dev/null
+++ b/common/capsense.c
@@ -0,0 +1,86 @@
+/* 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.
+ */
+
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "keyboard_protocol.h"
+#include "timer.h"
+
+/* Console output macro */
+#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args)
+
+#define CAPSENSE_I2C_ADDR 0x08
+#define CAPSENSE_MASK_BITS 8
+#define CAPSENSE_POLL_INTERVAL (20 * MSEC)
+
+static int capsense_read_bitmask(void)
+{
+ int rv;
+ uint8_t val = 0;
+
+ i2c_lock(I2C_PORT_CAPSENSE, 1);
+ rv = i2c_xfer(I2C_PORT_CAPSENSE, CAPSENSE_I2C_ADDR,
+ 0, 0, &val, 1, I2C_XFER_SINGLE);
+ i2c_lock(I2C_PORT_CAPSENSE, 0);
+
+ if (rv)
+ CPRINTF("[%T %s failed: error %d]\n", __func__, rv);
+
+ return val;
+}
+
+static void capsense_init(void)
+{
+ gpio_enable_interrupt(GPIO_CAPSENSE_INT_L);
+}
+DECLARE_HOOK(HOOK_INIT, capsense_init, HOOK_PRIO_DEFAULT);
+
+/*
+ * Keep checking polling the capsense until all the buttons are released.
+ * We're not worrying about debouncing, since the capsense module should do
+ * that for us.
+ */
+static void capsense_change_deferred(void)
+{
+ static uint8_t cur_val;
+ uint8_t new_val;
+ int i, n, c;
+
+ new_val = capsense_read_bitmask();
+ if (new_val != cur_val) {
+ CPRINTF("[%T capsense 0x%02x: ", new_val);
+ for (i = 0; i < CAPSENSE_MASK_BITS; i++) {
+ /* See what changed */
+ n = (new_val >> i) & 0x01;
+ c = (cur_val >> i) & 0x01;
+ CPRINTF("%s", n ? " X " : " _ ");
+ if (n == c)
+ continue;
+#ifdef HAS_TASK_KEYPROTO
+ /* Treat it as a keyboard event. */
+ keyboard_update_button(i + KEYBOARD_BUTTON_CAPSENSE_1,
+ n);
+#endif
+ }
+ CPRINTF("]\n");
+ cur_val = new_val;
+ }
+
+ if (cur_val)
+ hook_call_deferred(capsense_change_deferred,
+ CAPSENSE_POLL_INTERVAL);
+}
+DECLARE_DEFERRED(capsense_change_deferred);
+
+/*
+ * Somebody's poking at us.
+ */
+void capsense_interrupt(enum gpio_signal signal)
+{
+ hook_call_deferred(capsense_change_deferred, 0);
+}