/*
 * Copyright (c) 2017 Redpine Signals Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <asm/unaligned.h>
#include <net/rsi_91x.h>

#define RSI_DMA_ALIGN	8
#define RSI_FRAME_DESC_SIZE	16
#define RSI_HEADROOM_FOR_BT_HAL	(RSI_FRAME_DESC_SIZE + RSI_DMA_ALIGN)

struct rsi_hci_adapter {
	void *priv;
	struct rsi_proto_ops *proto_ops;
	struct hci_dev *hdev;
};

static int rsi_hci_open(struct hci_dev *hdev)
{
	return 0;
}

static int rsi_hci_close(struct hci_dev *hdev)
{
	return 0;
}

static int rsi_hci_flush(struct hci_dev *hdev)
{
	return 0;
}

static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
{
	struct rsi_hci_adapter *h_adapter = hci_get_drvdata(hdev);
	struct sk_buff *new_skb = NULL;

	switch (hci_skb_pkt_type(skb)) {
	case HCI_COMMAND_PKT:
		hdev->stat.cmd_tx++;
		break;
	case HCI_ACLDATA_PKT:
		hdev->stat.acl_tx++;
		break;
	case HCI_SCODATA_PKT:
		hdev->stat.sco_tx++;
		break;
	}

	if (skb_headroom(skb) < RSI_HEADROOM_FOR_BT_HAL) {
		/* Insufficient skb headroom - allocate a new skb */
		new_skb = skb_realloc_headroom(skb, RSI_HEADROOM_FOR_BT_HAL);
		if (unlikely(!new_skb))
			return -ENOMEM;
		bt_cb(new_skb)->pkt_type = hci_skb_pkt_type(skb);
		kfree_skb(skb);
		skb = new_skb;
		if (!IS_ALIGNED((unsigned long)skb->data, RSI_DMA_ALIGN)) {
			u8 *skb_data = skb->data;
			int skb_len = skb->len;

			skb_push(skb, RSI_DMA_ALIGN);
			skb_pull(skb, PTR_ALIGN(skb->data,
						RSI_DMA_ALIGN) - skb->data);
			memmove(skb->data, skb_data, skb_len);
			skb_trim(skb, skb_len);
		}
	}

	return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb,
						   RSI_BT_Q);
}

static int rsi_hci_recv_pkt(void *priv, const u8 *pkt)
{
	struct rsi_hci_adapter *h_adapter = priv;
	struct hci_dev *hdev = h_adapter->hdev;
	struct sk_buff *skb;
	int pkt_len = get_unaligned_le16(pkt) & 0x0fff;

	skb = dev_alloc_skb(pkt_len);
	if (!skb)
		return -ENOMEM;

	memcpy(skb->data, pkt + RSI_FRAME_DESC_SIZE, pkt_len);
	skb_put(skb, pkt_len);
	h_adapter->hdev->stat.byte_rx += skb->len;

	hci_skb_pkt_type(skb) = pkt[14];

	return hci_recv_frame(hdev, skb);
}

static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
{
	struct rsi_hci_adapter *h_adapter = NULL;
	struct hci_dev *hdev;
	int err = 0;

	h_adapter = kzalloc(sizeof(*h_adapter), GFP_KERNEL);
	if (!h_adapter)
		return -ENOMEM;

	h_adapter->priv = priv;
	ops->set_bt_context(priv, h_adapter);
	h_adapter->proto_ops = ops;

	hdev = hci_alloc_dev();
	if (!hdev) {
		BT_ERR("Failed to alloc HCI device");
		goto err;
	}

	h_adapter->hdev = hdev;

	if (ops->get_host_intf(priv) == RSI_HOST_INTF_SDIO)
		hdev->bus = HCI_SDIO;
	else
		hdev->bus = HCI_USB;

	hci_set_drvdata(hdev, h_adapter);
	hdev->dev_type = HCI_PRIMARY;
	hdev->open = rsi_hci_open;
	hdev->close = rsi_hci_close;
	hdev->flush = rsi_hci_flush;
	hdev->send = rsi_hci_send_pkt;

	err = hci_register_dev(hdev);
	if (err < 0) {
		BT_ERR("HCI registration failed with errcode %d", err);
		hci_free_dev(hdev);
		goto err;
	}

	return 0;
err:
	h_adapter->hdev = NULL;
	kfree(h_adapter);
	return -EINVAL;
}

static void rsi_hci_detach(void *priv)
{
	struct rsi_hci_adapter *h_adapter = priv;
	struct hci_dev *hdev;

	if (!h_adapter)
		return;

	hdev = h_adapter->hdev;
	if (hdev) {
		hci_unregister_dev(hdev);
		hci_free_dev(hdev);
		h_adapter->hdev = NULL;
	}

	kfree(h_adapter);
}

const struct rsi_mod_ops rsi_bt_ops = {
	.attach	= rsi_hci_attach,
	.detach	= rsi_hci_detach,
	.recv_pkt = rsi_hci_recv_pkt,
};
EXPORT_SYMBOL(rsi_bt_ops);

static int rsi_91x_bt_module_init(void)
{
	return 0;
}

static void rsi_91x_bt_module_exit(void)
{
	return;
}

module_init(rsi_91x_bt_module_init);
module_exit(rsi_91x_bt_module_exit);
MODULE_AUTHOR("Redpine Signals Inc");
MODULE_DESCRIPTION("RSI BT driver");
MODULE_LICENSE("Dual BSD/GPL");
