/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#include "test_gpio.h"

static struct drv_data cb_data[2];
static int cb_cnt[2];

static void callback_1(const struct device *dev,
		       struct gpio_callback *gpio_cb, uint32_t pins)
{
	TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[0]);

}

static void callback_2(const struct device *dev,
		       struct gpio_callback *gpio_cb, uint32_t pins)
{
	TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[1]);
}

static void callback_remove_self(const struct device *dev,
				 struct gpio_callback *gpio_cb, uint32_t pins)
{
	struct drv_data *dd = CONTAINER_OF(gpio_cb, struct drv_data, gpio_cb);

	TC_PRINT("%s triggered: %d\n", __func__, ++cb_cnt[1]);
	dd->aux = gpio_remove_callback(dev, gpio_cb);
}

static int init_callback(const struct device *dev,
			 gpio_callback_handler_t handler_1,
			 gpio_callback_handler_t handler_2)
{
	int rc = gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE);

	if (rc == 0) {
		rc = gpio_pin_interrupt_configure(dev, PIN_OUT, GPIO_INT_DISABLE);
	}
	if (rc == 0) {
		/* 1. set PIN_OUT */
		rc = gpio_pin_configure(dev, PIN_OUT, (GPIO_OUTPUT_LOW | PIN_OUT_FLAGS));
	}

	if (rc == 0) {
		/* 2. configure PIN_IN callback, but don't enable */
		rc = gpio_pin_configure(dev, PIN_IN, (GPIO_INPUT | PIN_IN_FLAGS));
	}

	if (rc == 0) {
		gpio_init_callback(&cb_data[0].gpio_cb, handler_1, BIT(PIN_IN));
		rc = gpio_add_callback(dev, &cb_data[0].gpio_cb);
	}

	if (rc == 0) {
		gpio_init_callback(&cb_data[1].gpio_cb, handler_2, BIT(PIN_IN));
		rc = gpio_add_callback(dev, &cb_data[1].gpio_cb);
	}

	return rc;
}

static void trigger_callback(const struct device *dev, int enable_cb)
{
	gpio_pin_set(dev, PIN_OUT, 0);
	k_sleep(K_MSEC(100));

	cb_cnt[0] = 0;
	cb_cnt[1] = 0;
	if (enable_cb == 1) {
		gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_EDGE_RISING);
	} else {
		gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE);
	}
	k_sleep(K_MSEC(100));
	gpio_pin_set(dev, PIN_OUT, 1);
	k_sleep(K_MSEC(1000));
}

static int test_callback_add_remove(void)
{
	const struct device *const dev = DEVICE_DT_GET(DEV);

	/* SetUp: initialize environment */
	int rc = init_callback(dev, callback_1, callback_2);

	if (rc == -ENOTSUP) {
		TC_PRINT("%s not supported\n", __func__);
		return TC_PASS;
	}
	zassert_equal(rc, 0,
		      "init_callback failed");

	/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
	trigger_callback(dev, 1);
	/*= checkpoint: check callback is triggered =*/
	if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
		TC_ERROR("not trigger callback correctly\n");
		goto err_exit;
	}

	/* 4. remove callback_1 */
	gpio_remove_callback(dev, &cb_data[0].gpio_cb);
	trigger_callback(dev, 1);

	/*= checkpoint: check callback is triggered =*/
	if (cb_cnt[0] != 0 || cb_cnt[1] != 1) {
		TC_ERROR("not trigger callback correctly\n");
		goto err_exit;
	}

	/* 5. remove callback_2 */
	gpio_remove_callback(dev, &cb_data[1].gpio_cb);
	trigger_callback(dev, 1);
	/*= checkpoint: check callback is triggered =*/
	if (cb_cnt[0] != 0 || cb_cnt[1] != 0) {
		TC_ERROR("not trigger callback correctly\n");
		goto err_exit;
	}
	return TC_PASS;

