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

#include <zephyr/usb/usbd.h>
#include <zephyr/toolchain/common.h>
#include <zephyr/drivers/usb/udc.h>
#include <zephyr/sys/slist.h>

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

#include <zephyr/logging/log.h>
#if IS_ENABLED(CONFIG_USBD_LOG_LEVEL)
#define USBD_CLASS_LOG_LEVEL CONFIG_USBD_LOG_LEVEL
#else
#define USBD_CLASS_LOG_LEVEL LOG_LEVEL_NONE
#endif
LOG_MODULE_REGISTER(usbd_class, CONFIG_USBD_LOG_LEVEL);

size_t usbd_class_desc_len(struct usbd_class_node *const c_nd)
{
	struct usbd_class_data *data = c_nd->data;
	struct usb_desc_header *dh;
	uint8_t *ptr;
	size_t len = 0;

	if (data->desc != NULL) {
		dh = data->desc;
		ptr = (uint8_t *)dh;

		while (dh->bLength != 0) {
			len += dh->bLength;
			ptr += dh->bLength;
			dh = (struct usb_desc_header *)ptr;
		}
	}

	return len;
}

struct usbd_class_node *
usbd_class_get_by_config(struct usbd_contex *const uds_ctx,
			 const uint8_t cnum,
			 const uint8_t inum)
{
	struct usbd_class_node *c_nd;
	struct usbd_config_node *cfg_nd;

	cfg_nd = usbd_config_get(uds_ctx, cnum);
	if (cfg_nd == NULL) {
		return NULL;
	}

	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
		if (c_nd->data->iface_bm & BIT(inum)) {
			return c_nd;
		}
	}

	return NULL;
}

struct usbd_class_node *
usbd_class_get_by_iface(struct usbd_contex *const uds_ctx,
			const uint8_t inum)
{
	struct usbd_class_node *c_nd;
	struct usbd_config_node *cfg_nd;

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

	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
		if (c_nd->data->iface_bm & BIT(inum)) {
			return c_nd;
		}
	}

	return NULL;
}

static bool xfer_owner_exist(struct usbd_contex *const uds_ctx,
			     struct usbd_config_node *const cfg_nd,
			     struct net_buf *const buf)
{
	struct udc_buf_info *bi = udc_get_buf_info(buf);
	struct usbd_class_node *c_nd;

	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
		if (bi->owner == c_nd) {
			uint32_t ep_active = c_nd->data->ep_active;
			uint32_t ep_assigned = c_nd->data->ep_assigned;

			if (!usbd_ep_bm_is_set(&ep_active, bi->ep)) {
				LOG_DBG("ep 0x%02x is not active", bi->ep);
			}

			if (!usbd_ep_bm_is_set(&ep_assigned, bi->ep)) {
				LOG_DBG("ep 0x%02x is not assigned", bi->ep);
			}

			return true;
		}
	}

	return false;
}

int usbd_class_handle_xfer(struct usbd_contex *const uds_ctx,
			   struct net_buf *const buf,
			   const int err)
{
	struct udc_buf_info *bi = udc_get_buf_info(buf);

	if (unlikely(USBD_CLASS_LOG_LEVEL == LOG_LEVEL_DBG)) {
		struct usbd_config_node *cfg_nd;

		if (usbd_state_is_configured(uds_ctx)) {
			cfg_nd = usbd_config_get_current(uds_ctx);
			if (xfer_owner_exist(uds_ctx, cfg_nd, buf)) {
				return usbd_class_request(bi->owner, buf, err);
			}
		}

		SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->configs, cfg_nd, node) {
			if (xfer_owner_exist(uds_ctx, cfg_nd, buf)) {
				return usbd_class_request(bi->owner, buf, err);
			}
		}

		return -ENODATA;
	}

	return usbd_class_request(bi->owner, buf, err);
}

