summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/fpsensor/fpsensor_state.c32
-rw-r--r--include/ec_commands.h12
-rw-r--r--util/ectool.c55
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},