/*
 * Copyright (c) 2017 Linaro Limited
 * Copyright (c) 2016 Nordic Semiconductor ASA
 * Copyright (c) 2015-2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <errno.h>
#include <stddef.h>
#include <stdio.h>

#include <zephyr.h>
#include <misc/byteorder.h>
#include <logging/sys_log.h>
#include <misc/stack.h>

#include <device.h>
#include <init.h>
#include <gpio.h>
#include <spi.h>

#include <net/buf.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/hci.h>
#include <bluetooth/buf.h>
#include <bluetooth/hci_raw.h>

#include "common/log.h"

#define HCI_CMD                 0x01
#define HCI_ACL                 0x02
#define HCI_SCO                 0x03
#define HCI_EVT                 0x04

/* Special Values */
#define SPI_WRITE               0x0A
#define SPI_READ                0x0B
#define READY_NOW               0x02
#define SANITY_CHECK            0x02

/* Offsets */
#define STATUS_HEADER_READY     0
#define STATUS_HEADER_TOREAD    3

#define PACKET_TYPE             0
#define EVT_BLUE_INITIALIZED    0x01

#define SPI_HCI_DEV_NAME        CONFIG_BT_CTLR_TO_HOST_SPI_DEV_NAME
#define GPIO_IRQ_DEV_NAME       CONFIG_BT_CTLR_TO_HOST_SPI_IRQ_DEV_NAME
#define GPIO_IRQ_PIN            CONFIG_BT_CTLR_TO_HOST_SPI_IRQ_PIN

/* Needs to be aligned with the SPI master buffer size */
#define SPI_MAX_MSG_LEN         255

static u8_t rxmsg[SPI_MAX_MSG_LEN];
static u8_t txmsg[SPI_MAX_MSG_LEN];

/* HCI buffer pools */
#define CMD_BUF_SIZE BT_BUF_RX_SIZE

NET_BUF_POOL_DEFINE(cmd_tx_pool, CONFIG_BT_HCI_CMD_COUNT, CMD_BUF_SIZE,
		    BT_BUF_USER_DATA_MIN, NULL);

#if defined(CONFIG_BT_CTLR)
#define BT_L2CAP_MTU (CONFIG_BT_CTLR_TX_BUFFER_SIZE - \
		      BT_L2CAP_HDR_SIZE)
#else
#define BT_L2CAP_MTU 65 /* 64-byte public key + opcode */
#endif /* CONFIG_BT_CTLR */

/* Data size needed for ACL buffers */
#define BT_BUF_ACL_SIZE BT_L2CAP_BUF_SIZE(BT_L2CAP_MTU)

#if defined(CONFIG_BT_CTLR_TX_BUFFERS)
#define TX_BUF_COUNT CONFIG_BT_CTLR_TX_BUFFERS
#else
#define TX_BUF_COUNT 6
#endif

NET_BUF_POOL_DEFINE(acl_tx_pool, TX_BUF_COUNT, BT_BUF_ACL_SIZE,
		    BT_BUF_USER_DATA_MIN, NULL);

static struct device *spi_hci_dev;
static struct device *gpio_dev;
static BT_STACK_NOINIT(bt_tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE);
static struct k_thread bt_tx_thread_data;

static K_SEM_DEFINE(sem_spi_rx, 0, 1);
static K_SEM_DEFINE(sem_spi_tx, 0, 1);

static inline int spi_send(struct net_buf *buf)
{
	u8_t header_master[5] = { 0 };
	u8_t header_slave[5] = { READY_NOW, SANITY_CHECK,
				 0x00, 0x00, 0x00 };
	int ret;

	SYS_LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf),
		    buf->len);

	switch (bt_buf_get_type(buf)) {
	case BT_BUF_ACL_IN:
		net_buf_push_u8(buf, HCI_ACL);
		break;
	case BT_BUF_EVT:
		net_buf_push_u8(buf, HCI_EVT);
		break;
	default:
		SYS_LOG_ERR("Unknown type %u", bt_buf_get_type(buf));
		net_buf_unref(buf);
		return -EINVAL;
	}

	if (buf->len > SPI_MAX_MSG_LEN) {
		SYS_LOG_ERR("TX message too long");
		net_buf_unref(buf);
		return -EINVAL;
	}
	header_slave[STATUS_HEADER_TOREAD] = buf->len;

	gpio_pin_write(gpio_dev, GPIO_IRQ_PIN, 1);

	/* Coordinate transfer lock with the spi rx thread */
	k_sem_take(&sem_spi_tx, K_FOREVER);
	do {
		ret = spi_transceive(spi_hci_dev, header_slave, 5,
				     header_master, 5);
		if (ret < 0) {
			SYS_LOG_ERR("SPI transceive error: %d", ret);
		}
	} while (header_master[STATUS_HEADER_READY] != SPI_READ);

	ret = spi_transceive(spi_hci_dev, buf->data, buf->len,
			     &rxmsg, buf->len);
	if (ret < 0) {
		SYS_LOG_ERR("SPI transceive error: %d", ret);
	}
	net_buf_unref(buf);

	gpio_pin_write(gpio_dev, GPIO_IRQ_PIN, 0);
	k_sem_give(&sem_spi_rx);

	return 0;
}

