blob: af149eb3f9817760c55a6d5a63382f8f5ef4afd6 [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 <fpsensor/fpsensor.h>
#include <fpsensor/fpsensor_detect.h>
#include <mkbp_event.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))
#define FP_SIMULATOR_IMAGE_FRAME_PARAM_INITIALIZER(idx, node_id) \
{ \
.frame_size = FINGERPRINT_SENSOR_FRAME_SIZE(idx, node_id), \
.image_data_offset_bytes = \
FINGERPRINT_SENSOR_IMAGE_OFFSET(idx, node_id), \
.pixel_format = \
FINGERPRINT_SENSOR_V4L2_PIXEL_FORMAT(idx, node_id), \
.width = FINGERPRINT_SENSOR_RES_X(idx, node_id), \
.height = FINGERPRINT_SENSOR_RES_Y(idx, node_id), \
.bpp = FINGERPRINT_SENSOR_RES_BPP(idx, node_id), \
.fp_capture_type = \
FINGERPRINT_SENSOR_CAPTURE_TYPE(idx, node_id), \
.reserved = 0, \
}
static const struct fingerprint_image_frame_params
expected_image_frame_params_array[] = { LISTIFY(
NUM_IMAGE_CAPTURE_TYPES,
FP_SIMULATOR_IMAGE_FRAME_PARAM_INITIALIZER, (, ),
DT_NODELABEL(fpsensor_sim)) };
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_shim, test_shim_sensor_type_elan)
{
const struct gpio_dt_spec *sensor_sel_pin =
GPIO_DT_FROM_NODELABEL(fp_sensor_sel);
gpio_emul_input_set(sensor_sel_pin->port, sensor_sel_pin->pin, 0);
zassert_equal(fpsensor_detect_get_type(), FP_SENSOR_TYPE_ELAN);
}
ZTEST_USER(fpsensor_shim, test_shim_sensor_type_fpc)
{
const struct gpio_dt_spec *sensor_sel_pin =
GPIO_DT_FROM_NODELABEL(fp_sensor_sel);
gpio_emul_input_set(sensor_sel_pin->port, sensor_sel_pin->pin, 1);
zassert_equal(fpsensor_detect_get_type(), FP_SENSOR_TYPE_FPC);
}
ZTEST_USER(fpsensor_shim, test_shim_init_success)
{
zassert_ok(fp_sensor_init());
}
ZTEST_USER(fpsensor_shim, test_shim_init_sensor_init_failed)
{
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.init_result = -EINVAL;
fingerprint_set_state(fp_sim, &state);
zassert_equal(fp_sensor_init(), -EINVAL);
}
ZTEST_USER(fpsensor_shim, test_shim_init_algorithm_init_failed)
{
mock_alg_init_fake.return_val = -EINVAL;
zassert_equal(fp_sensor_init(), -EINVAL);
zassert_equal(mock_alg_init_fake.call_count, 1);
}
ZTEST_USER(fpsensor_shim, test_shim_init_sensor_config_failed)
{
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.config_result = -EINVAL;
fingerprint_set_state(fp_sim, &state);
zassert_equal(fp_sensor_init(), -EINVAL);
}
ZTEST_USER(fpsensor_shim, test_shim_deinit_success)
{
zassert_ok(fp_sensor_init());
zassert_ok(fp_sensor_deinit());
}
ZTEST_USER(fpsensor_shim, test_shim_deinit_algorithm_exit_failed)
{
zassert_ok(fp_sensor_init());
mock_alg_exit_fake.return_val = -EINVAL;
zassert_equal(fp_sensor_deinit(), -EINVAL);
zassert_equal(mock_alg_exit_fake.call_count, 1);
}
ZTEST_USER(fpsensor_shim, test_shim_deinit_sensor_deinit_failed)
{
struct fingerprint_sensor_state state;
zassert_ok(fp_sensor_init());
fingerprint_get_state(fp_sim, &state);
state.deinit_result = -EINVAL;
fingerprint_set_state(fp_sim, &state);
zassert_equal(fp_sensor_deinit(), -EINVAL);
}
ZTEST_USER(fpsensor_shim, test_shim_get_info_success)
{
/* We need to initialize driver first to initialize 'error' field */
zassert_ok(fp_sensor_init());
zassert_ok(fp_sensor_get_info(test_info_buffer, test_info_buffer_size));
zassert_equal(test_info_buffer->sensor_info.vendor_id,
FOURCC('C', 'r', 'O', 'S'));
zassert_equal(test_info_buffer->sensor_info.product_id, 0);
/*
* Last 4 bits of hardware id is a year of sensor production,
* could differ between sensors.
*/
zassert_equal(test_info_buffer->sensor_info.model_id, 0);
zassert_equal(test_info_buffer->sensor_info.version, 0);
zassert_equal(test_info_buffer->sensor_info.errors,
FINGERPRINT_ERROR_DEAD_PIXELS_UNKNOWN);
for (int i = 0; i < NUM_IMAGE_CAPTURE_TYPES; ++i) {
zassert_equal(
memcmp(&test_info_buffer->image_frame_params[i],
&expected_image_frame_params_array[i],
sizeof(struct fingerprint_image_frame_params)),
0, "Struct comparison failed at index %d", i);
}
}
ZTEST_USER(fpsensor_shim, test_shim_get_info_failed)
{
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.get_info_result = -EINVAL;
fingerprint_set_state(fp_sim, &state);
zassert_equal(fp_sensor_get_info(test_info_buffer,
test_info_buffer_size),
-EINVAL);
}
ZTEST_USER(fpsensor_shim, test_shim_finger_status_present)
{
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.finger_state = FINGERPRINT_FINGER_STATE_PRESENT;
fingerprint_set_state(fp_sim, &state);
zassert_equal(fp_finger_status(), FINGER_PRESENT);
}
ZTEST_USER(fpsensor_shim, test_shim_finger_status_error)
{
struct fingerprint_sensor_state state;
fingerprint_get_state(fp_sim, &state);
state.finger_state = static_cast<fingerprint_finger_state>(-EINVAL);
fingerprint_set_state(fp_sim, &state);
zassert_equal(fp_finger_status(), FINGER_NONE);
}
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,
};
fingerprint_set_state(fp_sim, &state);
RESET_FAKE(mock_alg_init);
RESET_FAKE(mock_alg_exit);
RESET_FAKE(mock_alg_enroll_start);
RESET_FAKE(mock_alg_enroll_step);
RESET_FAKE(mock_alg_enroll_finish);
RESET_FAKE(mock_alg_match);
}
ZTEST_SUITE(fpsensor_shim, NULL, NULL, fpsensor_before, NULL, NULL);