86 lines
2.0 KiB
C
86 lines
2.0 KiB
C
/* Copyright 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;
|
|
|
|
rv = i2c_xfer(I2C_PORT_CAPSENSE, CAPSENSE_I2C_ADDR,
|
|
0, 0, &val, 1);
|
|
|
|
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);
|
|
}
|