/*
 * Wireless / Bluetooth USB class
 *
 * Copyright (c) 2020 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/init.h>
#include <zephyr/sys/byteorder.h>

#include <zephyr/usb/usb_device.h>
#include <usb_descriptor.h>

#include <zephyr/net/buf.h>

#include <zephyr/bluetooth/buf.h>
#include <zephyr/bluetooth/hci_raw.h>
#include <zephyr/bluetooth/l2cap.h>

#define LOG_LEVEL CONFIG_USB_DEVICE_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(usb_bt_h4);

static K_FIFO_DEFINE(rx_queue);
static K_FIFO_DEFINE(tx_queue);

#define BT_H4_OUT_EP_ADDR               0x01
#define BT_H4_IN_EP_ADDR                0x81

#define BT_H4_OUT_EP_IDX                0
#define BT_H4_IN_EP_IDX                 1

/* HCI RX/TX threads */
static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_RX_STACK_SIZE);
static struct k_thread rx_thread_data;
static K_KERNEL_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE);
static struct k_thread tx_thread_data;

/* HCI USB state flags */
static bool configured;
static bool suspended;

struct usb_bt_h4_config {
	struct usb_if_descriptor if0;
	struct usb_ep_descriptor if0_out_ep;
	struct usb_ep_descriptor if0_in_ep;
} __packed;

USBD_CLASS_DESCR_DEFINE(primary, 0) struct usb_bt_h4_config bt_h4_cfg = {
	/* Interface descriptor 0 */
	.if0 = {
		.bLength = sizeof(struct usb_if_descriptor),
		.bDescriptorType = USB_DESC_INTERFACE,
		.bInterfaceNumber = 0,
		.bAlternateSetting = 0,
		.bNumEndpoints = 2,
		.bInterfaceClass = USB_BCC_VENDOR, /* TBD */
		.bInterfaceSubClass = 0,
		.bInterfaceProtocol = 0,
		.iInterface = 0,
	},

	/* Data Endpoint OUT */
	.if0_out_ep = {
		.bLength = sizeof(struct usb_ep_descriptor),
		.bDescriptorType = USB_DESC_ENDPOINT,
		.bEndpointAddress = BT_H4_OUT_EP_ADDR,
		.bmAttributes = USB_DC_EP_BULK,
		.wMaxPacketSize = sys_cpu_to_le16(USB_MAX_FS_BULK_MPS),
		.bInterval = 0x01,
	},

	/* Data Endpoint IN */
	.if0_in_ep = {
		.bLength = sizeof(struct usb_ep_descriptor),
		.bDescriptorType = USB_DESC_ENDPOINT,
		.bEndpointAddress = BT_H4_IN_EP_ADDR,
		.bmAttributes = USB_DC_EP_BULK,
		.wMaxPacketSize = sys_cpu_to_le16(USB_MAX_FS_BULK_MPS),
		.bInterval = 0x01,
	},
};

static struct usb_ep_cfg_data bt_h4_ep_data[] = {
	{
		.ep_cb = usb_transfer_ep_callback,
		.ep_addr = BT_H4_OUT_EP_ADDR,
	},
	{
		.ep_cb = usb_transfer_ep_callback,
		.ep_addr = BT_H4_IN_EP_ADDR,
	},
};

static void bt_h4_read(uint8_t ep, int size, void *priv)
{
	static uint8_t data[USB_MAX_FS_BULK_MPS];

	if (size > 0) {
		struct net_buf *buf;

		buf = bt_buf_get_tx(BT_BUF_H4, K_FOREVER, data, size);
		if (!buf) {
			LOG_ERR("Cannot get free TX buffer\n");
			return;
		}

		net_buf_put(&rx_queue, buf);
	}

	/* Start a new read transfer */
	usb_transfer(bt_h4_ep_data[BT_H4_OUT_EP_IDX].ep_addr, data,
		     USB_MAX_FS_BULK_MPS, USB_TRANS_READ, bt_h4_read, NULL);
}

static void hci_tx_thread(void)
{
	LOG_DBG("Start USB Bluetooth thread");

	while (true) {
		struct net_buf *buf;

		buf = net_buf_get(&tx_queue, K_FOREVER);

		usb_transfer_sync(bt_h4_ep_data[BT_H4_IN_EP_IDX].ep_addr,
				  buf->data, buf->len, USB_TRANS_WRITE);

		net_buf_unref(buf);
	}
}

