/*
 * 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_class.h"
#include "usbd_ch9.h"
#include "usbd_desc.h"

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

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

int usbd_device_set_bcd(struct usbd_contex *const uds_ctx,
			const uint16_t bcd)
{
	struct usb_device_descriptor *desc = uds_ctx->desc;
	int ret = 0;

	usbd_device_lock(uds_ctx);

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

	desc->bcdUSB = sys_cpu_to_le16(bcd);

set_bcd_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_device_set_vid(struct usbd_contex *const uds_ctx,
			 const uint16_t vid)
{
	struct usb_device_descriptor *desc = uds_ctx->desc;
	int ret = 0;

	usbd_device_lock(uds_ctx);

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

	desc->idVendor = sys_cpu_to_le16(vid);

set_vid_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_device_set_pid(struct usbd_contex *const uds_ctx,
			 const uint16_t pid)
{
	struct usb_device_descriptor *desc = uds_ctx->desc;
	int ret = 0;

	usbd_device_lock(uds_ctx);

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

	desc->idProduct = sys_cpu_to_le16(pid);

set_pid_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx,
				const uint8_t base_class,
				const uint8_t subclass, const uint8_t protocol)
{
	struct usb_device_descriptor *desc = uds_ctx->desc;
	int ret = 0;

	usbd_device_lock(uds_ctx);

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

	desc->bDeviceClass = base_class;
	desc->bDeviceSubClass = subclass;
	desc->bDeviceProtocol = protocol;

set_code_triple_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_wakeup_request(struct usbd_contex *const uds_ctx)
{
	struct udc_device_caps caps = udc_caps(uds_ctx->dev);
	int ret = 0;

	usbd_device_lock(uds_ctx);

	if (!caps.rwup) {
		LOG_ERR("Remote wakeup feature not supported");
		ret = -ENOTSUP;
		goto wakeup_request_error;
	}

	if (!uds_ctx->status.rwup || !usbd_is_suspended(uds_ctx)) {
		LOG_ERR("Remote wakeup feature not enabled or not suspended");
		ret = -EACCES;
		goto wakeup_request_error;
	}

	ret = udc_host_wakeup(uds_ctx->dev);

wakeup_request_error:
	usbd_device_unlock(uds_ctx);

	return ret;
}

bool usbd_is_suspended(struct usbd_contex *uds_ctx)
{
	return uds_ctx->status.suspended;
}

int usbd_init(struct usbd_contex *const uds_ctx)
{
	int ret;

	usbd_device_lock(uds_ctx);

	if (uds_ctx->dev == NULL) {
		ret = -ENODEV;
		goto init_exit;
	}

	if (usbd_is_initialized(uds_ctx)) {
		LOG_WRN("USB device support is already initialized");
		ret = -EALREADY;
		goto init_exit;
	}

	if (!device_is_ready(uds_ctx->dev)) {
		LOG_ERR("USB device controller is not ready");
		ret = -ENODEV;
		goto init_exit;
	}

	ret = usbd_device_init_core(uds_ctx);
	if (ret) {
		goto init_exit;
	}

	memset(&uds_ctx->ch9_data, 0, sizeof(struct usbd_ch9_data));
	uds_ctx->status.initialized = true;

init_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_enable(struct usbd_contex *const uds_ctx)
{
	int ret;

	usbd_device_lock(uds_ctx);

	if (!usbd_is_initialized(uds_ctx)) {
		LOG_WRN("USB device support is not initialized");
		ret = -EPERM;
		goto enable_exit;
	}

	if (usbd_is_enabled(uds_ctx)) {
		LOG_WRN("USB device support is already enabled");
		ret = -EALREADY;
		goto enable_exit;
	}

	ret = udc_enable(uds_ctx->dev);
	if (ret != 0) {
		LOG_ERR("Failed to enable controller");
		goto enable_exit;
	}

	ret = usbd_init_control_pipe(uds_ctx);
	if (ret != 0) {
		udc_disable(uds_ctx->dev);
		goto enable_exit;
	}

	uds_ctx->status.enabled = true;

enable_exit:
	usbd_device_unlock(uds_ctx);
	return ret;
}

int usbd_disable(struct usbd_contex *const uds_ctx)
{
	int ret;

	if (!usbd_is_enabled(uds_ctx)) {
		LOG_WRN("USB device support is already disabled");
		return -EALREADY;
	}

	usbd_device_lock(uds_ctx);

	ret = usbd_config_set(uds_ctx, 0);
	if (ret) {
		LOG_ERR("Failed to reset configuration");
	}

	ret = udc_disable(uds_ctx->dev);
	if (ret) {
		LOG_ERR("Failed to disable USB device");
	}

	uds_ctx->status.enabled = false;

	usbd_device_unlock(uds_ctx);

	return ret;
}

int usbd_shutdown(struct usbd_contex *const uds_ctx)
{
	int ret;

	usbd_device_lock(uds_ctx);

	/* TODO: control request dequeue ? */
	ret = usbd_device_shutdown_core(uds_ctx);
	if (ret) {
		LOG_ERR("Failed to shutdown USB device");
	}

	uds_ctx->status.initialized = false;
	usbd_device_unlock(uds_ctx);

	return 0;
}
