/* net_driver_bt.c - IP Bluetooth LE driver */

/*
 * Copyright (c) 2015 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 <nanokernel.h>
#include <toolchain.h>
#include <sections.h>
#include <string.h>
#include <errno.h>

#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT           printf
#else
#include <misc/printk.h>
#define PRINT           printk
#endif

#include <net/buf.h>
#include <net/ip_buf.h>
#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/net_socket.h>
#include "contiki/netstack.h"
#include <net_driver_bt.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/gatt.h>

#define L2CAP_IPSP_PSM 0x0023
#define L2CAP_IPSP_MTU IP_BUF_MAX_DATA

static inline void memswap(void *dst, const void *src, int len)
{
	int i;

	for (i = 0; i < len; i++) {
		((uint8_t *)dst)[i] = ((uint8_t *)src)[(len - 1) - i];
	}
}

static void ipsp_connected(struct bt_l2cap_chan *chan)
{
	struct bt_conn_info info;
	char src[BT_ADDR_LE_STR_LEN];
	char dst[BT_ADDR_LE_STR_LEN];
	linkaddr_t addr;

	bt_conn_get_info(chan->conn, &info);

	bt_addr_le_to_str(info.le.src, src, sizeof(src));
	bt_addr_le_to_str(info.le.dst, dst, sizeof(dst));

	NET_DBG("Channel %p Source %s connected to Destination %s\n", chan,
		src, dst);

	/* Swap bytes since net_set_mac expect big endian address */
	memswap(addr.u8, info.le.src->a.val, sizeof(addr.u8));

	net_set_mac(addr.u8, sizeof(addr));
}

static void ipsp_disconnected(struct bt_l2cap_chan *chan)
{
	NET_DBG("Channel %p disconnected\n", chan);
}

static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
	struct bt_conn_info info;
	linkaddr_t src;
	linkaddr_t dst;

	NET_DBG("Incoming data channel %p len %u\n", chan, ip_buf_len(buf));

	bt_conn_get_info(chan->conn, &info);

	/* Swap bytes since linkaddr_copy expect big endian address */
	memswap(src.u8, info.le.src->a.val, sizeof(src));
	memswap(dst.u8, info.le.dst->a.val, sizeof(dst));

	/* Add MAC addresses to the buffer */
	linkaddr_copy(&ip_buf_ll_dest(buf), &src);
	linkaddr_copy(&ip_buf_ll_src(buf), &dst);

	/* Initialize uip_len */
	uip_len(buf) = ip_buf_len(buf);

	/* Uncompress data */
	if (!NETSTACK_COMPRESS.uncompress(buf)) {
		NET_ERR("uncompression failed\n");
		return;
	}

	/* net_recv takes ownership of the buffer */
	net_buf_ref(buf);

	/* Add buffer to rx_queue */
	if (net_recv(buf) < 0) {
		NET_ERR("input to IP stack failed\n");
		net_buf_unref(buf);
		return;
	}
}

static struct net_buf *ipsp_alloc_buf(struct bt_l2cap_chan *chan)
{
	NET_DBG("Channel %p requires buffer\n", chan);

	return ip_buf_get_reserve_rx(0);
}

static struct bt_l2cap_chan_ops ipsp_ops = {
	.alloc_buf	= ipsp_alloc_buf,
	.recv		= ipsp_recv,
	.connected	= ipsp_connected,
	.disconnected	= ipsp_disconnected,
};

static struct bt_l2cap_chan ipsp_chan = {
	.ops		= &ipsp_ops,
	.rx.mtu		= L2CAP_IPSP_MTU,
};

static int ipsp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
{
	NET_DBG("Incoming conn %p\n", conn);

	if (ipsp_chan.conn) {
		NET_ERR("No channels available");
		return -ENOMEM;
	}

	*chan = &ipsp_chan;

	return 0;
}

static struct bt_l2cap_server server = {
	.psm		= L2CAP_IPSP_PSM,
	.accept		= ipsp_accept,
};

static struct bt_gatt_attr attrs[] = {
	/* IPSS Service Declaration */
	BT_GATT_PRIMARY_SERVICE(BT_UUID_IPSS),
};

static int net_driver_bt_open(void)
{
	bt_gatt_register(attrs, ARRAY_SIZE(attrs));

	bt_l2cap_server_register(&server);

	return 0;
}

static int net_driver_bt_send(struct net_buf *buf)
{
#ifdef CONFIG_NETWORKING_WITH_LOGGING
	int orig_len = ip_buf_len(buf);
#endif

	if (!NETSTACK_COMPRESS.compress(buf)) {
		NET_DBG("compression failed\n");
		ip_buf_unref(buf);
		return -EINVAL;
	}

	NET_DBG("sending %d bytes (original len %d)\n", ip_buf_len(buf),
		orig_len);

	return bt_l2cap_chan_send(&ipsp_chan, buf);
}

static struct net_driver net_driver_bt = {
	.head_reserve = 0,
	.open = net_driver_bt_open,
	.send = net_driver_bt_send,
};

int net_driver_bt_init(void)
{
	NETSTACK_COMPRESS.init();

	net_register_driver(&net_driver_bt);

	return 0;
}