struct usbd_class_node *
usbd_class_get_by_ep(struct usbd_contex *const uds_ctx,
		     const uint8_t ep)
{
	struct usbd_class_node *c_nd;
	struct usbd_config_node *cfg_nd;
	uint8_t ep_idx = USB_EP_GET_IDX(ep);
	uint8_t cfg;
	uint32_t ep_bm;

	if (USB_EP_DIR_IS_IN(ep)) {
		ep_bm = BIT(ep_idx + 16);
	} else {
		ep_bm = BIT(ep_idx);
	}

	if (!usbd_state_is_configured(uds_ctx)) {
		LOG_ERR("No configuration set (Address state)");
		return NULL;
	}

	cfg = usbd_get_config_value(uds_ctx);
	cfg_nd = usbd_config_get(uds_ctx, cfg);
	if (cfg_nd == NULL) {
		return NULL;
	}

	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
		if (c_nd->data->ep_assigned & ep_bm) {
			return c_nd;
		}
	}

	return NULL;
}

struct usbd_class_node *
usbd_class_get_by_req(struct usbd_contex *const uds_ctx,
		      const uint8_t request)
{
	struct usbd_config_node *cfg_nd;
	struct usbd_class_node *c_nd;

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

	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
		if (c_nd->data->v_reqs == NULL) {
			continue;
		}

		for (int i = 0; i < c_nd->data->v_reqs->len; i++) {
			/*
			 * First instance always wins.
			 * There is no other way to determine the recipient.
			 */
			if (c_nd->data->v_reqs->reqs[i] == request) {
				return c_nd;
			}
		}
	}

	return NULL;
}

static struct usbd_class_node *usbd_class_node_get(const char *name)
{
	STRUCT_SECTION_FOREACH(usbd_class_node, c_nd) {
		if (strcmp(name, c_nd->name) == 0) {
			return c_nd;
		}
	}

	LOG_ERR("USB device class %s not found", name);

	return NULL;
}

static int usbd_class_append(struct usbd_contex *const uds_ctx,
			     struct usbd_class_node *const c_nd,
			     const uint8_t cfg)
{
	struct usbd_config_node *cfg_nd;

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

	sys_slist_append(&cfg_nd->class_list, &c_nd->node);

	return 0;
}

static int usbd_class_remove(struct usbd_contex *const uds_ctx,
			     struct usbd_class_node *const c_nd,
			     const uint8_t cfg)
{
	struct usbd_config_node *cfg_nd;

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

	if (!sys_slist_find_and_remove(&cfg_nd->class_list, &c_nd->node)) {
		return -ENODATA;
	}

	return 0;
}

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

int usbd_register_class(struct usbd_contex *const uds_ctx,
			const char *name,
			const uint8_t cfg)
{
	struct usbd_class_node *c_nd;
	struct usbd_class_data *data;
	int ret;

	c_nd = usbd_class_node_get(name);
	if (c_nd == NULL) {
		return -ENODEV;
	}

	usbd_device_lock(uds_ctx);

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

	data = c_nd->data;
	if (data->desc == NULL) {
		ret = -EINVAL;
		goto register_class_error;
	}


	/* TODO: does it still need to be atomic ? */
	if (atomic_test_bit(&data->state, USBD_CCTX_REGISTERED)) {
		LOG_WRN("Class instance allready registered");
		ret = -EBUSY;
		goto register_class_error;
	}

	ret = usbd_class_append(uds_ctx, c_nd, cfg);
	if (ret == 0) {
		/* Initialize pointer back to the device struct */
		atomic_set_bit(&data->state, USBD_CCTX_REGISTERED);
		data->uds_ctx = uds_ctx;
	}

register_class_error:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_unregister_class(struct usbd_contex *const uds_ctx,
			  const char *name,
			  const uint8_t cfg)
{
	struct usbd_class_node *c_nd;
	struct usbd_class_data *data;
	int ret;

	c_nd = usbd_class_node_get(name);
	if (c_nd == NULL) {
		return -ENODEV;
	}

	usbd_device_lock(uds_ctx);

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

	data = c_nd->data;
	/* TODO: does it still need to be atomic ? */
	if (!atomic_test_bit(&data->state, USBD_CCTX_REGISTERED)) {
		LOG_WRN("Class instance not registered");
		ret = -EBUSY;
		goto unregister_class_error;
	}

	ret = usbd_class_remove(uds_ctx, c_nd, cfg);
	if (ret == 0) {
		atomic_clear_bit(&data->state, USBD_CCTX_REGISTERED);
		data->uds_ctx = NULL;
	}

unregister_class_error:
	usbd_device_unlock(uds_ctx);
	return ret;
}
