mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 00:51:29 +00:00
Implement typematic delay and rate. Also other keyboard commands.
BUG=None TEST=make && make runtests Change-Id: Ia0013ddbb0300791b4667bf70c5d0fb78c9508b1
This commit is contained in:
@@ -7,13 +7,53 @@
|
||||
|
||||
#include "cros_ec/include/ec_common.h"
|
||||
#include "cros_ec/include/ec_keyboard.h"
|
||||
#include "chip_interface/ec_uart.h"
|
||||
#include "chip_interface/keyboard.h"
|
||||
#include "host_interface/i8042.h"
|
||||
|
||||
|
||||
/*
|
||||
* i8042 global settings.
|
||||
*/
|
||||
static int i8042_enabled = 0; /* default the keyboard is disabled. */
|
||||
static uint8_t resend_command[MAX_I8042_OUTPUT_LEN];
|
||||
static uint8_t resend_command_len = 0;
|
||||
|
||||
/*
|
||||
* Scancode settings
|
||||
*/
|
||||
static EcKeyboardMatrixCallback matrix_callback;
|
||||
static enum EcScancodeSet scancode_set = EC_SCANCODE_SET_2;
|
||||
|
||||
/*
|
||||
* Typematic delay, rate and counter variables.
|
||||
*
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
* |un- | delay | B | D |
|
||||
* | used| 0 1 | 0 1 | 0 1 1 |
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
* Formula:
|
||||
* the inter-char delay = (2 ** B) * (D + 8) / 240 (sec)
|
||||
* Default: 500ms delay, 10.9 chars/sec.
|
||||
*/
|
||||
#define DEFAULT_TYPEMATIC_VALUE ((1 << 5) || (1 << 3) || (3 << 0))
|
||||
#define DEFAULT_FIRST_DELAY 500
|
||||
#define DEFAULT_INTER_DELAY 91
|
||||
static uint8_t typematic_value_from_host = DEFAULT_TYPEMATIC_VALUE;
|
||||
static int refill_first_delay = DEFAULT_FIRST_DELAY; /* unit: ms */
|
||||
static int counter_first_delay;
|
||||
static int refill_inter_delay = DEFAULT_INTER_DELAY; /* unit: ms */
|
||||
static int counter_inter_delay;
|
||||
|
||||
|
||||
static void reset_rate_and_delay() {
|
||||
typematic_value_from_host = DEFAULT_TYPEMATIC_VALUE;
|
||||
refill_first_delay = DEFAULT_FIRST_DELAY;
|
||||
refill_inter_delay = DEFAULT_INTER_DELAY;
|
||||
}
|
||||
|
||||
|
||||
static void KeyboardStateChanged(int row, int col, int is_pressed) {
|
||||
uint8_t scan_code[MAX_SCAN_CODE_LEN];
|
||||
int len;
|
||||
@@ -42,6 +82,8 @@ static int HandleHostCommand(
|
||||
uint8_t data,
|
||||
uint8_t *output) {
|
||||
int out_len = 0;
|
||||
int save_for_resend = 1;
|
||||
int i;
|
||||
|
||||
switch (command) {
|
||||
case EC_I8042_CMD_GSCANSET: /* also EC_I8042_CMD_SSCANSET */
|
||||
@@ -54,24 +96,77 @@ static int HandleHostCommand(
|
||||
}
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_SETREP:
|
||||
case EC_I8042_CMD_ENABLE:
|
||||
case EC_I8042_CMD_RESET_DIS:
|
||||
case EC_I8042_CMD_RESET_DEF:
|
||||
case EC_I8042_CMD_SETALL_MB:
|
||||
case EC_I8042_CMD_SETALL_MBR:
|
||||
case EC_I8042_CMD_RESET_BAT:
|
||||
case EC_I8042_CMD_RESEND:
|
||||
case EC_I8042_CMD_EX_ENABLE:
|
||||
case EC_I8042_CMD_SETLEDS: /* fall-thru */
|
||||
case EC_I8042_CMD_EX_SETLEDS:
|
||||
/* We use screen indicator. Do thing in keyboard controller. */
|
||||
output[out_len++] = EC_I8042_RET_ACK;
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_GETID: /* fall-thru */
|
||||
case EC_I8042_CMD_OK_GETID:
|
||||
case EC_I8042_CMD_GETID:
|
||||
case EC_I8042_CMD_SETLEDS:
|
||||
output[out_len++] = 0xab; /* Regular keyboards */
|
||||
output[out_len++] = 0x83;
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_SETREP:
|
||||
typematic_value_from_host = data;
|
||||
refill_first_delay = counter_first_delay + counter_inter_delay;
|
||||
refill_first_delay = ((typematic_value_from_host & 0x60) >> 5) * 250;
|
||||
refill_inter_delay = 1000 * /* ms */
|
||||
(1 << ((typematic_value_from_host & 0x18) >> 3)) *
|
||||
((typematic_value_from_host & 0x7) + 8) /
|
||||
240;
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_ENABLE:
|
||||
i8042_enabled = 1;
|
||||
/* TODO: clean the underlying internal buffer */
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_RESET_DIS:
|
||||
i8042_enabled = 0;
|
||||
reset_rate_and_delay();
|
||||
/* TODO: clean the underlying internal buffer */
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_RESET_DEF:
|
||||
reset_rate_and_delay();
|
||||
/* TODO: clean the underlying internal buffer */
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_RESET_BAT:
|
||||
i8042_enabled = 0;
|
||||
output[out_len++] = EC_I8042_RET_BAT;
|
||||
output[out_len++] = EC_I8042_RET_BAT;
|
||||
/* TODO: clean the underlying internal buffer */
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_RESEND:
|
||||
save_for_resend = 0;
|
||||
for (i = 0; i < resend_command_len; ++i) {
|
||||
output[out_len++] = resend_command[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case EC_I8042_CMD_SETALL_MB: /* fall-thru below */
|
||||
case EC_I8042_CMD_SETALL_MBR:
|
||||
case EC_I8042_CMD_EX_ENABLE:
|
||||
default:
|
||||
output[out_len++] = EC_I8042_RET_ERR;
|
||||
EcUartPrintf("Unsupported i8042 command 0x%02x.\n", command);
|
||||
break;
|
||||
}
|
||||
|
||||
/* For resend, keep output before leaving. */
|
||||
if (out_len && save_for_resend) {
|
||||
EC_ASSERT(out_len <= MAX_I8042_OUTPUT_LEN);
|
||||
for (i = 0; i < out_len; ++i) {
|
||||
resend_command[i] = output[i];
|
||||
}
|
||||
resend_command_len = out_len;
|
||||
}
|
||||
|
||||
EC_ASSERT(out_len <= MAX_I8042_OUTPUT_LEN);
|
||||
return out_len;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user