/* uart.c - Nordic BLE UART based Bluetooth driver */

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <errno.h>

#include <nanokernel.h>
#include <sections.h>

#include <board.h>
#include <init.h>
#include <uart.h>
#include <string.h>
#include <gpio.h>

#include <net/buf.h>

#include <bluetooth/log.h>

#include "util.h"
#include "rpc.h"

#if defined(CONFIG_BLUETOOTH_NRF51_PM)
#include "nrf51_pm.h"
#endif

#if !defined(CONFIG_BLUETOOTH_DEBUG_DRIVER)
#undef BT_DBG
#define BT_DBG(fmt, ...)
#endif

/**
 * @note this structure must be self-aligned and self-packed
 */
struct ipc_uart_header {
	uint16_t len;		/**< Length of IPC message. */
	uint8_t channel;	/**< Channel number of IPC message. */
	uint8_t src_cpu_id;	/**< CPU id of IPC sender. */
} __packed;

/* TODO: check size */
#define NBLE_TX_BUF_COUNT	2
#define NBLE_RX_BUF_COUNT	10
#define NBLE_BUF_SIZE		384

static struct nano_fifo rx;
static NET_BUF_POOL(rx_pool, NBLE_RX_BUF_COUNT, NBLE_BUF_SIZE, &rx, NULL, 0);

static struct nano_fifo tx;
static NET_BUF_POOL(tx_pool, NBLE_TX_BUF_COUNT, NBLE_BUF_SIZE, &tx, NULL, 0);

static BT_STACK_NOINIT(rx_fiber_stack, CONFIG_BLUETOOTH_RX_STACK_SIZE);

static struct device *nble_dev;

static struct nano_fifo rx_queue;

static void rx_fiber(void)
{
	BT_DBG("Started");

	while (true) {
		struct net_buf *buf;

		buf = nano_fifo_get(&rx_queue, TICKS_UNLIMITED);
		BT_DBG("Got buf %p", buf);

		rpc_deserialize(buf);

		net_buf_unref(buf);
	}
}

struct net_buf *rpc_alloc_cb(uint16_t length)
{
	struct net_buf *buf;

	BT_DBG("length %u", length);

	buf = net_buf_get(&tx, sizeof(struct ipc_uart_header));
	if (!buf) {
		BT_ERR("Unable to get tx buffer");
		return NULL;
	}

	if (length > net_buf_tailroom(buf)) {
		BT_ERR("Too big tx buffer requested");
		net_buf_unref(buf);
		return NULL;
	}

	return buf;
}

void rpc_transmit_cb(struct net_buf *buf)
{
	struct ipc_uart_header *hdr;

	BT_DBG("buf %p length %u", buf, buf->len);

	hdr = net_buf_push(buf, sizeof(*hdr));
	hdr->len = buf->len - sizeof(*hdr);
	hdr->channel = 0;
	hdr->src_cpu_id = 0;

	while (buf->len) {
		uart_poll_out(nble_dev, net_buf_pull_u8(buf));
	}

	net_buf_unref(buf);
}

static size_t nble_discard(struct device *uart, size_t len)
{
	/* FIXME: correct size for nble */
	uint8_t buf[33];

	return uart_fifo_read(uart, buf, min(len, sizeof(buf)));
}

static void bt_uart_isr(struct device *unused)
{
	static struct net_buf *buf;

	ARG_UNUSED(unused);

	while (uart_irq_update(nble_dev) && uart_irq_is_pending(nble_dev)) {
		static struct ipc_uart_header hdr;
		static uint8_t hdr_bytes;
		int read;

		if (!uart_irq_rx_ready(nble_dev)) {
			if (uart_irq_tx_ready(nble_dev)) {
				BT_DBG("transmit ready");
				/*
				 * Implementing ISR based transmit requires
				 * extra API for uart such as
				 * uart_line_status(), etc. The support was
				 * removed from the recent code, using polling
				 * for transmit for now.
				 */
			} else {
				BT_DBG("spurious interrupt");
			}
			continue;
		}

		if (hdr_bytes < sizeof(hdr)) {
			/* Get packet type */
			hdr_bytes += uart_fifo_read(nble_dev,
						    (uint8_t *)&hdr + hdr_bytes,
						    sizeof(hdr) - hdr_bytes);
			if (hdr_bytes < sizeof(hdr)) {
				continue;
			}

			if (hdr.len > NBLE_BUF_SIZE) {
				BT_ERR("Too much data to fit buffer");
				buf = NULL;
			} else {
				buf = net_buf_get_timeout(&rx, 0, TICKS_NONE);
				if (!buf) {
					BT_ERR("No available IPC buffers");
				}
			}
		}

		if (!buf) {
			hdr.len -= nble_discard(nble_dev, hdr.len);
			if (!hdr.len) {
				hdr_bytes = 0;
			}
			continue;
		}

		read = uart_fifo_read(nble_dev, net_buf_tail(buf), hdr.len);

		buf->len += read;
		hdr.len -= read;

		if (!hdr.len) {
			BT_DBG("full packet received");
			hdr_bytes = 0;
			/* Pass buffer to the stack */
			nano_fifo_put(&rx_queue, buf);
		}
	}
}

int nble_open(void)
{
	BT_DBG("");

	/* Initialize receive queue and start rx_fiber */
	nano_fifo_init(&rx_queue);
	fiber_start(rx_fiber_stack, sizeof(rx_fiber_stack),
		    (nano_fiber_entry_t)rx_fiber, 0, 0, 7, 0);

	uart_irq_rx_disable(nble_dev);
	uart_irq_tx_disable(nble_dev);

#if defined(CONFIG_BLUETOOTH_NRF51_PM)
	if (nrf51_init(nble_dev) < 0) {
		return -EIO;
	}
#else
	bt_uart_drain(nble_dev);
#endif

	uart_irq_callback_set(nble_dev, bt_uart_isr);

	uart_irq_rx_enable(nble_dev);

	return 0;
}

static int _bt_nble_init(struct device *unused)
{
	ARG_UNUSED(unused);

	nble_dev = device_get_binding(CONFIG_NBLE_UART_ON_DEV_NAME);
	if (!nble_dev) {
		return -EINVAL;
	}

	net_buf_pool_init(rx_pool);
	net_buf_pool_init(tx_pool);

	return 0;
}

DEVICE_INIT(bt_nble, "", _bt_nble_init, NULL, NULL, NANOKERNEL,
	    CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
