diff options
-rw-r--r-- | common/fpsensor/fpsensor_state.c | 32 | ||||
-rw-r--r-- | include/ec_commands.h | 12 | ||||
-rw-r--r-- | util/ectool.c | 55 |
3 files changed, 92 insertions, 7 deletions
diff --git a/common/fpsensor/fpsensor_state.c b/common/fpsensor/fpsensor_state.c index c395bd7af3..f7890f9cdc 100644 --- a/common/fpsensor/fpsensor_state.c +++ b/common/fpsensor/fpsensor_state.c @@ -199,12 +199,30 @@ DECLARE_HOST_COMMAND(EC_CMD_FP_MODE, fp_command_mode, EC_VER_MASK(0)); static enum ec_status fp_command_context(struct host_cmd_handler_args *args) { - const struct ec_params_fp_context *params = args->params; - - fp_reset_and_clear_context(); - - memcpy(user_id, params->userid, sizeof(user_id)); + const struct ec_params_fp_context_v1 *p = args->params; + uint32_t mode_output; + + switch (p->action) { + case FP_CONTEXT_ASYNC: + if (sensor_mode & FP_MODE_RESET_SENSOR) + return EC_RES_BUSY; + + /** + * Trigger a call to fp_reset_and_clear_context() by + * requesting a reset. Since that function triggers a call to + * fp_sensor_open(), this must be asynchronous because + * fp_sensor_open() can take ~175 ms. See http://b/137288498. + */ + return fp_set_sensor_mode(FP_MODE_RESET_SENSOR, &mode_output); + + case FP_CONTEXT_GET_RESULT: + if (sensor_mode & FP_MODE_RESET_SENSOR) + return EC_RES_BUSY; + + memcpy(user_id, p->userid, sizeof(user_id)); + return EC_RES_SUCCESS; + } - return EC_RES_SUCCESS; + return EC_RES_INVALID_PARAM; } -DECLARE_HOST_COMMAND(EC_CMD_FP_CONTEXT, fp_command_context, EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_FP_CONTEXT, fp_command_context, EC_VER_MASK(1)); diff --git a/include/ec_commands.h b/include/ec_commands.h index 2ce5ca5271..f813b5e629 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -5917,6 +5917,18 @@ struct ec_params_fp_context { uint32_t userid[FP_CONTEXT_USERID_WORDS]; } __ec_align4; +enum fp_context_action { + FP_CONTEXT_ASYNC = 0, + FP_CONTEXT_GET_RESULT = 1, +}; + +/* Version 1 of the command is "asynchronous". */ +struct ec_params_fp_context_v1 { + uint8_t action; /**< enum fp_context_action */ + uint8_t reserved[3]; /**< padding for alignment */ + uint32_t userid[FP_CONTEXT_USERID_WORDS]; +} __ec_align4; + #define EC_CMD_FP_STATS 0x0407 #define FPSTATS_CAPTURE_INV BIT(0) diff --git a/util/ectool.c b/util/ectool.c index 6ca7cfcf8f..d73dd770ee 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -142,6 +142,8 @@ const char help_str[] = " Writes to EC flash from a file\n" " forcelidopen <enable>\n" " Forces the lid switch to open position\n" + " fpcontext\n" + " Sets the fingerprint sensor context\n" " fpencstatus\n" " Prints status of Fingerprint sensor encryption engine\n" " fpframe\n" @@ -1726,6 +1728,58 @@ static void print_fp_enc_flags(const char *desc, uint32_t flags) printf("\n"); } +static int cmd_fp_context(int argc, char *argv[]) +{ + struct ec_params_fp_context_v1 p; + int rv; + int tries = 20; /* Wait at most two seconds */ + + if (argc < 2) { + fprintf(stderr, "Usage: %s <context>\n", argv[0]); + return -1; + } + + /* + * Note that we treat the resulting "userid" as raw byte array, so we + * don't want to copy the NUL from the end of the string. + */ + if (strlen(argv[1]) != sizeof(p.userid)) { + fprintf(stderr, "Context must be exactly %zu bytes\n", + sizeof(p.userid)); + return -1; + } + + p.action = FP_CONTEXT_ASYNC; + memcpy(p.userid, argv[1], sizeof(p.userid)); + + rv = ec_command(EC_CMD_FP_CONTEXT, 1, &p, sizeof(p), NULL, 0); + + if (rv != EC_RES_SUCCESS) + goto out; + + while (tries--) { + usleep(100000); + + p.action = FP_CONTEXT_GET_RESULT; + rv = ec_command(EC_CMD_FP_CONTEXT, 1, &p, sizeof(p), NULL, 0); + + if (rv == EC_RES_SUCCESS) { + printf("Set context successfully\n"); + return EC_RES_SUCCESS; + } + + /* Abort if EC returns an error other than EC_RES_BUSY. */ + if (rv <= -EECRESULT && rv != -EECRESULT - EC_RES_BUSY) + goto out; + } + + rv = -EECRESULT - EC_RES_TIMEOUT; + +out: + fprintf(stderr, "Failed to reset context: %d\n", rv); + return rv; +} + int cmd_fp_enc_status(int argc, char *argv[]) { int rv; @@ -9008,6 +9062,7 @@ const struct command commands[] = { {"flashspiinfo", cmd_flash_spi_info}, {"flashpd", cmd_flash_pd}, {"forcelidopen", cmd_force_lid_open}, + {"fpcontext", cmd_fp_context}, {"fpencstatus", cmd_fp_enc_status}, {"fpframe", cmd_fp_frame}, {"fpinfo", cmd_fp_info}, |