static void bt_tx_thread(void *p1, void *p2, void *p3)
{
	u8_t header_master[5];
	u8_t header_slave[5] = { READY_NOW, SANITY_CHECK,
				 0x00, 0x00, 0x00 };
	struct net_buf *buf = NULL;
	struct bt_hci_cmd_hdr cmd_hdr;
	struct bt_hci_acl_hdr acl_hdr;
	int ret;

	ARG_UNUSED(p1);
	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

	memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN);

	while (1) {
		do {
			ret = spi_transceive(spi_hci_dev, header_slave, 5,
					     header_master, 5);
			if (ret < 0) {
				SYS_LOG_ERR("SPI transceive error: %d", ret);
			}
		} while ((header_master[STATUS_HEADER_READY] != SPI_READ) &&
			 (header_master[STATUS_HEADER_READY] != SPI_WRITE));

		if (header_master[STATUS_HEADER_READY] == SPI_READ) {
			/* Unblock the spi tx thread and wait for it */
			k_sem_give(&sem_spi_tx);
			k_sem_take(&sem_spi_rx, K_FOREVER);
			continue;
		}

		/* Receiving data from the SPI Host */
		ret = spi_transceive(spi_hci_dev, &txmsg, SPI_MAX_MSG_LEN,
				     &rxmsg, SPI_MAX_MSG_LEN);
		if (ret < 0) {
			SYS_LOG_ERR("SPI transceive error: %d", ret);
			continue;
		}

		switch (rxmsg[PACKET_TYPE]) {
		case HCI_CMD:
			memcpy(&cmd_hdr, &rxmsg[1], sizeof(cmd_hdr));

			buf = net_buf_alloc(&cmd_tx_pool, K_NO_WAIT);
			if (buf) {
				bt_buf_set_type(buf, BT_BUF_CMD);
				net_buf_add_mem(buf, &cmd_hdr,
						sizeof(cmd_hdr));
				net_buf_add_mem(buf, &rxmsg[4],
						cmd_hdr.param_len);
			} else {
				SYS_LOG_ERR("No available command buffers!");
				continue;
			}
			break;
		case HCI_ACL:
			memcpy(&acl_hdr, &rxmsg[1], sizeof(acl_hdr));

			buf = net_buf_alloc(&acl_tx_pool, K_NO_WAIT);
			if (buf) {
				bt_buf_set_type(buf, BT_BUF_ACL_OUT);
				net_buf_add_mem(buf, &acl_hdr,
						sizeof(acl_hdr));
				net_buf_add_mem(buf, &rxmsg[5],
						sys_le16_to_cpu(acl_hdr.len));
			} else {
				SYS_LOG_ERR("No available ACL buffers!");
				continue;
			}
			break;
		default:
			SYS_LOG_ERR("Unknown BT HCI buf type");
			continue;
		}

		SYS_LOG_DBG("buf %p type %u len %u",
			    buf, bt_buf_get_type(buf), buf->len);

		ret = bt_send(buf);
		if (ret) {
			SYS_LOG_ERR("Unable to send (ret %d)", ret);
			net_buf_unref(buf);
		}

		STACK_ANALYZE("tx_stack", bt_tx_thread_stack);

		/* Make sure other threads get a chance to run */
		k_yield();
	}
}

static int hci_spi_init(struct device *unused)
{
	static struct spi_config btspi_config = {
		.config = SPI_WORD(8),
	};

	ARG_UNUSED(unused);

	SYS_LOG_DBG("");

	spi_hci_dev = device_get_binding(SPI_HCI_DEV_NAME);
	if (!spi_hci_dev) {
		return -EINVAL;
	}

	if (spi_configure(spi_hci_dev, &btspi_config) < 0) {
		return -EINVAL;
	}

	gpio_dev = device_get_binding(GPIO_IRQ_DEV_NAME);
	if (!gpio_dev) {
		return -EINVAL;
	}
	gpio_pin_configure(gpio_dev, GPIO_IRQ_PIN,
			   GPIO_DIR_OUT | GPIO_PUD_PULL_DOWN);

	return 0;
}

DEVICE_INIT(hci_spi, "hci_spi", &hci_spi_init, NULL, NULL,
	    APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

void main(void)
{
	static K_FIFO_DEFINE(rx_queue);
	struct bt_hci_evt_hdr *evt_hdr;
	struct net_buf *buf;
	k_tid_t tx_id;
	int err;

	SYS_LOG_DBG("Start");

	err = bt_enable_raw(&rx_queue);
	if (err) {
		SYS_LOG_ERR("bt_enable_raw: %d; aborting", err);
		return;
	}

	/* Spawn the TX thread, which feeds cmds and data to the controller */
	tx_id = k_thread_create(&bt_tx_thread_data, bt_tx_thread_stack,
				K_THREAD_STACK_SIZEOF(bt_tx_thread_stack),
				bt_tx_thread, NULL, NULL, NULL, K_PRIO_COOP(7),
				0, K_NO_WAIT);

	/* Send a vendor event to announce that the slave is initialized */
	buf = net_buf_alloc(&cmd_tx_pool, K_FOREVER);
	bt_buf_set_type(buf, BT_BUF_EVT);
	evt_hdr = net_buf_add(buf, sizeof(*evt_hdr));
	evt_hdr->evt = BT_HCI_EVT_VENDOR;
	evt_hdr->len = 2;
	net_buf_add_le16(buf, EVT_BLUE_INITIALIZED);
	err = spi_send(buf);
	if (err) {
		SYS_LOG_ERR("can't send initialization event; aborting");
		k_thread_abort(tx_id);
		return;
	}

	while (1) {
		buf = net_buf_get(&rx_queue, K_FOREVER);
		err = spi_send(buf);
		if (err) {
			SYS_LOG_ERR("Failed to send");
		}
	}
}
