/*
 * Copyright (c) 2017 BayLibre, SAS
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <errno.h>
#include <string.h>

#include <zephyr/zephyr.h>
#include <zephyr/device.h>
#include <stdio.h>
#include <zephyr/sys/util.h>

#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/i2c/target/eeprom.h>

#include <ztest.h>

#define NODE_EP0 DT_NODELABEL(eeprom0)
#define NODE_EP1 DT_NODELABEL(eeprom1)

#define TEST_DATA_SIZE	20
static const uint8_t eeprom_0_data[TEST_DATA_SIZE] = "0123456789abcdefghij";
static const uint8_t eeprom_1_data[TEST_DATA_SIZE] = "jihgfedcba9876543210";
static uint8_t i2c_buffer[TEST_DATA_SIZE];

/*
 * We need 5x(buffer size) + 1 to print a comma-separated list of each
 * byte in hex, plus a null.
 */
uint8_t buffer_print_eeprom[TEST_DATA_SIZE * 5 + 1];
uint8_t buffer_print_i2c[TEST_DATA_SIZE * 5 + 1];

static void to_display_format(const uint8_t *src, size_t size, char *dst)
{
	size_t i;

	for (i = 0; i < size; i++) {
		sprintf(dst + 5 * i, "0x%02x,", src[i]);
	}
}

static int run_full_read(const struct device *i2c, uint8_t addr,
			 const uint8_t *comp_buffer)
{
	int ret;

	TC_PRINT("Testing full read: Master: %s, address: 0x%x\n",
		 i2c->name, addr);

	/* Read EEPROM from I2C Master requests, then compare */
	ret = i2c_burst_read(i2c, addr, 0, i2c_buffer, TEST_DATA_SIZE);
	zassert_equal(ret, 0, "Failed to read EEPROM");

	if (memcmp(i2c_buffer, comp_buffer, TEST_DATA_SIZE)) {
		to_display_format(i2c_buffer, TEST_DATA_SIZE,
				  buffer_print_i2c);
		to_display_format(comp_buffer, TEST_DATA_SIZE,
				  buffer_print_eeprom);
		TC_PRINT("Error: Buffer contents are different: %s\n",
			 buffer_print_i2c);
		TC_PRINT("                         vs expected: %s\n",
			 buffer_print_eeprom);
		return -EIO;
	}

	return 0;
}

static int run_partial_read(const struct device *i2c, uint8_t addr,
			    const uint8_t *comp_buffer, unsigned int offset)
{
	int ret;

	TC_PRINT("Testing partial read. Master: %s, address: 0x%x, off=%d\n",
		 i2c->name, addr, offset);

	ret = i2c_burst_read(i2c, addr,
			     offset, i2c_buffer, TEST_DATA_SIZE-offset);
	zassert_equal(ret, 0, "Failed to read EEPROM");

	if (memcmp(i2c_buffer, &comp_buffer[offset], TEST_DATA_SIZE-offset)) {
		to_display_format(i2c_buffer, TEST_DATA_SIZE-offset,
				  buffer_print_i2c);
		to_display_format(&comp_buffer[offset], TEST_DATA_SIZE-offset,
				  buffer_print_eeprom);
		TC_PRINT("Error: Buffer contents are different: %s\n",
			 buffer_print_i2c);
		TC_PRINT("                         vs expected: %s\n",
			 buffer_print_eeprom);
		return -EIO;
	}

	return 0;
}

static int run_program_read(const struct device *i2c, uint8_t addr,
			    unsigned int offset)
{
	int ret, i;

	TC_PRINT("Testing program. Master: %s, address: 0x%x, off=%d\n",
		i2c->name, addr, offset);

	for (i = 0 ; i < TEST_DATA_SIZE-offset ; ++i) {
		i2c_buffer[i] = i;
	}

	ret = i2c_burst_write(i2c, addr,
			      offset, i2c_buffer, TEST_DATA_SIZE-offset);
	zassert_equal(ret, 0, "Failed to write EEPROM");

	(void)memset(i2c_buffer, 0xFF, TEST_DATA_SIZE);

	/* Read back EEPROM from I2C Master requests, then compare */
	ret = i2c_burst_read(i2c, addr,
			     offset, i2c_buffer, TEST_DATA_SIZE-offset);
	zassert_equal(ret, 0, "Failed to read EEPROM");

	for (i = 0 ; i < TEST_DATA_SIZE-offset ; ++i) {
		if (i2c_buffer[i] != i) {
			to_display_format(i2c_buffer, TEST_DATA_SIZE-offset,
					  buffer_print_i2c);
			TC_PRINT("Error: Unexpected buffer content: %s\n",
				 buffer_print_i2c);
			return -EIO;
		}
	}

	return 0;
}

