/*
 * Copyright (c) 2022 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/usb/udc.h>
#include <zephyr/usb/usbd.h>

#include "usbd_device.h"
#include "usbd_config.h"
#include "usbd_interface.h"
#include "usbd_ch9.h"
#include "usbd_class_api.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(usbd_cfg, CONFIG_USBD_LOG_LEVEL);

static sys_slist_t *usbd_configs(struct usbd_contex *uds_ctx,
				 const enum usbd_speed speed)
{
	switch (speed) {
	case USBD_SPEED_FS:
		return &uds_ctx->fs_configs;
	case USBD_SPEED_HS:
		return &uds_ctx->hs_configs;
	default:
		return NULL;
	}
}

struct usbd_config_node *usbd_config_get(struct usbd_contex *const uds_ctx,
					 const enum usbd_speed speed,
					 const uint8_t cfg)
{
	struct usbd_config_node *cfg_nd;

	SYS_SLIST_FOR_EACH_CONTAINER(usbd_configs(uds_ctx, speed), cfg_nd, node) {
		if (usbd_config_get_value(cfg_nd) == cfg) {
			return cfg_nd;
		}
	}

	return NULL;
}

struct usbd_config_node *
usbd_config_get_current(struct usbd_contex *const uds_ctx)
{
	if (!usbd_state_is_configured(uds_ctx)) {
		LOG_INF("No configuration set (Address state?)");
		return NULL;
	}

	return usbd_config_get(uds_ctx, usbd_bus_speed(uds_ctx),
			       usbd_get_config_value(uds_ctx));
}

static void usbd_config_classes_enable(struct usbd_config_node *const cfg_nd,
				       const bool enable)
{
	struct usbd_class_iter *iter;

	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
		if (enable) {
			usbd_class_enable(iter->c_nd);
		} else {
			usbd_class_disable(iter->c_nd);
		}
	}
}

/* Reset configuration to addressed state, shutdown all endpoints */
static int usbd_config_reset(struct usbd_contex *const uds_ctx)
{
	struct usbd_config_node *cfg_nd;
	int ret = 0;

	cfg_nd = usbd_config_get_current(uds_ctx);
	if (cfg_nd == NULL) {
		return -ENODATA;
	}

	ret = usbd_interface_shutdown(uds_ctx, cfg_nd);

	memset(&uds_ctx->ch9_data.alternate, 0,
	       USBD_NUMOF_INTERFACES_MAX);

	usbd_set_config_value(uds_ctx, 0);
	usbd_config_classes_enable(cfg_nd, false);

	return ret;
}

bool usbd_config_exist(struct usbd_contex *const uds_ctx,
		       const enum usbd_speed speed,
		       const uint8_t cfg)
{
	struct usbd_config_node *config;

	config = usbd_config_get(uds_ctx, speed, cfg);

	return (config != NULL) ? true : false;
}

int usbd_config_set(struct usbd_contex *const uds_ctx,
		    const uint8_t new_cfg)
{
	struct usbd_config_node *cfg_nd;
	const enum usbd_speed speed = usbd_bus_speed(uds_ctx);
	int ret;

	if (usbd_get_config_value(uds_ctx) != 0) {
		ret = usbd_config_reset(uds_ctx);
		if (ret) {
			LOG_ERR("Failed to reset configuration");
			return ret;
		}
	}

	if (new_cfg == 0) {
		usbd_set_config_value(uds_ctx, new_cfg);
		return 0;
	}

	cfg_nd = usbd_config_get(uds_ctx, speed, new_cfg);
	if (cfg_nd == NULL) {
		return -ENODATA;
	}

	ret = usbd_interface_default(uds_ctx, speed, cfg_nd);
	if (ret) {
		return ret;
	}

	usbd_set_config_value(uds_ctx, new_cfg);
	usbd_config_classes_enable(cfg_nd, true);

	return 0;
}

/*
 * All the functions below are part of public USB device support API.
 */

