diff options
Diffstat (limited to 'driver/fingerprint/fpc/bep/fpc_private.c')
-rw-r--r-- | driver/fingerprint/fpc/bep/fpc_private.c | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/driver/fingerprint/fpc/bep/fpc_private.c b/driver/fingerprint/fpc/bep/fpc_private.c new file mode 100644 index 0000000000..f69cffb0ce --- /dev/null +++ b/driver/fingerprint/fpc/bep/fpc_private.c @@ -0,0 +1,260 @@ +/* Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <stdint.h> +#include <stddef.h> + +#include "fpc_bio_algorithm.h" +#include "fpsensor.h" +#include "spi.h" +#include "system.h" +#include "util.h" + +#include STRINGIFY(FP_SENSOR_PRIVATE) + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_FP, format, ## args) +#define CPRINTS(format, args...) cprints(CC_FP, format, ## args) + +static uint8_t enroll_ctx[FP_ALGORITHM_ENROLLMENT_SIZE] = {0}; + +/* Recorded error flags */ +static uint16_t errors; + +/* FPC specific initialization and de-initialization functions */ +int fp_sensor_open(void); +int fp_sensor_close(void); + +/* Get FPC library version code.*/ +const char *fp_sensor_get_version(void); + +/* Get FPC library build info.*/ +const char *fp_sensor_get_build_info(void); + +/* Sensor description */ +static struct ec_response_fp_info ec_fp_sensor_info = { + /* Sensor identification */ + .vendor_id = FOURCC('F', 'P', 'C', ' '), + .product_id = 9, + .model_id = 1, + .version = 1, + /* Image frame characteristics */ + .frame_size = FP_SENSOR_IMAGE_SIZE, + .pixel_format = V4L2_PIX_FMT_GREY, + .width = FP_SENSOR_RES_X, + .height = FP_SENSOR_RES_Y, + .bpp = FP_SENSOR_RES_BPP, +}; + +typedef struct fpc_bep_sensor fpc_bep_sensor_t; + +typedef struct { + const fpc_bep_sensor_t *sensor; + uint32_t image_buffer_size; +} fpc_sensor_info_t; + +#if defined(FP_SENSOR_CONFIG_FPC1025) + +extern const fpc_bep_sensor_t fpc_bep_sensor_1025; +extern const fpc_bep_algorithm_t fpc_bep_algorithm_pfe_1025; + +const fpc_sensor_info_t fpc_sensor_info = { + .sensor = &fpc_bep_sensor_1025, + .image_buffer_size = FP_SENSOR_IMAGE_SIZE, +}; + +const fpc_bio_info_t fpc_bio_info = { + .algorithm = &fpc_bep_algorithm_pfe_1025, + .template_size = FP_ALGORITHM_TEMPLATE_SIZE, +}; + +#elif defined(FP_SENSOR_CONFIG_FPC1035) + +extern const fpc_bep_sensor_t fpc_bep_sensor_1035; +extern const fpc_bep_algorithm_t fpc_bep_algorithm_pfe_1035; + +const fpc_sensor_info_t fpc_sensor_info = { + .sensor = &fpc_bep_sensor_1035, + .image_buffer_size = FP_SENSOR_IMAGE_SIZE, +}; + +const fpc_bio_info_t fpc_bio_info = { + .algorithm = &fpc_bep_algorithm_pfe_1035, + .template_size = FP_ALGORITHM_TEMPLATE_SIZE, +}; +#else +#error "Sensor type not defined!" +#endif + +/* Sensor IC commands */ +enum fpc_cmd { + FPC_CMD_DEEPSLEEP = 0x2C, + FPC_CMD_HW_ID = 0xFC, +}; + +/* Maximum size of a sensor command SPI transfer */ +#define MAX_CMD_SPI_TRANSFER_SIZE 3 + +/* Memory for the SPI transfer buffer */ +static uint8_t spi_buf[MAX_CMD_SPI_TRANSFER_SIZE]; + +static int fpc_send_cmd(const uint8_t cmd) +{ + spi_buf[0] = cmd; + + return spi_transaction(SPI_FP_DEVICE, spi_buf, 1, spi_buf, + SPI_READBACK_ALL); +} + +void fp_sensor_low_power(void) +{ + fpc_send_cmd(FPC_CMD_DEEPSLEEP); +} + +static int fpc_check_hwid(void) +{ + uint16_t id; + int rc; + + spi_buf[0] = FPC_CMD_HW_ID; + + rc = spi_transaction(SPI_FP_DEVICE, spi_buf, 3, spi_buf, + SPI_READBACK_ALL); + if (rc) { + CPRINTS("FPC HW ID read failed %d", rc); + return FP_ERROR_SPI_COMM; + } + + id = (spi_buf[1] << 8) | spi_buf[2]; + if ((id >> 4) != FP_SENSOR_HWID) { + CPRINTS("FPC unknown silicon 0x%04x", id); + return FP_ERROR_BAD_HWID; + } + CPRINTS(FP_SENSOR_NAME " id 0x%04x", id); + + return EC_SUCCESS; +} + +/* Reset and initialize the sensor IC */ +int fp_sensor_init(void) +{ + int rc; + + /* Print the binary libfpbep.a library version */ + CPRINTS("FPC libfpbep.a %s", fp_sensor_get_version()); + + /* Print the BEP version and build time of the library */ + CPRINTS("Build information - %s", fp_sensor_get_build_info()); + + rc = fp_sensor_open(); + if (rc) { + errors |= FP_ERROR_INIT_FAIL; + CPRINTS("Error: fp_sensor_open() failed, result=%d", rc); + } + + errors |= fpc_check_hwid(); + + rc = bio_algorithm_init(); + if (rc < 0) { + errors |= FP_ERROR_INIT_FAIL; + CPRINTS("Error: bio_algorithm_init() failed, result=%d", rc); + } + + /* Go back to low power */ + fp_sensor_low_power(); + + return EC_SUCCESS; +} + +/* Deinitialize the sensor IC */ +int fp_sensor_deinit(void) +{ + int rc; + + rc = bio_algorithm_exit(); + if (rc < 0) + CPRINTS("Error: bio_algorithm_exit() failed, result=%d", rc); + + rc = fp_sensor_close(); + if (rc < 0) + CPRINTS("Error: fp_sensor_close() failed, result=%d", rc); + + return rc; +} + +int fp_sensor_get_info(struct ec_response_fp_info *resp) +{ + int rc; + + spi_buf[0] = FPC_CMD_HW_ID; + + memcpy(resp, &ec_fp_sensor_info, sizeof(struct ec_response_fp_info)); + + rc = spi_transaction(SPI_FP_DEVICE, spi_buf, 3, spi_buf, + SPI_READBACK_ALL); + if (rc) + return EC_RES_ERROR; + + resp->model_id = (spi_buf[1] << 8) | spi_buf[2]; + resp->errors = errors; + + return EC_SUCCESS; +} + +int fp_finger_match(void *templ, uint32_t templ_count, uint8_t *image, + int32_t *match_index, uint32_t *update_bitmap) +{ + int rc; + + rc = bio_template_image_match_list(templ, templ_count, image, + match_index, update_bitmap); + if (rc < 0) + CPRINTS("Error: bio_template_image_match_list() failed, result=%d", + rc); + + return rc; +} + +int fp_enrollment_begin(void) +{ + int rc; + bio_enrollment_t bio_enroll = enroll_ctx; + + rc = bio_enrollment_begin(&bio_enroll); + if (rc < 0) + CPRINTS("Error: bio_enrollment_begin() failed, result=%d", rc); + + return rc; +} + +int fp_enrollment_finish(void *templ) +{ + int rc; + bio_enrollment_t bio_enroll = enroll_ctx; + bio_template_t bio_templ = templ; + + rc = bio_enrollment_finish(bio_enroll, templ ? &bio_templ : NULL); + if (rc < 0) + CPRINTS("Error: bio_enrollment_finish() failed, result=%d", rc); + + return rc; +} + +int fp_finger_enroll(uint8_t *image, int *completion) +{ + int rc; + bio_enrollment_t bio_enroll = enroll_ctx; + + rc = bio_enrollment_add_image(bio_enroll, image); + if (rc < 0) { + CPRINTS("Error: bio_enrollment_add_image() failed, result=%d", + rc); + return rc; + } + + *completion = bio_enrollment_get_percent_complete(bio_enroll); + + return rc; +} |