summaryrefslogtreecommitdiff
path: root/common/fpsensor/fpsensor.c
diff options
context:
space:
mode:
authorYicheng Li <yichengli@chromium.org>2021-03-02 15:38:17 -0800
committerCommit Bot <commit-bot@chromium.org>2021-04-02 23:16:12 +0000
commitac08c9d1dbc9f587df3ee6b15d58c0203f7e356e (patch)
tree04cd12d6787ce1b0b99b1d4e0aff504ccfa2c35e /common/fpsensor/fpsensor.c
parente3cbbc3461c83d2d97b78447c53db1c6540cb3be (diff)
downloadchrome-ec-ac08c9d1dbc9f587df3ee6b15d58c0203f7e356e.tar.gz
fpsensor: Support building firmware that works for both sensors
This is a refactoring to allow building FPMCU firmware that works for one FPC sensor and one ELAN sensor. 1. When both drivers implement our common functions, e.g. fp_sensor_init(), rename them to fp_sensor_init_fpc() and fp_sensor_init_elan(). 2. There are a few functions implemented not in FPC driver but in FPC private library, e.g. fp_sensor_finger_status(). I kept this as-is for FPC but renamed the one in ELAN driver to fp_sensor_finger_status_elan() 3. If building for ELAN, need to hardcode elan=1 in hatch_fp/board.c because the sensor type GPIO always says FPC. BRANCH=none BUG=b:175158241 TEST=make run-fpsensor; make run-fpsensor_status; make run-fpsensor_crypto TEST=make -j BOARD=dartmonkey TEST=add CONFIG_FP_SENSOR_ELAN515 to board/hatch_fp/board.h; make -j BOARD=bloonchipper Firmware binary fully works on Dragonair (FPC) and Voema (ELAN) TEST=run device tests with http://crrev/c/2750547 and http://crrev/i/3654297 on Dragonclaw, all pass Change-Id: I789090dbdfe35ac6aefd6a629fa4c7bde89dc437 Signed-off-by: Yicheng Li <yichengli@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2727971 Reviewed-by: Tom Hughes <tomhughes@chromium.org> Commit-Queue: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'common/fpsensor/fpsensor.c')
-rw-r--r--common/fpsensor/fpsensor.c109
1 files changed, 68 insertions, 41 deletions
diff --git a/common/fpsensor/fpsensor.c b/common/fpsensor/fpsensor.c
index 08a456dc0e..7c032ddae8 100644
--- a/common/fpsensor/fpsensor.c
+++ b/common/fpsensor/fpsensor.c
@@ -51,6 +51,9 @@ static timestamp_t encryption_deadline;
/* Delay between 2 s of the sensor to detect finger removal */
#define FINGER_POLLING_DELAY (100*MSEC)
+/* Fp sensor driver interface. */
+struct fp_sensor_interface *fp_driver;
+
/* Timing statistics. */
static uint32_t capture_time_us;
static uint32_t matching_time_us;
@@ -109,14 +112,17 @@ static uint32_t fp_process_enroll(void)
/* begin/continue enrollment */
CPRINTS("[%d]Enrolling ...", templ_valid);
- res = fp_finger_enroll(fp_buffer, &percent);
+ res = fp_driver->fp_finger_enroll(fp_buffer, &percent);
+
CPRINTS("[%d]Enroll =>%d (%d%%)", templ_valid, res, percent);
if (res < 0)
return EC_MKBP_FP_ENROLL
| EC_MKBP_FP_ERRCODE(EC_MKBP_FP_ERR_ENROLL_INTERNAL);
templ_dirty |= BIT(templ_valid);
if (percent == 100) {
- res = fp_enrollment_finish(fp_template[templ_valid]);
+ res = fp_driver->fp_enrollment_finish(
+ fp_template +
+ templ_valid * fp_driver->algorithm_template_size);
if (res) {
res = EC_MKBP_FP_ERR_ENROLL_INTERNAL;
} else {
@@ -143,8 +149,8 @@ static uint32_t fp_process_match(void)
fp_disable_positive_match_secret(&positive_match_secret_state);
CPRINTS("Matching/%d ...", templ_valid);
if (templ_valid) {
- res = fp_finger_match(fp_template[0], templ_valid, fp_buffer,
- &fgr, &updated);
+ res = fp_driver->fp_finger_match(fp_template, templ_valid,
+ fp_buffer, &fgr, &updated);
CPRINTS("Match =>%d (finger %d)", res, fgr);
if (res < 0 || fgr < 0 || fgr >= FP_MAX_FINGER_COUNT) {
res = EC_MKBP_FP_ERR_MATCH_NO_INTERNAL;
@@ -168,8 +174,9 @@ static uint32_t fp_process_match(void)
static void fp_process_finger(void)
{
timestamp_t t0 = get_time();
- int res = fp_sensor_acquire_image_with_mode(fp_buffer,
- FP_CAPTURE_TYPE(sensor_mode));
+ int res = fp_driver->fp_sensor_acquire_image_with_mode_(
+ fp_buffer, FP_CAPTURE_TYPE(sensor_mode));
+
capture_time_us = time_since32(t0);
if (!res) {
uint32_t evt = EC_MKBP_FP_IMAGE_READY;
@@ -210,7 +217,7 @@ void fp_task(void)
#ifdef HAVE_FP_PRIVATE_DRIVER
/* Reset and initialize the sensor IC */
- fp_sensor_init();
+ fp_driver->fp_sensor_init();
while (1) {
uint32_t evt;
@@ -225,28 +232,29 @@ void fp_task(void)
gpio_disable_interrupt(GPIO_FPS_INT);
if ((mode ^ enroll_session) & FP_MODE_ENROLL_SESSION) {
if (mode & FP_MODE_ENROLL_SESSION) {
- if (fp_enrollment_begin())
+ if (fp_driver->fp_enrollment_begin())
sensor_mode &=
~FP_MODE_ENROLL_SESSION;
} else {
- fp_enrollment_finish(NULL);
+ fp_driver->fp_enrollment_finish(NULL);
}
enroll_session =
sensor_mode & FP_MODE_ENROLL_SESSION;
}
if (is_test_capture(mode)) {
- fp_sensor_acquire_image_with_mode(fp_buffer,
- FP_CAPTURE_TYPE(mode));
+ fp_driver->fp_sensor_acquire_image_with_mode_(
+ fp_buffer, FP_CAPTURE_TYPE(mode));
sensor_mode &= ~FP_MODE_CAPTURE;
send_mkbp_event(EC_MKBP_FP_IMAGE_READY);
continue;
} else if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) {
/* wait for a finger on the sensor */
- fp_sensor_configure_detect();
+ fp_driver->fp_sensor_configure_detect_();
}
- if (sensor_mode & FP_MODE_DEEPSLEEP)
+ if (sensor_mode & FP_MODE_DEEPSLEEP) {
/* Shutdown the sensor */
- fp_sensor_low_power();
+ fp_driver->fp_sensor_low_power();
+ }
if (sensor_mode & FP_MODE_FINGER_UP)
/* Poll the sensor to detect finger removal */
timeout_us = FINGER_POLLING_DELAY;
@@ -258,17 +266,17 @@ void fp_task(void)
fp_reset_and_clear_context();
sensor_mode &= ~FP_MODE_RESET_SENSOR;
} else if (mode & FP_MODE_SENSOR_MAINTENANCE) {
- fp_maintenance();
+ fp_driver->fp_maintenance();
sensor_mode &= ~FP_MODE_SENSOR_MAINTENANCE;
} else {
- fp_sensor_low_power();
+ fp_driver->fp_sensor_low_power();
}
} else if (evt & (TASK_EVENT_SENSOR_IRQ | TASK_EVENT_TIMER)) {
overall_t0 = get_time();
timestamps_invalid = 0;
gpio_disable_interrupt(GPIO_FPS_INT);
if (sensor_mode & FP_MODE_ANY_DETECT_FINGER) {
- st = fp_sensor_finger_status();
+ st = fp_driver->fp_sensor_finger_status_();
if (st == FINGER_PRESENT &&
sensor_mode & FP_MODE_FINGER_DOWN) {
CPRINTS("Finger!");
@@ -288,10 +296,10 @@ void fp_task(void)
fp_process_finger();
if (sensor_mode & FP_MODE_ANY_WAIT_IRQ) {
- fp_sensor_configure_detect();
+ fp_driver->fp_sensor_configure_detect_();
gpio_enable_interrupt(GPIO_FPS_INT);
} else {
- fp_sensor_low_power();
+ fp_driver->fp_sensor_low_power();
}
}
}
@@ -341,11 +349,11 @@ static enum ec_status fp_command_info(struct host_cmd_handler_args *args)
struct ec_response_fp_info *r = args->response;
#ifdef HAVE_FP_PRIVATE_DRIVER
- if (fp_sensor_get_info(r) < 0)
+ if (fp_driver->fp_sensor_get_info(r) < 0)
#endif
return EC_RES_UNAVAILABLE;
- r->template_size = FP_ALGORITHM_ENCRYPTED_TEMPLATE_SIZE;
+ r->template_size = fp_driver->encrypted_template_size;
r->template_max = FP_MAX_FINGER_COUNT;
r->template_valid = templ_valid;
r->template_dirty = templ_dirty;
@@ -397,8 +405,12 @@ static enum ec_status fp_command_frame(struct host_cmd_handler_args *args)
if (!is_raw_capture(sensor_mode))
offset += FP_SENSOR_IMAGE_OFFSET;
- ret = validate_fp_buffer_offset(sizeof(fp_buffer), offset,
- size);
+ /*
+ * Check the requested data is within the template size.
+ * This is stricter than checking buffer overflow.
+ */
+ ret = validate_fp_buffer_offset(
+ fp_driver->algorithm_template_size, offset, size);
if (ret != EC_SUCCESS)
return EC_RES_INVALID_PARAM;
@@ -416,7 +428,12 @@ static enum ec_status fp_command_frame(struct host_cmd_handler_args *args)
return EC_RES_INVALID_PARAM;
if (fgr >= templ_valid)
return EC_RES_UNAVAILABLE;
- ret = validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size);
+ /*
+ * Check the requested data is within the encrypted template size.
+ * This is stricter than checking buffer overflow.
+ */
+ ret = validate_fp_buffer_offset(fp_driver->encrypted_template_size,
+ offset, size);
if (ret != EC_SUCCESS)
return EC_RES_INVALID_PARAM;
@@ -427,9 +444,10 @@ static enum ec_status fp_command_frame(struct host_cmd_handler_args *args)
uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info);
/* Positive match salt is after the template. */
uint8_t *positive_match_salt =
- encrypted_template + sizeof(fp_template[0]);
- size_t encrypted_blob_size = sizeof(fp_template[0]) +
- sizeof(fp_positive_match_salt[0]);
+ encrypted_template + fp_driver->algorithm_template_size;
+ size_t encrypted_blob_size =
+ fp_driver->algorithm_template_size +
+ sizeof(fp_positive_match_salt[0]);
/* b/114160734: Not more than 1 encrypted message per second. */
if (!timestamp_expired(encryption_deadline, &now))
@@ -472,8 +490,9 @@ static enum ec_status fp_command_frame(struct host_cmd_handler_args *args)
* Copy the payload to |fp_enc_buffer| where it will be
* encrypted in-place.
*/
- memcpy(encrypted_template, fp_template[fgr],
- sizeof(fp_template[0]));
+ memcpy(encrypted_template,
+ fp_template + fgr * fp_driver->algorithm_template_size,
+ fp_driver->algorithm_template_size);
memcpy(positive_match_salt, fp_positive_match_salt[fgr],
sizeof(fp_positive_match_salt[0]));
@@ -557,7 +576,12 @@ static enum ec_status fp_command_template(struct host_cmd_handler_args *args)
if (args->params_size !=
size + offsetof(struct ec_params_fp_template, data))
return EC_RES_INVALID_PARAM;
- ret = validate_fp_buffer_offset(sizeof(fp_enc_buffer), offset, size);
+ /*
+ * Check the received data fits within the encrypted template size.
+ * This is stricter than checking buffer overflow.
+ */
+ ret = validate_fp_buffer_offset(fp_driver->encrypted_template_size,
+ offset, size);
if (ret != EC_SUCCESS)
return EC_RES_INVALID_PARAM;
@@ -568,7 +592,7 @@ static enum ec_status fp_command_template(struct host_cmd_handler_args *args)
uint8_t *encrypted_template = fp_enc_buffer + sizeof(*enc_info);
/* Positive match salt is after the template. */
uint8_t *positive_match_salt =
- encrypted_template + sizeof(fp_template[0]);
+ encrypted_template + fp_driver->algorithm_template_size;
size_t encrypted_blob_size;
/*
@@ -588,10 +612,11 @@ static enum ec_status fp_command_template(struct host_cmd_handler_args *args)
}
if (enc_info->struct_version <= 3) {
- encrypted_blob_size = sizeof(fp_template[0]);
+ encrypted_blob_size =
+ fp_driver->algorithm_template_size;
} else {
encrypted_blob_size =
- sizeof(fp_template[0]) +
+ fp_driver->algorithm_template_size +
sizeof(fp_positive_match_salt[0]);
}
@@ -614,8 +639,8 @@ static enum ec_status fp_command_template(struct host_cmd_handler_args *args)
fp_clear_finger_context(idx);
return EC_RES_UNAVAILABLE;
}
- memcpy(fp_template[idx], encrypted_template,
- sizeof(fp_template[0]));
+ memcpy(fp_template + idx * fp_driver->algorithm_template_size,
+ encrypted_template, fp_driver->algorithm_template_size);
if (template_needs_validation_value(enc_info)) {
CPRINTS("fgr%d: Generating positive match salt.", idx);
init_trng();
@@ -626,8 +651,10 @@ static enum ec_status fp_command_template(struct host_cmd_handler_args *args)
if (bytes_are_trivial(positive_match_salt,
sizeof(fp_positive_match_salt[0]))) {
CPRINTS("fgr%d: Trivial positive match salt.", idx);
- always_memset(fp_template[idx], 0,
- sizeof(fp_template[0]));
+ always_memset(
+ fp_template +
+ idx * fp_driver->algorithm_template_size,
+ 0, fp_driver->algorithm_template_size);
return EC_RES_INVALID_PARAM;
}
memcpy(fp_positive_match_salt[idx], positive_match_salt,
@@ -690,11 +717,11 @@ static void upload_pgm_image(uint8_t *frame)
CPRINTF("#IGNORE for ZModem\r**\030B00");
msleep(2000); /* let the download program start */
/* Print 8-bpp PGM ASCII header */
- CPRINTF("P2\n%d %d\n255\n", FP_SENSOR_RES_X, FP_SENSOR_RES_Y);
+ CPRINTF("P2\n%d %d\n255\n", fp_driver->res_x, fp_driver->res_y);
- for (y = 0; y < FP_SENSOR_RES_Y; y++) {
+ for (y = 0; y < fp_driver->res_y; y++) {
watchdog_reload();
- for (x = 0; x < FP_SENSOR_RES_X; x++, ptr++)
+ for (x = 0; x < fp_driver->res_x; x++, ptr++)
CPRINTF("%d ", *ptr);
CPRINTF("\n");
cflush();
@@ -846,7 +873,7 @@ DECLARE_CONSOLE_COMMAND(fpclear, command_fpclear, NULL,
int command_fpmaintenance(int argc, char **argv)
{
#ifdef HAVE_FP_PRIVATE_DRIVER
- return fp_maintenance();
+ return fp_driver->fp_maintenance();
#else
return EC_SUCCESS;
#endif /* #ifdef HAVE_FP_PRIVATE_DRIVER */