static void hci_rx_thread(void)
{
	while (true) {
		struct net_buf *buf;

		buf = net_buf_get(&rx_queue, K_FOREVER);
		if (bt_send(buf)) {
			LOG_ERR("Error sending to driver");
			net_buf_unref(buf);
		}
	}
}

static void bt_h4_status_cb(struct usb_cfg_data *cfg,
			    enum usb_dc_status_code status, const uint8_t *param)
{
	ARG_UNUSED(cfg);

	/* Check the USB status and do needed action if required */
	switch (status) {
	case USB_DC_RESET:
		LOG_DBG("Device reset detected");
		suspended = false;
		configured = false;
		break;
	case USB_DC_CONFIGURED:
		LOG_DBG("Device configured");
		if (!configured) {
			configured = true;
			/* Start reading */
			bt_h4_read(bt_h4_ep_data[BT_H4_OUT_EP_IDX].ep_addr,
				   0, NULL);
		}
		break;
	case USB_DC_DISCONNECTED:
		LOG_DBG("Device disconnected");
		/* Cancel any transfer */
		usb_cancel_transfer(bt_h4_ep_data[BT_H4_IN_EP_IDX].ep_addr);
		usb_cancel_transfer(bt_h4_ep_data[BT_H4_OUT_EP_IDX].ep_addr);
		suspended = false;
		configured = false;
		break;
	case USB_DC_SUSPEND:
		suspended = true;
		break;
	case USB_DC_RESUME:
		LOG_DBG("Device resumed");
		if (suspended) {
			LOG_DBG("from suspend");
			suspended = false;
			if (configured) {
				/* Start reading */
				bt_h4_read(bt_h4_ep_data[BT_H4_OUT_EP_IDX].ep_addr,
					   0, NULL);
			}
		} else {
			LOG_DBG("Spurious resume event");
		}
		break;
	case USB_DC_UNKNOWN:
	default:
		LOG_DBG("Unhandled status: %u", status);
		break;
	}
}

static int bt_h4_vendor_handler(struct usb_setup_packet *setup,
				int32_t *len, uint8_t **data)
{
	LOG_DBG("Class request: bRequest 0x%x bmRequestType 0x%x len %d",
		setup->bRequest, setup->bmRequestType, *len);

	return -ENOTSUP;
}

static void bt_h4_interface_config(struct usb_desc_header *head,
				   uint8_t bInterfaceNumber)
{
	ARG_UNUSED(head);

	bt_h4_cfg.if0.bInterfaceNumber = bInterfaceNumber;
}

USBD_DEFINE_CFG_DATA(bt_h4_config) = {
	.usb_device_description = NULL,
	.interface_config = bt_h4_interface_config,
	.interface_descriptor = &bt_h4_cfg.if0,
	.cb_usb_status = bt_h4_status_cb,
	.interface = {
		.class_handler = NULL,
		.custom_handler = NULL,
		.vendor_handler = bt_h4_vendor_handler,
	},
	.num_endpoints = ARRAY_SIZE(bt_h4_ep_data),
	.endpoint = bt_h4_ep_data,
};

static int bt_h4_init(const struct device *dev)
{
	int ret;

	LOG_DBG("Initialization");

	ret = bt_enable_raw(&tx_queue);
	if (ret) {
		LOG_ERR("Failed to open Bluetooth raw channel: %d", ret);
		return ret;
	}

	k_thread_create(&rx_thread_data, rx_thread_stack,
			K_KERNEL_STACK_SIZEOF(rx_thread_stack),
			(k_thread_entry_t)hci_rx_thread, NULL, NULL, NULL,
			K_PRIO_COOP(8), 0, K_NO_WAIT);

	k_thread_name_set(&rx_thread_data, "usb_bt_h4_rx");

	k_thread_create(&tx_thread_data, tx_thread_stack,
			K_KERNEL_STACK_SIZEOF(tx_thread_stack),
			(k_thread_entry_t)hci_tx_thread, NULL, NULL, NULL,
			K_PRIO_COOP(8), 0, K_NO_WAIT);

	k_thread_name_set(&tx_thread_data, "usb_bt_h4_tx");

	return 0;
}

SYS_INIT(bt_h4_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
