/* 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 CPRINTS(format, args...) cprints(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) CPRINTS("%s failed: error %d", __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_data, 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_data, 0); }