diff options
author | Simon Glass <sjg@chromium.org> | 2012-10-16 16:08:51 -0700 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2012-10-29 14:47:27 -0700 |
commit | a1458e29b091af065170690cde23fcd18f6047ce (patch) | |
tree | 71cc43ff296a1f7d88909a47d1aa8f69d6646dba | |
parent | e81dfd920e97301ffdd17d57aed9f90b74a898be (diff) | |
download | chrome-ec-a1458e29b091af065170690cde23fcd18f6047ce.tar.gz |
Revert "Revert "stm32: Implement keyscan configuration command""
This reverts commit 964c45d56a894f4706265542bc54df74c21f5b50.
This brings the ToT code back into the branch.
BUG=chrome-os-partner:12179
BRANCH=snow
TEST=manual
Use keyboard in U-Boot, browser, gmail and write a paragraph
of text. Try pressing keys quickly. See that things seem to work
correctly.
Change-Id: I0010256ecf1573ab0fc381456318c0b2d56b4d4d
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/36078
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: David Hendricks <dhendrix@chromium.org>
-rw-r--r-- | chip/stm32/keyboard_scan.c | 88 | ||||
-rw-r--r-- | util/ectool.c | 150 |
2 files changed, 238 insertions, 0 deletions
diff --git a/chip/stm32/keyboard_scan.c b/chip/stm32/keyboard_scan.c index 06473e8f85..bf261d38e7 100644 --- a/chip/stm32/keyboard_scan.c +++ b/chip/stm32/keyboard_scan.c @@ -550,3 +550,91 @@ DECLARE_CONSOLE_COMMAND(kbpress, command_keyboard_press, "[col] [row] [0 | 1]", "Simulate keypress", NULL); + +/** + * Copy keyscan configuration from one place to another according to flags + * + * This is like a structure copy, except that only selected fields are + * copied. + * + * TODO(sjg@chromium.org): Consider making this table drive as ectool. + * + * @param src Source config + * @param dst Destination config + * @param valid_mask Bits representing which fields to copy - each bit is + * from enum mkbp_config_valid + * @param valid_flags Bit mask controlling flags to copy. Any 1 bit means + * that the corresponding bit in src->flags is copied + * over to dst->flags + */ +static void keyscan_copy_config(const struct ec_mkbp_config *src, + struct ec_mkbp_config *dst, + uint32_t valid_mask, uint8_t valid_flags) +{ + uint8_t new_flags; + + if (valid_mask & EC_MKBP_VALID_SCAN_PERIOD) + dst->scan_period_us = src->scan_period_us; + if (valid_mask & EC_MKBP_VALID_POLL_TIMEOUT) + dst->poll_timeout_us = src->poll_timeout_us; + if (valid_mask & EC_MKBP_VALID_MIN_POST_SCAN_DELAY) { + /* + * Key scanning is high priority, so we should require at + * least 100us min delay here. Setting this to 0 will cause + * watchdog events. Use 200 to be safe. + */ + dst->min_post_scan_delay_us = + MAX(src->min_post_scan_delay_us, 200); + } + if (valid_mask & EC_MKBP_VALID_OUTPUT_SETTLE) + dst->output_settle_us = src->output_settle_us; + if (valid_mask & EC_MKBP_VALID_DEBOUNCE_DOWN) + dst->debounce_down_us = src->debounce_down_us; + if (valid_mask & EC_MKBP_VALID_DEBOUNCE_UP) + dst->debounce_up_us = src->debounce_up_us; + if (valid_mask & EC_MKBP_VALID_FIFO_MAX_DEPTH) { + /* Sanity check for fifo depth */ + dst->fifo_max_depth = MIN(src->fifo_max_depth, + KB_FIFO_DEPTH); + } + new_flags = dst->flags & ~valid_flags; + new_flags |= src->flags & valid_flags; + dst->flags = new_flags; + + /* + * If we just enabled key scanning, kick the task so that it will + * fall out of the task_wait_event() in keyboard_scan_task(). + */ + if ((new_flags & EC_MKBP_FLAGS_ENABLE) && + !(dst->flags & EC_MKBP_FLAGS_ENABLE)) + task_wake(TASK_ID_KEYSCAN); +} + +static int host_command_mkbp_set_config(struct host_cmd_handler_args *args) +{ + const struct ec_params_mkbp_set_config *req = args->params; + + keyscan_copy_config(&req->config, &config, + config.valid_mask & req->config.valid_mask, + config.valid_flags & req->config.valid_flags); + + return EC_RES_SUCCESS; +} + +static int host_command_mkbp_get_config(struct host_cmd_handler_args *args) +{ + struct ec_response_mkbp_get_config *resp = args->response; + + memcpy(&resp->config, &config, sizeof(config)); + args->response_size = sizeof(*resp); + + return EC_RES_SUCCESS; +} + +DECLARE_HOST_COMMAND(EC_CMD_MKBP_SET_CONFIG, + host_command_mkbp_set_config, + EC_VER_MASK(0)); + +DECLARE_HOST_COMMAND(EC_CMD_MKBP_GET_CONFIG, + host_command_mkbp_get_config, + EC_VER_MASK(0)); diff --git a/util/ectool.c b/util/ectool.c index 705b187f24..072dd66258 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -2080,6 +2080,155 @@ int cmd_ec_hash(int argc, char *argv[]) return ec_hash_print(&r); } +struct param_info { + const char *name; /* name of this parameter */ + const char *help; /* help message */ + int size; /* size in bytes */ + int offset; /* offset within structure */ +}; + +#define FIELD(fname, field, help_str) \ + { \ + .name = fname, \ + .help = help_str, \ + .size = sizeof(((struct ec_mkbp_config *)NULL)->field), \ + .offset = __builtin_offsetof(struct ec_mkbp_config, field), \ + } + +static const struct param_info keyconfig_params[] = { + FIELD("scan_period", scan_period_us, "period between scans"), + FIELD("poll_timeout", poll_timeout_us, + "revert to irq mode after no activity for this long"), + FIELD("min_post_scan_delay", min_post_scan_delay_us, + "minimum post-scan delay before starting a new scan"), + FIELD("output_settle", output_settle_us, + "delay to wait for output to settle"), + FIELD("debounce_down", debounce_down_us, + "time for debounce on key down"), + FIELD("debounce_up", debounce_up_us, "time for debounce on key up"), + FIELD("fifo_max_depth", fifo_max_depth, + "maximum depth to allow for fifo (0 = disable)"), + FIELD("flags", flags, "0 to disable scanning, 1 to enable"), +}; + +static const struct param_info *find_field(const struct param_info *params, + int count, const char *name, unsigned int *nump) +{ + const struct param_info *param; + int i; + + for (i = 0, param = params; i < count; i++, param++) { + if (0 == strcmp(param->name, name)) { + if (nump) + *nump = i; + return param; + } + } + + fprintf(stderr, "Unknown parameter '%s'\n", name); + return NULL; +} + +static int get_value(const struct param_info *param, const char *config) +{ + const char *field; + + field = config + param->offset; + switch (param->size) { + case 1: + return *(uint8_t *)field; + case 2: + return *(uint16_t *)field; + case 4: + return *(uint32_t *)field; + default: + fprintf(stderr, "Internal error: unknown size %d\n", + param->size); + } + + return -1; +} + +static int show_fields(struct ec_mkbp_config *config, int argc, char *argv[]) +{ + const struct param_info *param; + uint32_t mask ; + int i; + + if (!argc) { + mask = -1U; /* show all fields */ + } else { + mask = 0; + while (argc > 0) { + unsigned int num; + + param = find_field(keyconfig_params, + ARRAY_SIZE(keyconfig_params), + argv[0], &num); + if (!param) + return -1; + mask |= 1 << num; + argc--; + argv++; + } + } + + param = keyconfig_params; + for (i = 0; i < ARRAY_SIZE(keyconfig_params); i++, param++) { + if (mask & (1 << i)) { + fprintf(stderr, "%-12s %u\n", param->name, + get_value(param, (char *)config)); + } + } + + return 0; +} + +static int cmd_keyconfig(int argc, char *argv[]) +{ + struct ec_params_mkbp_set_config req; + int cmd; + int rv; + + if (argc < 2) { + const struct param_info *param; + int i; + + fprintf(stderr, "Usage: %s get [<param>] - print params\n" + "\t%s set [<param>> <value>]\n" + " Available params are: (all time values are in us)", + argv[0], argv[0]); + + param = keyconfig_params; + for (i = 0; i < ARRAY_SIZE(keyconfig_params); i++, param++) { + fprintf(stderr, "%-12s %s\n", param->name, + param->name); + } + return -1; + } + + /* Get the command */ + if (0 == strcmp(argv[1], "get")) { + cmd = EC_CMD_MKBP_GET_CONFIG; + } else if (0 == strcmp(argv[1], "set")) { + cmd = EC_CMD_MKBP_SET_CONFIG; + } else { + fprintf(stderr, "Invalid command '%s\n", argv[1]); + return -1; + } + + switch (cmd) { + case EC_CMD_MKBP_GET_CONFIG: + /* Read the existing config */ + rv = ec_command(cmd, 0, NULL, 0, &req, sizeof(req)); + if (rv < 0) + return rv; + show_fields(&req.config, argc - 2, argv + 2); + break; + } + + return 0; +} struct command { const char *name; @@ -2119,6 +2268,7 @@ const struct command commands[] = { {"i2cread", cmd_i2c_read}, {"i2cwrite", cmd_i2c_write}, {"lightbar", cmd_lightbar}, + {"keyconfig", cmd_keyconfig}, {"pstoreinfo", cmd_pstore_info}, {"pstoreread", cmd_pstore_read}, {"pstorewrite", cmd_pstore_write}, |