Register HCI device

Signed-off-by: Fabien Parent <fparent@baylibre.com>
diff --git a/btmtk_sdio.c b/btmtk_sdio.c
index 516e729..1f571ca 100644
--- a/btmtk_sdio.c
+++ b/btmtk_sdio.c
@@ -70,6 +70,7 @@
 static wait_queue_head_t fw_log_inq;
 static struct fasync_struct *fasync;
 /*static int btmtk_woble_state = BTMTK_WOBLE_STATE_UNKNOWN;*/
+static struct hci_dev *hdev;
 
 static int need_reset_stack;
 static int need_set_i2s = 0;
@@ -2416,6 +2417,19 @@
 		bt_cb(fops_skb)->pkt_type = type;
 		memcpy(fops_skb->data, skb->data, buf_len);
 
+
+		{
+			struct sk_buff *skb_hci = bt_skb_alloc(buf_len, GFP_KERNEL);
+			skb_put(skb_hci, buf_len);
+
+			memcpy(skb_hci->data, fops_skb->data, buf_len);
+			hci_skb_pkt_type(skb_hci) = type;
+
+			ret = hci_recv_frame(hdev, skb_hci);
+			if (ret < 0)
+				printk(KERN_ERR "XXX: error recv frame: %d\n", ret);
+		}
+
 		fops_skb->len = buf_len;
 		lock_unsleepable_lock(&(metabuffer.spin_lock));
 		skb_queue_tail(&g_priv->adapter->fops_queue, fops_skb);
@@ -2936,6 +2950,29 @@
 }
 #endif
 
+static int btsdio_open(struct hci_dev *hdev)
+{
+	return 0;
+}
+
+static int btsdio_close(struct hci_dev *hdev)
+{
+	return 0;
+}
+
+static int btsdio_flush(struct hci_dev *hdev)
+{
+	return 0;
+}
+
+static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	skb_queue_tail(&g_priv->adapter->tx_queue, skb);
+	wake_up_interruptible(&g_priv->main_thread.wait_q);
+
+	return 0;
+}
+
 static int btmtk_sdio_probe(struct sdio_func *func,
 					const struct sdio_device_id *id)
 {
@@ -3075,6 +3112,31 @@
 	btmtk_stereo_reg_irq();
 #endif
 
+	hdev = hci_alloc_dev();
+	if (!hdev)
+		return -ENOMEM;
+
+	hdev->bus = HCI_SDIO;
+
+	if (id->class == SDIO_CLASS_BT_AMP)
+		hdev->dev_type = HCI_AMP;
+	else
+		hdev->dev_type = HCI_PRIMARY;
+
+	SET_HCIDEV_DEV(hdev, &func->dev);
+
+	hdev->open     = btsdio_open;
+	hdev->close    = btsdio_close;
+	hdev->flush    = btsdio_flush;
+	hdev->send     = btsdio_send_frame;
+
+	ret = hci_register_dev(hdev);
+	if (ret < 0) {
+		pr_err("XXX: Failed to register HCI: %d\n", ret);
+		hci_free_dev(hdev);
+		return ret;
+	}
+
 	pr_info("%s normal end\n", __func__);
 	probe_ready = true;
 	return 0;
@@ -3089,10 +3151,14 @@
 static void btmtk_sdio_remove(struct sdio_func *func)
 {
 	struct btmtk_sdio_card *card;
+	int ret;
 
 	pr_info("%s begin user_rmmod %d\n", __func__, user_rmmod);
 	probe_ready = false;
 
+	hci_unregister_dev(hdev);
+	hci_free_dev(hdev);
+
 #if SUPPORT_BT_STEREO
 	btmtk_stereo_unreg_irq();
 #endif