/*
 * Copyright (c) 2018 Linaro
 * Copyright (c) 2019 PHYTEC Messtechnik GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <usb/usb_device.h>
#include <logging/log.h>

#include "usb_transfer.h"
#include "usb_work_q.h"

LOG_MODULE_REGISTER(usb_transfer, CONFIG_USB_DEVICE_LOG_LEVEL);

struct usb_transfer_sync_priv {
	int tsize;
	struct k_sem sem;
};

struct usb_transfer_data {
	/** endpoint associated to the transfer */
	uint8_t ep;
	/** Transfer status */
	int status;
	/** Transfer read/write buffer */
	uint8_t *buffer;
	/** Transfer buffer size */
	size_t bsize;
	/** Transferred size */
	size_t tsize;
	/** Transfer callback */
	usb_transfer_callback cb;
	/** Transfer caller private data */
	void *priv;
	/** Transfer synchronization semaphore */
	struct k_sem sem;
	/** Transfer read/write work */
	struct k_work work;
	/** Transfer flags */
	unsigned int flags;
};

/** Max number of parallel transfers */
static struct usb_transfer_data ut_data[CONFIG_USB_MAX_NUM_TRANSFERS];

/* Transfer management */
static struct usb_transfer_data *usb_ep_get_transfer(uint8_t ep)
{
	for (int i = 0; i < ARRAY_SIZE(ut_data); i++) {
		if (ut_data[i].ep == ep) {
			return &ut_data[i];
		}
	}

	return NULL;
}

bool usb_transfer_is_busy(uint8_t ep)
{
	struct usb_transfer_data *trans = usb_ep_get_transfer(ep);

	if (trans && trans->status == -EBUSY) {
		return true;
	}

	return false;
}

static void usb_transfer_work(struct k_work *item)
{
	struct usb_transfer_data *trans;
	int ret = 0;
	uint32_t bytes;
	uint8_t ep;

	trans = CONTAINER_OF(item, struct usb_transfer_data, work);
	ep = trans->ep;

	if (trans->status != -EBUSY) {
		/* transfer cancelled or already completed */
		LOG_DBG("Transfer cancelled or completed, ep 0x%02x", ep);
		goto done;
	}

	if (trans->flags & USB_TRANS_WRITE) {
		if (!trans->bsize) {
			if (!(trans->flags & USB_TRANS_NO_ZLP)) {
				LOG_DBG("Transfer ZLP");
				usb_write(ep, NULL, 0, NULL);
			}
			trans->status = 0;
			goto done;
		}

		ret = usb_write(ep, trans->buffer, trans->bsize, &bytes);
		if (ret) {
			LOG_ERR("Transfer error %d, ep 0x%02x", ret, ep);
			/* transfer error */
			trans->status = -EINVAL;
			goto done;
		}

		trans->buffer += bytes;
		trans->bsize -= bytes;
		trans->tsize += bytes;
	} else {
		ret = usb_dc_ep_read_wait(ep, trans->buffer, trans->bsize,
					  &bytes);
		if (ret) {
			LOG_ERR("Transfer error %d, ep 0x%02x", ret, ep);
			/* transfer error */
			trans->status = -EINVAL;
			goto done;
		}

		trans->buffer += bytes;
		trans->bsize -= bytes;
		trans->tsize += bytes;

		/* ZLP, short-pkt or buffer full */
		if (!bytes || (bytes % usb_dc_ep_mps(ep)) || !trans->bsize) {
			/* transfer complete */
			trans->status = 0;
			goto done;
		}

		/* we expect mote data, clear NAK */
		usb_dc_ep_read_continue(ep);
	}

done:
	if (trans->status != -EBUSY && trans->cb) { /* Transfer complete */
		usb_transfer_callback cb = trans->cb;
		int tsize = trans->tsize;
		void *priv = trans->priv;

		if (k_is_in_isr()) {
			/* reschedule completion in thread context */
			k_work_submit_to_queue(&USB_WORK_Q, &trans->work);
			return;
		}

		LOG_DBG("Transfer done, ep 0x%02x, status %d, size %zu",
			trans->ep, trans->status, trans->tsize);

		trans->cb = NULL;
		k_sem_give(&trans->sem);

		/* Transfer completion callback */
		if (trans->status != -ECANCELED) {
			cb(ep, tsize, priv);
		}
	}
}

