/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define SYS_LOG_LEVEL CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL
#define SYS_LOG_DOMAIN "net/ieee802154/upipe/"
#include <logging/sys_log.h>

#include <errno.h>

#include <kernel.h>
#include <arch/cpu.h>

#include <board.h>
#include <device.h>
#include <init.h>
#include <net/net_if.h>
#include <net/net_pkt.h>

#include <console/uart_pipe.h>
#include <net/ieee802154_radio.h>

#include "ieee802154_uart_pipe.h"

/** Singleton device used in uart pipe callback */
static struct device *upipe_dev;

static u8_t *upipe_rx(u8_t *buf, size_t *off)
{
	struct upipe_context *upipe = upipe_dev->driver_data;
	struct net_pkt *pkt = NULL;
	struct net_buf *frag = NULL;

	if (!upipe_dev) {
		goto done;
	}

	if (!upipe->rx && *buf == UART_PIPE_RADIO_15_4_FRAME_TYPE) {
		upipe->rx = true;
		goto done;
	}

	if (!upipe->rx_len) {
		if (*buf > 127) {
			goto flush;
		}

		upipe->rx_len = *buf;
		goto done;
	}

	upipe->rx_buf[upipe->rx_off++] = *buf;

	if (upipe->rx_len == upipe->rx_off) {
		pkt = net_pkt_get_reserve_rx(0, K_NO_WAIT);
		if (!pkt) {
			SYS_LOG_DBG("No pkt available");
			goto flush;
		}

		frag = net_pkt_get_frag(pkt, K_NO_WAIT);
		if (!frag) {
			SYS_LOG_DBG("No fragment available");
			goto out;
		}

		net_pkt_frag_insert(pkt, frag);

		memcpy(frag->data, upipe->rx_buf, upipe->rx_len - 2);
		net_buf_add(frag, upipe->rx_len - 2);

		if (ieee802154_radio_handle_ack(upipe->iface, pkt) == NET_OK) {
			SYS_LOG_DBG("ACK packet handled");
			goto out;
		}

		SYS_LOG_DBG("Caught a packet (%u)", upipe->rx_len);
		if (net_recv_data(upipe->iface, pkt) < 0) {
			SYS_LOG_DBG("Packet dropped by NET stack");
			goto out;
		}

		goto flush;
out:
		net_pkt_unref(pkt);
flush:
		upipe->rx = false;
		upipe->rx_len = 0;
		upipe->rx_off = 0;
	}
done:
	*off = 0;

	return buf;
}

static enum ieee802154_hw_caps upipe_get_capabilities(struct device *dev)
{
	return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ;
}

static int upipe_cca(struct device *dev)
{
	struct upipe_context *upipe = dev->driver_data;

	if (upipe->stopped) {
		return -EIO;
	}

	return 0;
}

static int upipe_set_channel(struct device *dev, u16_t channel)
{
	struct upipe_context *upipe = dev->driver_data;

	if (upipe->stopped) {
		return -EIO;
	}

	return 0;
}

static int upipe_set_txpower(struct device *dev, s16_t dbm)
{
	struct upipe_context *upipe = dev->driver_data;

	if (upipe->stopped) {
		return -EIO;
	}

	return 0;
}

static int upipe_tx(struct device *dev,
		    struct net_pkt *pkt,
		    struct net_buf *frag)
{
	u8_t *pkt_buf = frag->data - net_pkt_ll_reserve(pkt);
	u8_t len = net_pkt_ll_reserve(pkt) + frag->len;
	struct upipe_context *upipe = dev->driver_data;
	u8_t i, data;

	SYS_LOG_DBG("%p (%u)", frag, len);

	if (upipe->stopped) {
		return -EIO;
	}

	data = UART_PIPE_RADIO_15_4_FRAME_TYPE;
	uart_pipe_send(&data, 1);

	data = len + 2;
	uart_pipe_send(&data, 1);

	for (i = 0; i < len; i++) {
		uart_pipe_send(pkt_buf+i, 1);
	}

	/* The 2 dummy bytes representing FCS */
	data = 0xFF;
	uart_pipe_send(&data, 1);
	uart_pipe_send(&data, 1);

	return 0;
}

static int upipe_start(struct device *dev)
{
	struct upipe_context *upipe = dev->driver_data;

	if (!upipe->stopped) {
		return -EALREADY;
	}

	upipe->stopped = false;

	return 0;
}

static int upipe_stop(struct device *dev)
{
	struct upipe_context *upipe = dev->driver_data;

	if (upipe->stopped) {
		return -EALREADY;
	}

	upipe->stopped = true;

	return 0;
}

static int upipe_init(struct device *dev)
{
	struct upipe_context *upipe = dev->driver_data;

	memset(upipe, 0, sizeof(struct upipe_context));

	uart_pipe_register(upipe->uart_pipe_buf, 1, upipe_rx);

	upipe_stop(dev);

	return 0;
}

static inline u8_t *get_mac(struct device *dev)
{
	struct upipe_context *upipe = dev->driver_data;

	upipe->mac_addr[0] = 0x00;
	upipe->mac_addr[1] = 0x10;
	upipe->mac_addr[2] = 0x20;
	upipe->mac_addr[3] = 0x30;

	UNALIGNED_PUT(sys_cpu_to_be32(sys_rand32_get()),
		      (u32_t *) ((void *)upipe->mac_addr+4));

	return upipe->mac_addr;
}

static void upipe_iface_init(struct net_if *iface)
{
	struct device *dev = net_if_get_device(iface);
	struct upipe_context *upipe = dev->driver_data;
	u8_t *mac = get_mac(dev);

	SYS_LOG_DBG("");

	net_if_set_link_addr(iface, mac, 8, NET_LINK_IEEE802154);

	upipe_dev = dev;
	upipe->iface = iface;

	ieee802154_init(iface);
}

static struct upipe_context upipe_context_data;

static struct ieee802154_radio_api upipe_radio_api = {
	.iface_api.init		= upipe_iface_init,
	.iface_api.send		= ieee802154_radio_send,

	.get_capabilities	= upipe_get_capabilities,
	.cca			= upipe_cca,
	.set_channel		= upipe_set_channel,
	.set_txpower		= upipe_set_txpower,
	.tx			= upipe_tx,
	.start			= upipe_start,
	.stop			= upipe_stop,
};

NET_DEVICE_INIT(upipe_15_4, CONFIG_IEEE802154_UPIPE_DRV_NAME,
		upipe_init, &upipe_context_data, NULL,
		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
		&upipe_radio_api, IEEE802154_L2,
		NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125);
