summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2017-03-30 10:27:46 +0200
committerchrome-bot <chrome-bot@chromium.org>2017-05-23 05:57:13 -0700
commit563456c6582d785483c32cbf01d97c413b303324 (patch)
treec5686e9fd40469e3fbd78f4e876741193f28da9f
parent0ce33d0e87c1e7418d7908f14e228fbc00059f3d (diff)
downloadchrome-ec-563456c6582d785483c32cbf01d97c413b303324.tar.gz
eve_fp: add more fingerprint host commands
Move the existing fingerprint host command in the driver and add more of them to prepare the new fingerprint architecture. The commands are mostly stubbed for now. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> CQ-DEPEND=*364728 BRANCH=none BUG=b:35648259 TEST=make BOARD=eve_fp (with and without a private repository) do a fingerprint image capture with 'fptest'. Change-Id: Ie17a5fde2d6470c6272e8059bddc845cea07aff2 Reviewed-on: https://chromium-review.googlesource.com/491071 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/eve_fp/board.c33
-rw-r--r--driver/fpc1140.c139
-rw-r--r--include/ec_commands.h73
-rw-r--r--util/ectool.c113
4 files changed, 324 insertions, 34 deletions
diff --git a/board/eve_fp/board.c b/board/eve_fp/board.c
index 94ae0daade..21b1c2668b 100644
--- a/board/eve_fp/board.c
+++ b/board/eve_fp/board.c
@@ -7,7 +7,6 @@
#include "console.h"
#include "gpio.h"
#include "hooks.h"
-#include "host_command.h"
#include "spi.h"
#include "system.h"
#include "task.h"
@@ -57,35 +56,3 @@ static void board_init(void)
hook_call_deferred(&ap_deferred_data, 0);
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
-
-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));
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));
diff --git a/include/ec_commands.h b/include/ec_commands.h
index abc71517bd..4ef579af65 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -2881,6 +2881,12 @@ struct __ec_align2 ec_response_keyboard_factory_test {
uint16_t shorted; /* Keyboard pins are shorted */
};
+/* Fingerprint events in 'fp_events' for EC_MKBP_EVENT_FINGERPRINT */
+#define EC_MKBP_FP_RAW_EVENT(fp_events) ((fp_events) & 0x00FFFFFF)
+#define EC_MKBP_FP_FINGER_DOWN (1 << 29)
+#define EC_MKBP_FP_FINGER_UP (1 << 30)
+#define EC_MKBP_FP_IMAGE_READY (1 << 31)
+
/*****************************************************************************/
/* Temperature sensor commands */
@@ -4104,7 +4110,7 @@ struct __ec_align4 ec_params_rwsig_action {
/*****************************************************************************/
/* Fingerprint MCU commands: range 0x0400-0x040x */
-/* Fingerprint SPI sensor passthru command */
+/* Fingerprint SPI sensor passthru command: prototyping ONLY */
#define EC_CMD_FP_PASSTHRU 0x0400
#define EC_FP_FLAG_NOT_COMPLETE 0x1
@@ -4115,6 +4121,71 @@ struct __ec_align2 ec_params_fp_passthru {
uint8_t data[]; /* Data to send */
};
+/* Fingerprint sensor configuration command: prototyping ONLY */
+#define EC_CMD_FP_SENSOR_CONFIG 0x0401
+
+#define EC_FP_SENSOR_CONFIG_MAX_REGS 16
+
+struct __ec_align2 ec_params_fp_sensor_config {
+ uint8_t count; /* Number of setup registers */
+ /*
+ * the value to send to each of the 'count' setup registers
+ * is stored in the 'data' array for 'len' bytes just after
+ * the previous one.
+ */
+ uint8_t len[EC_FP_SENSOR_CONFIG_MAX_REGS];
+ uint8_t data[];
+};
+
+/* Configure the Fingerprint MCU behavior */
+#define EC_CMD_FP_MODE 0x0402
+
+/* Put the sensor in its lowest power mode */
+#define FP_MODE_DEEPSLEEP (1<<0)
+/* Wait to see a finger on the sensor */
+#define FP_MODE_FINGER_DOWN (1<<1)
+/* Poll until the finger has left the sensor */
+#define FP_MODE_FINGER_UP (1<<2)
+/* Capture the current finger image */
+#define FP_MODE_CAPTURE (1<<3)
+/* special value: don't change anything just read back current mode */
+#define FP_MODE_DONT_CHANGE (1<<31)
+
+struct __ec_align4 ec_params_fp_mode {
+ uint32_t mode; /* as defined by FP_MODE_ constants */
+ /* TBD */
+};
+
+struct __ec_align4 ec_response_fp_mode {
+ uint32_t mode; /* as defined by FP_MODE_ constants */
+ /* TBD */
+};
+
+/* Retrieve Fingerprint sensor information */
+#define EC_CMD_FP_INFO 0x0403
+
+struct __ec_align2 ec_response_fp_info {
+ /* Sensor identification */
+ uint32_t vendor_id;
+ uint32_t product_id;
+ uint32_t model_id;
+ uint32_t version;
+ /* Image frame characteristics */
+ uint32_t frame_size;
+ uint32_t pixel_format; /* using V4L2_PIX_FMT_ */
+ uint16_t width;
+ uint16_t height;
+ uint16_t bpp;
+};
+
+/* Get the last captured finger frame: TODO: will be AES-encrypted */
+#define EC_CMD_FP_FRAME 0x0404
+
+struct __ec_align4 ec_params_fp_frame {
+ uint32_t offset;
+ uint32_t size;
+};
+
/*****************************************************************************/
/*
* Reserve a range of host commands for board-specific, experimental, or
diff --git a/util/ectool.c b/util/ectool.c
index 6a8441f172..039ddcb9d9 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -112,6 +112,12 @@ const char help_str[] =
" Reads from EC flash to a file\n"
" flashwrite <offset> <infile>\n"
" Writes to EC flash from a file\n"
+ " fpframe\n"
+ " Retrieve the finger image as a PGM image\n"
+ " fpinfo\n"
+ " Prints information about the Fingerprint sensor\n"
+ " fpmode [capture|deepsleep|fingerdown|fingerup]\n"
+ " Configure/Read the fingerprint sensor current mode\n"
" forcelidopen <enable>\n"
" Forces the lid switch to open position\n"
" gpioget <GPIO name>\n"
@@ -1059,6 +1065,110 @@ int cmd_rwsig_action(int argc, char *argv[])
return ec_command(EC_CMD_RWSIG_ACTION, 0, &req, sizeof(req), NULL, 0);
}
+int cmd_fp_mode(int argc, char *argv[])
+{
+ struct ec_params_fp_mode p;
+ struct ec_response_fp_mode r;
+ uint32_t mode = 0;
+ int i, rv;
+
+ if (argc == 1)
+ mode = FP_MODE_DONT_CHANGE;
+ for (i = 1; i < argc; i++) {
+ if (!strncmp(argv[i], "deepsleep", 9))
+ mode |= FP_MODE_DEEPSLEEP;
+ else if (!strncmp(argv[i], "fingerdown", 10))
+ mode |= FP_MODE_FINGER_DOWN;
+ else if (!strncmp(argv[i], "fingerup", 8))
+ mode |= FP_MODE_FINGER_UP;
+ else if (!strncmp(argv[i], "capture", 7))
+ mode |= FP_MODE_CAPTURE;
+ }
+
+ p.mode = mode;
+ rv = ec_command(EC_CMD_FP_MODE, 0, &p, sizeof(p), &r, sizeof(r));
+ if (rv < 0)
+ return rv;
+
+ printf("FP mode: (0x%x) ", r.mode);
+ if (r.mode & FP_MODE_DEEPSLEEP)
+ printf("deepsleep ");
+ if (r.mode & FP_MODE_FINGER_DOWN)
+ printf("finger-down ");
+ if (r.mode & FP_MODE_FINGER_UP)
+ printf("finger-up ");
+ if (r.mode & FP_MODE_CAPTURE)
+ printf("capture ");
+ printf("\n");
+ return rv;
+}
+
+int cmd_fp_info(int argc, char *argv[])
+{
+ struct ec_response_fp_info r;
+ int rv;
+
+ rv = ec_command(EC_CMD_FP_INFO, 0, NULL, 0, &r, sizeof(r));
+ if (rv < 0)
+ return rv;
+
+ printf("Fingerprint sensor: vendor %x product %x model %x version %x\n",
+ r.vendor_id, r.product_id, r.model_id, r.version);
+ printf("Image: size %dx%d %d bpp\n", r.width, r.height, r.bpp);
+
+ return 0;
+}
+
+int cmd_fp_frame(int argc, char *argv[])
+{
+ struct ec_response_fp_info r;
+ struct ec_params_fp_frame p;
+ int rv = 0;
+ size_t stride, size;
+ uint8_t *buffer8 = ec_inbuf;
+
+ rv = ec_command(EC_CMD_FP_INFO, 0, NULL, 0, &r, sizeof(r));
+ if (rv < 0)
+ return rv;
+
+ stride = (size_t)r.width * r.bpp/8;
+ if (stride > ec_max_insize) {
+ fprintf(stderr, "Not implemented for line size %zu B "
+ "(%u pixels) > EC transfer size %d\n",
+ stride, r.width, ec_max_insize);
+ return -1;
+ }
+ if (r.bpp != 8) {
+ fprintf(stderr, "Not implemented for BPP = %d != 8\n", r.bpp);
+ return -1;
+ }
+
+ size = stride * r.height;
+
+ /* Print 8-bpp PGM ASCII header */
+ printf("P2\n%d %d\n%d\n", r.width, r.height, (1 << r.bpp) - 1);
+
+ p.offset = 0;
+ p.size = stride;
+ while (size) {
+ int x;
+
+ rv = ec_command(EC_CMD_FP_FRAME, 0, &p, sizeof(p),
+ ec_inbuf, stride);
+ if (rv < 0)
+ return rv;
+ p.offset += stride;
+ size -= stride;
+
+ for (x = 0; x < stride; x++)
+ printf("%d ", buffer8[x]);
+ printf("\n");
+ }
+ printf("# END OF FILE\n");
+
+ return 0;
+}
+
/**
* determine if in GFU mode or not.
*
@@ -7064,6 +7174,9 @@ const struct command commands[] = {
{"flashspiinfo", cmd_flash_spi_info},
{"flashpd", cmd_flash_pd},
{"forcelidopen", cmd_force_lid_open},
+ {"fpframe", cmd_fp_frame},
+ {"fpinfo", cmd_fp_info},
+ {"fpmode", cmd_fp_mode},
{"gpioget", cmd_gpio_get},
{"gpioset", cmd_gpio_set},
{"hangdetect", cmd_hang_detect},