void usb_transfer_ep_callback(uint8_t ep, enum usb_dc_ep_cb_status_code status)
{
	struct usb_transfer_data *trans = usb_ep_get_transfer(ep);

	if (status != USB_DC_EP_DATA_IN && status != USB_DC_EP_DATA_OUT) {
		return;
	}

	if (!trans) {
		if (status == USB_DC_EP_DATA_OUT) {
			uint32_t bytes;
			/* In the unlikely case we receive data while no
			 * transfer is ongoing, we have to consume the data
			 * anyway. This is to prevent stucking reception on
			 * other endpoints (e.g dw driver has only one rx-fifo,
			 * so drain it).
			 */
			do {
				uint8_t data;

				usb_dc_ep_read_wait(ep, &data, 1, &bytes);
			} while (bytes);

			LOG_ERR("RX data lost, no transfer");
		}
		return;
	}

	if (!k_is_in_isr() || (status == USB_DC_EP_DATA_OUT)) {
		/* If we are not in IRQ context, no need to defer work */
		/* Read (out) needs to be done from ep_callback */
		usb_transfer_work(&trans->work);
	} else {
		k_work_submit_to_queue(&USB_WORK_Q, &trans->work);
	}
}

int usb_transfer(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags,
		 usb_transfer_callback cb, void *cb_data)
{
	struct usb_transfer_data *trans = NULL;
	int i, key, ret = 0;

	LOG_DBG("Transfer start, ep 0x%02x, data %p, dlen %zd",
		ep, data, dlen);

	key = irq_lock();

	for (i = 0; i < ARRAY_SIZE(ut_data); i++) {
		if (!k_sem_take(&ut_data[i].sem, K_NO_WAIT)) {
			trans = &ut_data[i];
			break;
		}
	}

	if (!trans) {
		LOG_ERR("No transfer slot available");
		ret = -ENOMEM;
		goto done;
	}

	if (trans->status == -EBUSY) {
		/* A transfer is already ongoing and not completed */
		LOG_ERR("A transfer is already ongoing, ep 0x%02x", ep);
		k_sem_give(&trans->sem);
		ret = -EBUSY;
		goto done;
	}

	/* Configure new transfer */
	trans->ep = ep;
	trans->buffer = data;
	trans->bsize = dlen;
	trans->tsize = 0;
	trans->cb = cb;
	trans->flags = flags;
	trans->priv = cb_data;
	trans->status = -EBUSY;

	if (usb_dc_ep_mps(ep) && (dlen % usb_dc_ep_mps(ep))) {
		/* no need to send ZLP since last packet will be a short one */
		trans->flags |= USB_TRANS_NO_ZLP;
	}

	if (flags & USB_TRANS_WRITE) {
		/* start writing first chunk */
		k_work_submit_to_queue(&USB_WORK_Q, &trans->work);
	} else {
		/* ready to read, clear NAK */
		ret = usb_dc_ep_read_continue(ep);
	}

done:
	irq_unlock(key);
	return ret;
}

void usb_cancel_transfer(uint8_t ep)
{
	struct usb_transfer_data *trans;
	unsigned int key;

	key = irq_lock();

	trans = usb_ep_get_transfer(ep);
	if (!trans) {
		goto done;
	}

	if (trans->status != -EBUSY) {
		goto done;
	}

	trans->status = -ECANCELED;
	k_work_submit_to_queue(&USB_WORK_Q, &trans->work);

done:
	irq_unlock(key);
}

void usb_cancel_transfers(void)
{
	for (int i = 0; i < ARRAY_SIZE(ut_data); i++) {
		struct usb_transfer_data *trans = &ut_data[i];
		unsigned int key;

		key = irq_lock();

		if (trans->status == -EBUSY) {
			trans->status = -ECANCELED;
			k_work_submit_to_queue(&USB_WORK_Q, &trans->work);
			LOG_DBG("Cancel transfer for ep: 0x%02x", trans->ep);
		}

		irq_unlock(key);
	}
}

static void usb_transfer_sync_cb(uint8_t ep, int size, void *priv)
{
	struct usb_transfer_sync_priv *pdata = priv;

	pdata->tsize = size;
	k_sem_give(&pdata->sem);
}

int usb_transfer_sync(uint8_t ep, uint8_t *data, size_t dlen, unsigned int flags)
{
	struct usb_transfer_sync_priv pdata;
	int ret;

	k_sem_init(&pdata.sem, 0, 1);

	ret = usb_transfer(ep, data, dlen, flags, usb_transfer_sync_cb, &pdata);
	if (ret) {
		return ret;
	}

	/* Semaphore will be released by the transfer completion callback */
	k_sem_take(&pdata.sem, K_FOREVER);

	return pdata.tsize;
}

/* Init transfer slots */
int usb_transfer_init(void)
{
	for (int i = 0; i < ARRAY_SIZE(ut_data); i++) {
		k_work_init(&ut_data[i].work, usb_transfer_work);
		k_sem_init(&ut_data[i].sem, 1, 1);
	}

	return 0;
}