err_exit:
	gpio_remove_callback(dev, &cb_data[0].gpio_cb);
	gpio_remove_callback(dev, &cb_data[1].gpio_cb);
	return TC_FAIL;
}

static int test_callback_self_remove(void)
{
	int res = TC_FAIL;
	const struct device *const dev = DEVICE_DT_GET(DEV);

	/* SetUp: initialize environment */
	int rc = init_callback(dev, callback_1, callback_remove_self);

	if (rc == -ENOTSUP) {
		TC_PRINT("%s not supported\n", __func__);
		return TC_PASS;
	}
	zassert_equal(rc, 0,
		      "init_callback failed");

	gpio_pin_set(dev, PIN_OUT, 0);
	k_sleep(K_MSEC(100));

	cb_data[0].aux = INT_MAX;
	cb_data[1].aux = INT_MAX;

	/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
	trigger_callback(dev, 1);

	/*= checkpoint: check both callbacks are triggered =*/
	if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
		TC_ERROR("not trigger callback correctly\n");
		goto err_exit;
	}

	/*= checkpoint: check remove executed is invoked =*/
	if (cb_data[0].aux != INT_MAX || cb_data[1].aux != 0) {
		TC_ERROR("not remove callback correctly\n");
		goto err_exit;
	}

	/* 4 enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
	trigger_callback(dev, 1);

	/*= checkpoint: check only remaining callback is triggered =*/
	if (cb_cnt[0] != 1 || cb_cnt[1] != 0) {
		TC_ERROR("not trigger remaining callback correctly\n");
		goto err_exit;
	}

	res = TC_PASS;

err_exit:
	gpio_remove_callback(dev, &cb_data[0].gpio_cb);
	gpio_remove_callback(dev, &cb_data[1].gpio_cb);
	return res;
}

static int test_callback_enable_disable(void)
{
	const struct device *const dev = DEVICE_DT_GET(DEV);

	/* SetUp: initialize environment */
	int rc = init_callback(dev, callback_1, callback_2);

	if (rc == -ENOTSUP) {
		TC_PRINT("%s not supported\n", __func__);
		return TC_PASS;
	}
	zassert_equal(rc, 0,
		      "init_callback failed");

	/* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */
	trigger_callback(dev, 1);
	/*= checkpoint: check callback is triggered =*/
	if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
		TC_ERROR("not trigger callback correctly\n");
		goto err_exit;
	}

	/* 4. disable callback */
	trigger_callback(dev, 0);
	/*= checkpoint: check callback is triggered =*/
	if (cb_cnt[0] != 0 || cb_cnt[1] != 0) {
		TC_ERROR("not trigger callback correctly\n");
		goto err_exit;
	}

	/* 5. enable callback again */
	trigger_callback(dev, 1);
	/*= checkpoint: check callback is triggered =*/
	if (cb_cnt[0] != 1 || cb_cnt[1] != 1) {
		TC_ERROR("not trigger callback correctly\n");
		goto err_exit;
	}
	gpio_remove_callback(dev, &cb_data[0].gpio_cb);
	gpio_remove_callback(dev, &cb_data[1].gpio_cb);
	return TC_PASS;

err_exit:
	gpio_remove_callback(dev, &cb_data[0].gpio_cb);
	gpio_remove_callback(dev, &cb_data[1].gpio_cb);
	return TC_FAIL;
}

ZTEST(gpio_port_cb_mgmt, test_gpio_callback_add_remove)
{
	zassert_equal(test_callback_add_remove(), TC_PASS,
		     NULL);
}

ZTEST(gpio_port_cb_mgmt, test_gpio_callback_self_remove)
{
	zassert_equal(test_callback_self_remove(), TC_PASS,
		     NULL);
}

ZTEST(gpio_port_cb_mgmt, test_gpio_callback_enable_disable)
{
	zassert_equal(test_callback_enable_disable(), TC_PASS,
		     NULL);
}
