mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:7461 TEST=manual make BOARD={bds,link,daisy} make tests flash link system and make sure it boots Change-Id: I1241a1895c083e387e38ddab01ac346ca4474eb9
151 lines
3.3 KiB
C
151 lines
3.3 KiB
C
/* Copyright (c) 2011 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.
|
|
*
|
|
* Chrome OS EC i8042 interface code.
|
|
*/
|
|
|
|
#include "board.h"
|
|
#include "common.h"
|
|
#include "i8042.h"
|
|
#include "keyboard.h"
|
|
#include "task.h"
|
|
#include "timer.h"
|
|
#include "uart.h"
|
|
#include "util.h"
|
|
|
|
|
|
#define I8042_DEBUG 1
|
|
|
|
#define MAX_QUEUED_KEY_PRESS 16
|
|
|
|
/* Circular buffer to host.
|
|
* head: next to dequeqe
|
|
* tail: next to enqueue
|
|
* head == tail: empty.
|
|
* tail + 1 == head: full
|
|
*/
|
|
static int head_to_buffer = 0;
|
|
static int tail_to_buffer = 0;
|
|
#define HOST_BUFFER_SIZE (16)
|
|
static uint8_t to_host_buffer[HOST_BUFFER_SIZE];
|
|
|
|
static int i8042_irq_enabled = 0;
|
|
|
|
|
|
/* Reset all i8042 buffer */
|
|
void i8042_init()
|
|
{
|
|
head_to_buffer = tail_to_buffer = 0;
|
|
}
|
|
|
|
|
|
/* Called by the chip-specific code when host sedns a byte to port 0x60. */
|
|
void i8042_receives_data(int data)
|
|
{
|
|
int ret_len;
|
|
uint8_t output[MAX_SCAN_CODE_LEN];
|
|
enum ec_error_list ret;
|
|
|
|
ret_len = handle_keyboard_data(data, output);
|
|
ret = i8042_send_to_host(ret_len, output);
|
|
ASSERT(ret == EC_SUCCESS);
|
|
}
|
|
|
|
|
|
/* Called by the chip-specific code when host sedns a byte to port 0x64. */
|
|
void i8042_receives_command(int cmd)
|
|
{
|
|
int ret_len;
|
|
uint8_t output[MAX_SCAN_CODE_LEN];
|
|
enum ec_error_list ret;
|
|
|
|
ret_len = handle_keyboard_command(cmd, output);
|
|
ret = i8042_send_to_host(ret_len, output);
|
|
ASSERT(ret == EC_SUCCESS);
|
|
}
|
|
|
|
|
|
/* Called by EC common code to send bytes to host via port 0x60. */
|
|
static void enq_to_host(int len, uint8_t *to_host)
|
|
{
|
|
int from, to;
|
|
|
|
/* Check if the buffer has enough space, then copy them to buffer. */
|
|
if ((tail_to_buffer + len) <= (head_to_buffer + HOST_BUFFER_SIZE - 1)) {
|
|
for (from = 0, to = tail_to_buffer; from < len;) {
|
|
to_host_buffer[to++] = to_host[from++];
|
|
to %= HOST_BUFFER_SIZE;
|
|
}
|
|
tail_to_buffer = (tail_to_buffer + len) % HOST_BUFFER_SIZE;
|
|
}
|
|
}
|
|
|
|
|
|
/* Called by common/keyboard.c when the host wants to receive keyboard IRQ
|
|
* (or not).
|
|
*/
|
|
void i8042_enable_keyboard_irq(void) {
|
|
i8042_irq_enabled = 1;
|
|
}
|
|
|
|
void i8042_disable_keyboard_irq(void) {
|
|
i8042_irq_enabled = 0;
|
|
}
|
|
|
|
|
|
void i8042_command_task(void)
|
|
{
|
|
while (1) {
|
|
/* Either a new byte to host or host picking up can un-block. */
|
|
task_wait_event(-1);
|
|
|
|
while (1) {
|
|
uint8_t chr;
|
|
int empty = 0;
|
|
|
|
/* Check if we have data in buffer to host. */
|
|
if (head_to_buffer == tail_to_buffer) {
|
|
empty = 1; /* nothing to host */
|
|
}
|
|
if (empty) break;
|
|
|
|
/* if the host still didn't read that away,
|
|
try next time. */
|
|
if (keyboard_has_char()) {
|
|
#if I8042_DEBUG >= 5
|
|
uart_printf("[%d] i8042_command_task() "
|
|
"cannot send to host due to host "
|
|
"havn't taken away.\n",
|
|
get_time().le.lo);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
/* Get a char from buffer. */
|
|
chr = to_host_buffer[head_to_buffer];
|
|
head_to_buffer =
|
|
(head_to_buffer + 1) % HOST_BUFFER_SIZE;
|
|
|
|
/* Write to host. */
|
|
keyboard_put_char(chr, i8042_irq_enabled);
|
|
#if I8042_DEBUG >= 4
|
|
uart_printf("[%d] i8042_command_task() "
|
|
"sends to host: 0x%02x\n",
|
|
get_time().le.lo, chr);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
enum ec_error_list i8042_send_to_host(int len, uint8_t *to_host)
|
|
{
|
|
enq_to_host(len, to_host);
|
|
|
|
/* Wake up the task to handle the command */
|
|
task_wake(TASK_ID_I8042CMD);
|
|
|
|
return EC_SUCCESS;
|
|
}
|