diff options
Diffstat (limited to 'driver/fpc1140.c')
-rw-r--r-- | driver/fpc1140.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/driver/fpc1140.c b/driver/fpc1140.c index edeeb6bd36..05094eb713 100644 --- a/driver/fpc1140.c +++ b/driver/fpc1140.c @@ -9,11 +9,18 @@ #include "ec_commands.h" #include "endian.h" #include "gpio.h" +#include "host_command.h" #include "mkbp_event.h" #include "spi.h" +#include "system.h" #include "task.h" #include "timer.h" #include "util.h" +#ifdef HAVE_PRIVATE +#include "fpc1145_private.h" + +uint8_t fp_buffer[FPC_IMAGE_SIZE]; +#endif #define CPRINTF(format, args...) cprintf(CC_FP, format, ## args) #define CPRINTS(format, args...) cprints(CC_FP, format, ## args) @@ -36,6 +43,13 @@ enum fpc_cmd { #endif static uint32_t fp_events; +static uint32_t sensor_mode; + +/* Opaque sensor configuration registers settings */ +static union { + struct ec_params_fp_sensor_config sensor_config; + uint8_t data[0x220]; +} u; static int fpc_send_cmd(const uint8_t cmd) { @@ -86,6 +100,9 @@ static uint8_t fpc_read_int(void) /* Reset and initialize the sensor IC */ static int fpc_init(void) { +#ifdef HAVE_PRIVATE + memcpy(&u.sensor_config, &fpc1145_config, fpc1145_config_size); +#endif /* configure the SPI controller (also ensure that CS_N is high) */ gpio_config_module(MODULE_SPI_MASTER, 1); spi_enable(CONFIG_SPI_FP_PORT, 1); @@ -149,3 +166,125 @@ static int fp_get_next_event(uint8_t *out) return sizeof(event_out); } DECLARE_EVENT_SOURCE(EC_MKBP_EVENT_FINGERPRINT, fp_get_next_event); + +static int fp_command_passthru(struct host_cmd_handler_args *args) +{ + const struct ec_params_fp_passthru *params = args->params; + void *out = args->response; + int rc; + int ret = EC_RES_SUCCESS; + + if (system_is_locked()) + return EC_RES_ACCESS_DENIED; + + if (params->len > args->params_size + + offsetof(struct ec_params_fp_passthru, data) || + params->len > args->response_max) + return EC_RES_INVALID_PARAM; + + rc = spi_transaction_async(&spi_devices[0], params->data, + params->len, out, SPI_READBACK_ALL); + if (params->flags & EC_FP_FLAG_NOT_COMPLETE) + rc |= spi_transaction_wait(&spi_devices[0]); + else + rc |= spi_transaction_flush(&spi_devices[0]); + + if (rc == EC_ERROR_TIMEOUT) + ret = EC_RES_TIMEOUT; + else if (rc) + ret = EC_RES_ERROR; + + args->response_size = params->len; + return ret; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_PASSTHRU, fp_command_passthru, EC_VER_MASK(0)); + +static int fp_command_sensor_config(struct host_cmd_handler_args *args) +{ + const struct ec_params_fp_sensor_config *p = args->params; + int i, index; + unsigned limit = args->params_size + - offsetof(struct ec_params_fp_sensor_config, data); + + /* Validate the content size */ + if (p->count > EC_FP_SENSOR_CONFIG_MAX_REGS || + args->params_size > sizeof(u)) + return EC_RES_INVALID_PARAM; + for (i = 0, index = 0; i < p->count; i++) { + if (index + p->len[i] > limit) + return EC_RES_INVALID_PARAM; + index += p->len[i]; + } + + memcpy(&u.sensor_config, p, args->params_size); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_SENSOR_CONFIG, fp_command_sensor_config, + EC_VER_MASK(0)); + +static int fp_command_mode(struct host_cmd_handler_args *args) +{ + const struct ec_params_fp_mode *p = args->params; + struct ec_response_fp_mode *r = args->response; + + if (!(p->mode & FP_MODE_DONT_CHANGE)) { + sensor_mode = p->mode; + if (p->mode & FP_MODE_DEEPSLEEP) { + /* TBD fpc_send_cmd(FPC_CMD_DEEPSLEEP) */; + } else { + if (p->mode & FP_MODE_FINGER_DOWN) + /* TBD: fp_prepare_capture()*/; + if (p->mode & FP_MODE_FINGER_UP) + /* TBD */; + } + } + + r->mode = sensor_mode; + args->response_size = sizeof(*r); + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_MODE, fp_command_mode, EC_VER_MASK(0)); + +static int fp_command_info(struct host_cmd_handler_args *args) +{ + struct ec_response_fp_info *r = args->response; + int rc; + const uint8_t cmd = FPC_CMD_HW_ID; + uint16_t id; + int ret = EC_RES_SUCCESS; + +#ifdef HAVE_PRIVATE + memcpy(r, &fpc1145_info, sizeof(*r)); +#else + return EC_RES_UNAVAILABLE; +#endif + rc = spi_transaction(SPI_FPC_DEVICE, &cmd, 1, (void *)&id, sizeof(id)); + if (rc) + return EC_RES_ERROR; + r->model_id = be16toh(id); + + args->response_size = sizeof(*r); + return ret; +} +DECLARE_HOST_COMMAND(EC_CMD_FP_INFO, fp_command_info, EC_VER_MASK(0)); + +static int fp_command_frame(struct host_cmd_handler_args *args) +{ +#ifdef HAVE_PRIVATE + const struct ec_params_fp_frame *params = args->params; + void *out = args->response; + + if (params->offset + params->size > sizeof(fp_buffer) || + params->size > args->response_max) + return EC_RES_INVALID_PARAM; + + memcpy(out, fp_buffer + params->offset, params->size); + + args->response_size = params->size; + return EC_RES_SUCCESS; +#else + return EC_RES_UNAVAILABLE; +#endif +} +DECLARE_HOST_COMMAND(EC_CMD_FP_FRAME, fp_command_frame, EC_VER_MASK(0)); |