void test_eeprom_target(void)
{
	const char *label_0 = DT_LABEL(NODE_EP0);
	const struct device *eeprom_0 = device_get_binding(label_0);
	const struct device *i2c_0 = device_get_binding(DT_BUS_LABEL(NODE_EP0));
	int addr_0 = DT_REG_ADDR(NODE_EP0);
	const char *label_1 = DT_LABEL(NODE_EP1);
	const struct device *eeprom_1 = device_get_binding(label_1);
	const struct device *i2c_1 = device_get_binding(DT_BUS_LABEL(NODE_EP1));
	int addr_1 = DT_REG_ADDR(NODE_EP1);
	int ret, offset;

	zassert_not_null(i2c_0, "EP0 I2C device %s not found",
			 DT_BUS_LABEL(NODE_EP0));
	zassert_not_null(eeprom_0, "EEPROM device %s not found", label_0);

	TC_PRINT("Found EP0 %s on I2C Master device %s at addr %02x\n",
		 label_0, DT_BUS_LABEL(NODE_EP0), addr_0);

	zassert_not_null(i2c_1, "I2C device %s not found",
			 DT_BUS_LABEL(NODE_EP1));
	zassert_not_null(eeprom_1, "EEPROM device %s not found", label_1);

	TC_PRINT("Found EP1 %s on I2C Master device %s at addr %02x\n",
		 label_1, DT_BUS_LABEL(NODE_EP1), addr_1);

	if (IS_ENABLED(CONFIG_APP_DUAL_ROLE_I2C)) {
		TC_PRINT("Testing dual-role\n");
	} else {
		TC_PRINT("Testing single-role\n");
	}

	/* Program differentiable data into the two devices through a back door
	 * that doesn't use I2C.
	 */
	ret = eeprom_target_program(eeprom_0, eeprom_0_data, TEST_DATA_SIZE);
	zassert_equal(ret, 0, "Failed to program EEPROM %s", label_0);
	if (IS_ENABLED(CONFIG_APP_DUAL_ROLE_I2C)) {
		ret = eeprom_target_program(eeprom_1, eeprom_1_data,
					   TEST_DATA_SIZE);
		zassert_equal(ret, 0, "Failed to program EEPROM %s", label_1);
	}

	/* Attach each EEPROM to its owning bus as a target device. */
	ret = i2c_target_driver_register(eeprom_0);
	zassert_equal(ret, 0, "Failed to register EEPROM %s", label_0);

	if (IS_ENABLED(CONFIG_APP_DUAL_ROLE_I2C)) {
		ret = i2c_target_driver_register(eeprom_1);
		zassert_equal(ret, 0, "Failed to register EEPROM %s", label_1);
	}

	/* The simulated EP0 is configured to be accessed as a target device
	 * at addr_0 on i2c_0 and should expose eeprom_0_data.  The validation
	 * uses i2c_1 as a bus master to access this device, which works because
	 * i2c_0 and i2_c have their SDA (SCL) pins shorted (they are on the
	 * same physical bus).  Thus in these calls i2c_1 is a master device
	 * operating on the target address addr_0.
	 *
	 * Similarly validation of EP1 uses i2c_0 as a master with addr_1 and
	 * eeprom_1_data for validation.
	 */
	ret = run_full_read(i2c_1, addr_0, eeprom_0_data);
	zassert_equal(ret, 0,
		     "Full I2C read from EP0 failed");
	if (IS_ENABLED(CONFIG_APP_DUAL_ROLE_I2C)) {
		ret = run_full_read(i2c_0, addr_1, eeprom_1_data);
		zassert_equal(ret, 0,
			      "Full I2C read from EP1 failed");
	}

	for (offset = 0 ; offset < TEST_DATA_SIZE-1 ; ++offset) {
		zassert_equal(0, run_partial_read(i2c_1, addr_0,
			      eeprom_0_data, offset),
			      "Partial I2C read EP0 failed");
		if (IS_ENABLED(CONFIG_APP_DUAL_ROLE_I2C)) {
			zassert_equal(0, run_partial_read(i2c_0, addr_1,
							  eeprom_1_data,
							  offset),
				      "Partial I2C read EP1 failed");
		}
	}

	for (offset = 0 ; offset < TEST_DATA_SIZE-1 ; ++offset) {
		zassert_equal(0, run_program_read(i2c_1, addr_0, offset),
			      "Program I2C read EP0 failed");
		if (IS_ENABLED(CONFIG_APP_DUAL_ROLE_I2C)) {
			zassert_equal(0, run_program_read(i2c_0, addr_1,
							  offset),
				      "Program I2C read EP1 failed");
		}
	}

	/* Detach EEPROM */
	ret = i2c_target_driver_unregister(eeprom_0);
	zassert_equal(ret, 0, "Failed to unregister EEPROM %s", label_0);

	if (IS_ENABLED(CONFIG_APP_DUAL_ROLE_I2C)) {
		ret = i2c_target_driver_unregister(eeprom_1);
		zassert_equal(ret, 0, "Failed to unregister EEPROM %s",
			      label_1);
	}
}

void test_main(void)
{
	ztest_test_suite(test_eeprom_target, ztest_unit_test(test_eeprom_target));
	ztest_run_test_suite(test_eeprom_target);
}