int usbd_config_attrib_rwup(struct usbd_contex *const uds_ctx,
			    const enum usbd_speed speed,
			    const uint8_t cfg, const bool enable)
{
	struct usbd_config_node *cfg_nd;
	struct usb_cfg_descriptor *desc;
	struct udc_device_caps caps;
	int ret = 0;

	usbd_device_lock(uds_ctx);

	if (usbd_is_enabled(uds_ctx)) {
		ret = -EALREADY;
		goto attrib_rwup_exit;
	}

	caps = udc_caps(uds_ctx->dev);
	if (!caps.rwup) {
		LOG_ERR("Feature not supported by controller");
		ret = -ENOTSUP;
		goto attrib_rwup_exit;
	}

	cfg_nd = usbd_config_get(uds_ctx, speed, cfg);
	if (cfg_nd == NULL) {
		LOG_INF("Configuration %u not found", cfg);
		ret = -ENODATA;
		goto attrib_rwup_exit;
	}

	desc = cfg_nd->desc;
	if (enable) {
		desc->bmAttributes |= USB_SCD_REMOTE_WAKEUP;
	} else {
		desc->bmAttributes &= ~USB_SCD_REMOTE_WAKEUP;
	}

attrib_rwup_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_config_attrib_self(struct usbd_contex *const uds_ctx,
			    const enum usbd_speed speed,
			    const uint8_t cfg, const bool enable)
{
	struct usbd_config_node *cfg_nd;
	struct usb_cfg_descriptor *desc;
	int ret = 0;

	usbd_device_lock(uds_ctx);

	if (usbd_is_enabled(uds_ctx)) {
		ret = -EALREADY;
		goto attrib_self_exit;
	}

	cfg_nd = usbd_config_get(uds_ctx, speed, cfg);
	if (cfg_nd == NULL) {
		LOG_INF("Configuration %u not found", cfg);
		ret = -ENODATA;
		goto attrib_self_exit;
	}

	desc = cfg_nd->desc;
	if (enable) {
		desc->bmAttributes |= USB_SCD_SELF_POWERED;
	} else {
		desc->bmAttributes &= ~USB_SCD_SELF_POWERED;
	}

attrib_self_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_config_maxpower(struct usbd_contex *const uds_ctx,
			 const enum usbd_speed speed,
			 const uint8_t cfg, const uint8_t power)
{
	struct usbd_config_node *cfg_nd;
	struct usb_cfg_descriptor *desc;
	int ret = 0;

	usbd_device_lock(uds_ctx);

	if (usbd_is_enabled(uds_ctx)) {
		ret = -EALREADY;
		goto maxpower_exit;
	}

	cfg_nd = usbd_config_get(uds_ctx, speed, cfg);
	if (cfg_nd == NULL) {
		LOG_INF("Configuration %u not found", cfg);
		ret = -ENODATA;
		goto maxpower_exit;
	}

	desc = cfg_nd->desc;
	desc->bMaxPower = power;

maxpower_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_add_configuration(struct usbd_contex *const uds_ctx,
			   const enum usbd_speed speed,
			   struct usbd_config_node *const cfg_nd)
{
	struct usb_cfg_descriptor *desc = cfg_nd->desc;
	sys_slist_t *configs;
	sys_snode_t *node;
	int ret = 0;

	usbd_device_lock(uds_ctx);

	if (usbd_is_initialized(uds_ctx)) {
		LOG_ERR("USB device support is initialized");
		ret = -EBUSY;
		goto add_configuration_exit;
	}

	if (speed == USBD_SPEED_HS &&
	    usbd_caps_speed(uds_ctx) == USBD_SPEED_FS) {
		LOG_ERR("Controller doesn't support HS");
		ret = -ENOTSUP;
		goto add_configuration_exit;
	}

	if (desc->bmAttributes & USB_SCD_REMOTE_WAKEUP) {
		struct udc_device_caps caps = udc_caps(uds_ctx->dev);

		if (!caps.rwup) {
			LOG_ERR("Feature not supported by controller");
			ret = -ENOTSUP;
			goto add_configuration_exit;
		}
	}

	configs = usbd_configs(uds_ctx, speed);
	switch (speed) {
	case USBD_SPEED_HS:
		SYS_SLIST_FOR_EACH_NODE(&uds_ctx->fs_configs, node) {
			if (node == &cfg_nd->node) {
				LOG_ERR("HS config already on FS list");
				ret = -EINVAL;
				goto add_configuration_exit;
			}
		}
		break;
	case USBD_SPEED_FS:
		SYS_SLIST_FOR_EACH_NODE(&uds_ctx->hs_configs, node) {
			if (node == &cfg_nd->node) {
				LOG_ERR("FS config already on HS list");
				ret = -EINVAL;
				goto add_configuration_exit;
			}
		}
		break;
	default:
		LOG_ERR("Unsupported configuration speed");
		ret = -ENOTSUP;
		goto add_configuration_exit;
	}

	if (sys_slist_find_and_remove(configs, &cfg_nd->node)) {
		LOG_WRN("Configuration %u re-inserted",
			usbd_config_get_value(cfg_nd));
	} else {
		uint8_t num = usbd_get_num_configs(uds_ctx, speed) + 1;

		usbd_config_set_value(cfg_nd, num);
		usbd_set_num_configs(uds_ctx, speed, num);
	}

	sys_slist_append(configs, &cfg_nd->node);

	usbd_device_unlock(uds_ctx);

add_configuration_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}
