diff options
Diffstat (limited to 'util/ectool.c')
-rw-r--r-- | util/ectool.c | 134 |
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}, |