summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2018-01-25 08:59:26 +0100
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-03-27 18:22:19 +0000
commita5bd63b499f6376fe01a1fecac6d18eed9ab1f6b (patch)
treef774879e4c7892aa326fca11ec055de7cffbedb9 /util
parente9f36b2f8043bf9f4ed817c129ca4a34e0477b63 (diff)
downloadchrome-ec-a5bd63b499f6376fe01a1fecac6d18eed9ab1f6b.tar.gz
fpsensor: add enrollment and matching interface
Add the state machine and the interfacing to the enrollment and matching algorithm providing by the private driver part. Implement the host commands interface for it (based on MKBP event) along with the console debug commands to exercise it. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=none TEST=On ZerbleBarn console, use 'fpenroll' then 'fpmatch' for several fingers. TEST=With ZerbleBarn and a servo-v2, retrieve and upload templates with 'ectool_servo fptemplate'. TEST=On Meowth, exercise with the prototype of biod CrosFpBiometricsManager. CQ-DEPEND=CL:*555078 Change-Id: I10b0d76d3faa898a682cf9a2eb7fc7e212b0c20c Reviewed-on: https://chromium-review.googlesource.com/886401 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/982310 Reviewed-by: Furquan Shaikh <furquan@chromium.org> Commit-Queue: Furquan Shaikh <furquan@chromium.org> Tested-by: Furquan Shaikh <furquan@chromium.org> Trybot-Ready: Furquan Shaikh <furquan@chromium.org>
Diffstat (limited to 'util')
-rw-r--r--util/ectool.c134
1 files changed, 123 insertions, 11 deletions
diff --git a/util/ectool.c b/util/ectool.c
index 28b2eeb8c4..83b263d74b 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -124,6 +124,8 @@ const char help_str[] =
" Prints information about the Fingerprint sensor\n"
" fpmode [capture|deepsleep|fingerdown|fingerup]\n"
" Configure/Read the fingerprint sensor current mode\n"
+ " fptemplate [<infile>|<index 0..2>]\n"
+ " Add a template if <infile> is provided, else dump it\n"
" forcelidopen <enable>\n"
" Forces the lid switch to open position\n"
" gpioget <GPIO name>\n"
@@ -1092,22 +1094,51 @@ int cmd_rwsig_action(int argc, char *argv[])
return ec_command(EC_CMD_RWSIG_ACTION, 0, &req, sizeof(req), NULL, 0);
}
-static void *fp_download_frame(struct ec_response_fp_info *info, int all)
+#define FP_FRAME_INDEX_SIMPLE_IMAGE -1
+
+/*
+ * Download a frame buffer from the FPMCU.
+ *
+ * Might be either the finger image or a finger template depending on 'index'.
+ *
+ * @param info a pointer to store the struct ec_response_fp_info retrieved by
+ * this command.
+ * @param index the specific frame to retrieve, might be:
+ * -1 (aka FP_FRAME_INDEX_SIMPLE_IMAGE) for the a single grayscale image.
+ * 0 (aka FP_FRAME_INDEX_RAW_IMAGE) for the full vendor raw finger image.
+ * 1..n for a finger template.
+ *
+ * @returns a pointer to the buffer allocated to contain the frame or NULL
+ * if case of error. The caller must call free() once it no longer needs the
+ * buffer.
+ */
+static void *fp_download_frame(struct ec_response_fp_info *info, int index)
{
struct ec_params_fp_frame p;
int rv = 0;
size_t stride, size;
void *buffer;
uint8_t *ptr;
+ int cmdver = ec_cmd_version_supported(EC_CMD_FP_INFO, 1) ? 1 : 0;
+ int rsize = cmdver == 1 ? sizeof(*info)
+ : sizeof(struct ec_response_fp_info_v0);
- rv = ec_command(EC_CMD_FP_INFO, 0, NULL, 0, info, sizeof(*info));
+ /* templates not supported in command v0 */
+ if (index > 0 && cmdver == 0)
+ return NULL;
+
+ rv = ec_command(EC_CMD_FP_INFO, cmdver, NULL, 0, info, rsize);
if (rv < 0)
return NULL;
- if (all)
- size = info->frame_size;
- else
+ if (index == FP_FRAME_INDEX_SIMPLE_IMAGE) {
size = (size_t)info->width * info->bpp/8 * info->height;
+ index = FP_FRAME_INDEX_RAW_IMAGE;
+ } else if (index == FP_FRAME_INDEX_RAW_IMAGE) {
+ size = info->frame_size;
+ } else {
+ size = info->template_size;
+ }
buffer = malloc(size);
if (!buffer) {
@@ -1116,7 +1147,7 @@ static void *fp_download_frame(struct ec_response_fp_info *info, int all)
}
ptr = buffer;
- p.offset = 0;
+ p.offset = index << FP_FRAME_INDEX_SHIFT;
while (size) {
stride = MIN(ec_max_insize, size);
p.size = stride;
@@ -1153,7 +1184,7 @@ static int fp_pattern_frame(int capt_type, const char *title, int inv)
return -1;
/* ensure the capture has happened without using event support */
usleep(200000);
- pattern = fp_download_frame(&info, 0);
+ pattern = fp_download_frame(&info, FP_FRAME_INDEX_SIMPLE_IMAGE);
if (!pattern)
return -1;
@@ -1239,6 +1270,12 @@ int cmd_fp_mode(int argc, char *argv[])
mode |= FP_MODE_FINGER_DOWN;
else if (!strncmp(argv[i], "fingerup", 8))
mode |= FP_MODE_FINGER_UP;
+ else if (!strncmp(argv[i], "enroll", 6))
+ mode |= FP_MODE_ENROLL_IMAGE | FP_MODE_ENROLL_SESSION;
+ else if (!strncmp(argv[i], "match", 5))
+ mode |= FP_MODE_MATCH;
+ else if (!strncmp(argv[i], "reset", 5))
+ mode = 0;
else if (!strncmp(argv[i], "capture", 7))
mode |= FP_MODE_CAPTURE;
/* capture types */
@@ -1266,6 +1303,11 @@ int cmd_fp_mode(int argc, char *argv[])
printf("finger-down ");
if (r.mode & FP_MODE_FINGER_UP)
printf("finger-up ");
+ if (r.mode & FP_MODE_ENROLL_SESSION)
+ printf("enroll%s ",
+ r.mode & FP_MODE_ENROLL_IMAGE ? "+image" : "");
+ if (r.mode & FP_MODE_MATCH)
+ printf("match ");
if (r.mode & FP_MODE_CAPTURE)
printf("capture ");
printf("\n");
@@ -1276,8 +1318,11 @@ int cmd_fp_info(int argc, char *argv[])
{
struct ec_response_fp_info r;
int rv;
+ int cmdver = ec_cmd_version_supported(EC_CMD_FP_INFO, 1) ? 1 : 0;
+ int rsize = cmdver == 1 ? sizeof(r)
+ : sizeof(struct ec_response_fp_info_v0);
- rv = ec_command(EC_CMD_FP_INFO, 0, NULL, 0, &r, sizeof(r));
+ rv = ec_command(EC_CMD_FP_INFO, cmdver, NULL, 0, &r, rsize);
if (rv < 0)
return rv;
@@ -1290,6 +1335,11 @@ int cmd_fp_info(int argc, char *argv[])
r.errors & FP_ERROR_BAD_HWID ? "BAD_HWID " : "",
r.errors & FP_ERROR_INIT_FAIL ? "INIT_FAIL " : "",
FP_ERROR_DEAD_PIXELS(r.errors));
+ if (cmdver == 1) {
+ printf("Templates: size %d count %d/%d dirty bitmap %x\n",
+ r.template_size, r.template_valid, r.template_max,
+ r.template_dirty);
+ }
return 0;
}
@@ -1297,8 +1347,9 @@ int cmd_fp_info(int argc, char *argv[])
int cmd_fp_frame(int argc, char *argv[])
{
struct ec_response_fp_info r;
- int raw = (argc == 2 && !strcasecmp(argv[1], "raw"));
- void *buffer = fp_download_frame(&r, raw);
+ int idx = (argc == 2 && !strcasecmp(argv[1], "raw")) ?
+ FP_FRAME_INDEX_RAW_IMAGE : FP_FRAME_INDEX_SIMPLE_IMAGE;
+ void *buffer = fp_download_frame(&r, idx);
uint8_t *ptr = buffer;
int x, y;
@@ -1307,7 +1358,7 @@ int cmd_fp_frame(int argc, char *argv[])
return -1;
}
- if (raw) {
+ if (idx == FP_FRAME_INDEX_RAW_IMAGE) {
fwrite(buffer, r.frame_size, 1, stdout);
goto frame_done;
}
@@ -1326,6 +1377,66 @@ frame_done:
return 0;
}
+int cmd_fp_template(int argc, char *argv[])
+{
+ struct ec_response_fp_info r;
+ struct ec_params_fp_template *p = ec_outbuf;
+ int max_chunk = ec_max_outsize
+ - offsetof(struct ec_params_fp_template, data);
+ int idx = -1;
+ char *e;
+ int size;
+ void *buffer = NULL;
+ uint32_t offset = 0;
+ int rv = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [<infile>|<index>]\n", argv[0]);
+ return -1;
+ }
+
+ idx = strtol(argv[1], &e, 0);
+ if (!(e && *e)) {
+ buffer = fp_download_frame(&r, idx + 1);
+ if (!buffer) {
+ fprintf(stderr, "Failed to get FP template %d\n", idx);
+ return -1;
+ }
+ fwrite(buffer, r.template_size, 1, stdout);
+ free(buffer);
+ return 0;
+ }
+ /* not an index, is it a filename ? */
+ buffer = read_file(argv[1], &size);
+ if (!buffer) {
+ fprintf(stderr, "Invalid parameter: %s\n", argv[1]);
+ return -1;
+ }
+ printf("sending template from: %s (%d bytes)\n", argv[1], size);
+ while (size) {
+ uint32_t tlen = MIN(max_chunk, size);
+
+ p->offset = offset;
+ p->size = tlen;
+ size -= tlen;
+ if (!size)
+ p->size |= FP_TEMPLATE_COMMIT;
+ memcpy(p->data, buffer + offset, tlen);
+ rv = ec_command(EC_CMD_FP_TEMPLATE, 0, p, tlen +
+ offsetof(struct ec_params_fp_template, data),
+ NULL, 0);
+ if (rv < 0)
+ break;
+ offset += tlen;
+ }
+ if (rv < 0)
+ fprintf(stderr, "Failed with %d\n", rv);
+ else
+ rv = 0;
+ free(buffer);
+ return rv;
+}
+
/**
* determine if in GFU mode or not.
*
@@ -7726,6 +7837,7 @@ const struct command commands[] = {
{"fpframe", cmd_fp_frame},
{"fpinfo", cmd_fp_info},
{"fpmode", cmd_fp_mode},
+ {"fptemplate", cmd_fp_template},
{"gpioget", cmd_gpio_get},
{"gpioset", cmd_gpio_set},
{"hangdetect", cmd_hang_detect},