blob: 0615300fe7ef93b6f9ccbbebc996f84a9e4dd44a [file]
/* Copyright 2024 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "mock_fingerprint_algorithm.h"
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/emul.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_emul.h>
#include <zephyr/fff.h>
#include <zephyr/sys/util.h>
#include <zephyr/ztest.h>
#include <zephyr/ztest_assert.h>
#include <drivers/fingerprint.h>
#include <drivers/fingerprint_sim.h>
#include <ec_commands.h>
#include <ec_tasks.h>
#include <fpsensor/fpsensor_state.h>
#include <host_command.h>
DEFINE_FFF_GLOBALS;
FAKE_VALUE_FUNC(int, mkbp_send_event, uint8_t);
#define fp_sim DEVICE_DT_GET(DT_CHOSEN(cros_fp_fingerprint_sensor))
static const size_t test_info_buffer_size =
sizeof(struct ec_response_fp_info_v3) +
sizeof(struct fp_image_frame_params_v2) * FP_MAX_CAPTURE_TYPES;
static uint8_t buffer[test_info_buffer_size];
static struct ec_response_fp_info_v3 *test_info_buffer =
(struct ec_response_fp_info_v3 *)buffer;
ZTEST_USER(fpsensor_init, test_tpm_seed_init)
{
struct ec_response_fp_encryption_status status;
struct ec_params_fp_seed params = {
.struct_version = 4,
.reserved = 0,
.seed = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
};
/* Get FP encryption flags. */
zassert_ok(ec_cmd_fp_encryption_status(NULL, &status));
/* Confirm TPM seed is not set */
zassert_true(status.valid_flags & FP_ENC_STATUS_SEED_SET);
zassert_false(status.status & FP_ENC_STATUS_SEED_SET);
/* Set TPM seed. */
zassert_ok(ec_cmd_fp_seed(NULL, &params));
/* Get FP encryption flags. */
zassert_ok(ec_cmd_fp_encryption_status(NULL, &status));
/* Confirm that FP_ENC_STATUS_SEED_SET is set. */
zassert_true(status.valid_flags & FP_ENC_STATUS_SEED_SET);
zassert_true(status.status & FP_ENC_STATUS_SEED_SET);
/* Try to set TPM seed once again (should fail). */
zassert_equal(EC_RES_ACCESS_DENIED, ec_cmd_fp_seed(NULL, &params));
}
ZTEST_USER(fpsensor_init, test_tpm_seed_invalid)
{
struct ec_params_fp_seed params = {
/* 0 is not a valid structure version. */
.struct_version = 0,
.reserved = 0,
.seed = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
};
/* Try to set TPM seed (should fail). */
zassert_equal(EC_RES_INVALID_PARAM, ec_cmd_fp_seed(NULL, &params));
}
ZTEST_USER(fpsensor_init, test_set_fp_context)
{
struct ec_params_fp_context_v1 params = {
.action = FP_CONTEXT_ASYNC,
.userid = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 },
};
struct ec_response_fp_encryption_status status;
/* Set context (asynchronously). */
zassert_ok(ec_cmd_fp_context_v1(NULL, &params));
/* Now any attempt to set context should return EC_RES_BUSY. */
zassert_equal(EC_RES_BUSY, ec_cmd_fp_context_v1(NULL, &params));
/* Now any attempt to get command result should return EC_RES_BUSY. */
params.action = FP_CONTEXT_GET_RESULT;
zassert_equal(EC_RES_BUSY, ec_cmd_fp_context_v1(NULL, &params));
/* Give opportunity for fpsensor task to change mode. */
k_msleep(1);
/* Get command result. */
zassert_ok(ec_cmd_fp_context_v1(NULL, &params));
/* Get FP encryption flags. */
zassert_ok(ec_cmd_fp_encryption_status(NULL, &status));
/* Confirm that FP_CONTEXT_USER_ID_SET is set. */
zassert_true(status.status & FP_CONTEXT_USER_ID_SET);
}
ZTEST_USER(fpsensor_init, test_maintenance_mode_dead_pixel_3)
{
struct ec_params_fp_mode params = {
.mode = FP_MODE_SENSOR_MAINTENANCE,
};
struct ec_response_fp_mode response;
struct fingerprint_sensor_state state;
const int dead_pixels = 3;
/* Confirm that number of dead pixels is unknown. */
zassert_ok(ec_cmd_fp_info_v3(NULL, test_info_buffer,
test_info_buffer_size));
zassert_equal(
FP_ERROR_DEAD_PIXELS(test_info_buffer->sensor_info.errors),
FP_ERROR_DEAD_PIXELS_UNKNOWN);
fingerprint_get_state(fp_sim, &state);
state.bad_pixels = dead_pixels;
fingerprint_set_state(fp_sim, &state);
/* Change fingerprint mode to maintenance. */
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_true(response.mode & FP_MODE_SENSOR_MAINTENANCE);
/* Give opportunity for fpsensor task to change mode. */
k_msleep(1);
/* Check that maintenance was run. */
fingerprint_get_state(fp_sim, &state);
zassert_true(state.maintenance_ran);
/* Confirm that number of dead pixels is correct. */
zassert_ok(ec_cmd_fp_info_v3(NULL, test_info_buffer,
test_info_buffer_size));
zassert_equal(
FP_ERROR_DEAD_PIXELS(test_info_buffer->sensor_info.errors),
dead_pixels);
/*
* Confirm that maintenance flag is not set after the maintenance
* operation is finished.
*/
params.mode = FP_MODE_DONT_CHANGE;
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_false(response.mode & FP_MODE_SENSOR_MAINTENANCE);
}
ZTEST_USER(fpsensor_init, test_maintenance_mode_dead_pixel_max_plus_2)
{
struct ec_params_fp_mode params = {
.mode = FP_MODE_SENSOR_MAINTENANCE,
};
struct ec_response_fp_mode response;
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.bad_pixels = FP_ERROR_DEAD_PIXELS_MAX + 2;
fingerprint_set_state(fp_sim, &state);
/* Change fingerprint mode to maintenance. */
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_true(response.mode & FP_MODE_SENSOR_MAINTENANCE);
/* Give opportunity for fpsensor task to change mode. */
k_msleep(1);
/* Check that maintenance was run. */
fingerprint_get_state(fp_sim, &state);
zassert_true(state.maintenance_ran);
/* Confirm that number of dead pixels is correct. */
zassert_ok(ec_cmd_fp_info_v3(NULL, test_info_buffer,
test_info_buffer_size));
zassert_equal(
FP_ERROR_DEAD_PIXELS(test_info_buffer->sensor_info.errors),
FP_ERROR_DEAD_PIXELS_MAX);
/*
* Confirm that maintenance flag is not set after the maintenance
* operation is finished.
*/
params.mode = FP_MODE_DONT_CHANGE;
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_false(response.mode & FP_MODE_SENSOR_MAINTENANCE);
}
ZTEST_USER(fpsensor_init, test_maintenance_mode_dead_pixel_max)
{
struct ec_params_fp_mode params = {
.mode = FP_MODE_SENSOR_MAINTENANCE,
};
struct ec_response_fp_mode response;
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.bad_pixels = FP_ERROR_DEAD_PIXELS_MAX;
fingerprint_set_state(fp_sim, &state);
/* Change fingerprint mode to maintenance. */
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_true(response.mode & FP_MODE_SENSOR_MAINTENANCE);
/* Give opportunity for fpsensor task to change mode. */
k_msleep(1);
/* Check that maintenance was run. */
fingerprint_get_state(fp_sim, &state);
zassert_true(state.maintenance_ran);
/* Confirm that number of dead pixels is correct. */
zassert_ok(ec_cmd_fp_info_v3(NULL, test_info_buffer,
test_info_buffer_size));
zassert_equal(
FP_ERROR_DEAD_PIXELS(test_info_buffer->sensor_info.errors),
FP_ERROR_DEAD_PIXELS_MAX);
/*
* Confirm that maintenance flag is not set after the maintenance
* operation is finished.
*/
params.mode = FP_MODE_DONT_CHANGE;
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_false(response.mode & FP_MODE_SENSOR_MAINTENANCE);
}
ZTEST_USER(fpsensor_init, test_maintenance_mode_dead_pixel_max_minus_1)
{
struct ec_params_fp_mode params = {
.mode = FP_MODE_SENSOR_MAINTENANCE,
};
struct ec_response_fp_mode response;
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.bad_pixels = FP_ERROR_DEAD_PIXELS_MAX - 1;
fingerprint_set_state(fp_sim, &state);
/* Change fingerprint mode to maintenance. */
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_true(response.mode & FP_MODE_SENSOR_MAINTENANCE);
/* Give opportunity for fpsensor task to change mode. */
k_msleep(1);
/* Check that maintenance was run. */
fingerprint_get_state(fp_sim, &state);
zassert_true(state.maintenance_ran);
/* Confirm that number of dead pixels is correct. */
zassert_ok(ec_cmd_fp_info_v3(NULL, test_info_buffer,
test_info_buffer_size));
zassert_equal(
FP_ERROR_DEAD_PIXELS(test_info_buffer->sensor_info.errors),
FP_ERROR_DEAD_PIXELS_MAX - 1);
/*
* Confirm that maintenance flag is not set after the maintenance
* operation is finished.
*/
params.mode = FP_MODE_DONT_CHANGE;
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_false(response.mode & FP_MODE_SENSOR_MAINTENANCE);
}
static void *fpsensor_setup(void)
{
/* Start shimmed tasks. */
start_ec_tasks();
k_msleep(100);
return NULL;
}
static void fpsensor_before(void *f)
{
struct fingerprint_sensor_state state = {
.bad_pixels = 0,
.maintenance_ran = false,
.detect_mode = false,
.low_power_mode = false,
.finger_state = FINGERPRINT_FINGER_STATE_NONE,
.init_result = 0,
.deinit_result = 0,
.config_result = 0,
.get_info_result = 0,
.acquire_image_result = FINGERPRINT_SENSOR_SCAN_GOOD,
.last_acquire_image_mode = -1,
};
struct ec_params_fp_mode params = {
.mode = 0,
};
struct ec_response_fp_mode response;
zassert_ok(ec_cmd_fp_mode(NULL, &params, &response));
zassert_equal(response.mode, 0);
/* Give opportunity for fpsensor task to change mode. */
k_msleep(1);
fingerprint_set_state(fp_sim, &state);
RESET_FAKE(mkbp_send_event);
}
ZTEST_SUITE(fpsensor_init, NULL, fpsensor_setup, fpsensor_before, NULL, NULL);