linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 1/3] Bluetooth: Add initial skeleton for Intel BT USB support
@ 2012-09-10 21:29 Tedd Ho-Jeong An
  0 siblings, 0 replies; 3+ messages in thread
From: Tedd Ho-Jeong An @ 2012-09-10 21:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, tedd.an, Ho, Albert O

[-- Attachment #1: Type: text/plain, Size: 10191 bytes --]

From: Tedd Ho-Jeong An <tedd.an@intel.com>

This patch adds an initial skeleton for Intel BT USB support.

- Extension to execute of vendor specific initialization at early stage
  which is before normal BT controller initialization and after the USB
  is initialized.

- Add initial skeleton of Intel specific initialization functions

- Add Intel BT USB VID/PID

Outpu from /sys/kernel/debug/usb/devices:

T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=8087 ProdID=07dc Rev= 0.00
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=81(I) Atr=03(Int.) MxPS=  64 Ivl=1ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
I:  If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
I:  If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
I:  If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
I:  If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
I:  If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms

Signed-off-by: Tedd Ho-Jeong AN <tedd.an@intel.com>
---
 drivers/bluetooth/Makefile       |    2 +-
 drivers/bluetooth/btusb.c        |   29 ++++++++++++++
 drivers/bluetooth/btusb.h        |   31 +++++++++++++++
 drivers/bluetooth/btusb_intel.c  |   81 ++++++++++++++++++++++++++++++++++++++
 include/net/bluetooth/hci_core.h |    6 +++
 net/bluetooth/hci_core.c         |   16 ++++++++
 6 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 drivers/bluetooth/btusb.h
 create mode 100644 drivers/bluetooth/btusb_intel.c

diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 4afae20..57c7fe2 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_BT_HCIBT3C)	+= bt3c_cs.o
 obj-$(CONFIG_BT_HCIBLUECARD)	+= bluecard_cs.o
 obj-$(CONFIG_BT_HCIBTUART)	+= btuart_cs.o
 
-obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o
+obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o btusb_intel.o
 obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o
 
 obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index f637c25..029c5b7 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -27,6 +27,8 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
+#include "btusb.h"
+
 #define VERSION "0.6"
 
 static bool ignore_dga;
@@ -47,6 +49,8 @@ static struct usb_driver btusb_driver;
 #define BTUSB_BROKEN_ISOC	0x20
 #define BTUSB_WRONG_SCO_MTU	0x40
 #define BTUSB_ATH3012		0x80
+#define BTUSB_INTEL			0x100
+#define BTUSB_DEV_INIT		0x8000
 
 static struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -190,6 +194,9 @@ static struct usb_device_id blacklist_table[] = {
 	/* Frontline ComProbe Bluetooth Sniffer */
 	{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
 
+	/* Intel Bluetooth device */
+	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_DEV_INIT | BTUSB_INTEL },
+
 	{ }	/* Terminating entry */
 };
 
@@ -235,6 +242,17 @@ struct btusb_data {
 	int suspend_count;
 };
 
+struct btusb_vendor_dev {
+	unsigned long info;
+	int (*vsdev_init)(struct hci_dev *hdev);
+	void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
+};
+
+static struct btusb_vendor_dev vendor_dev[] = {
+	{ BTUSB_INTEL, btusb_intel_init, btusb_intel_event },
+	{ 0 }
+};
+
 static int inc_tx(struct btusb_data *data)
 {
 	unsigned long flags;
@@ -1069,6 +1087,17 @@ static int btusb_probe(struct usb_interface *intf,
 		}
 	}
 
+	/* vendor specific device initialization */
+	if (id->driver_info & BTUSB_DEV_INIT) {
+		for (i = 0; vendor_dev[i].info; i++) {
+			if (id->driver_info & vendor_dev[i].info) {
+				hdev->vsdev_init = vendor_dev[i].vsdev_init;
+				hdev->vsdev_event = vendor_dev[i].vsdev_event;
+				break;
+			}
+		}
+	}
+
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		hci_free_dev(hdev);
diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h
new file mode 100644
index 0000000..f03040f
--- /dev/null
+++ b/drivers/bluetooth/btusb.h
@@ -0,0 +1,31 @@
+/*
+ *
+ *  Generic Bluetooth USB driver
+ *
+ *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __BTUSB_H
+#define __BTUSB_H
+
+/* Intel specific device initialization callbacks */
+int btusb_intel_init(struct hci_dev *hdev);
+void btusb_intel_event(struct hci_dev *hdev, struct sk_buff *skb);
+
+#endif /* __BTUSB_H */
diff --git a/drivers/bluetooth/btusb_intel.c b/drivers/bluetooth/btusb_intel.c
new file mode 100644
index 0000000..51c019d
--- /dev/null
+++ b/drivers/bluetooth/btusb_intel.c
@@ -0,0 +1,81 @@
+/*
+ *
+ *  Bluetooth USB Driver - Intel device initialization
+ *
+ *  Copyright (C) 2012  Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "btusb.h"
+
+/* patch state */
+enum intel_patch_state {
+	INTEL_PATCH_PRE,
+	INTEL_PATCH_VER,
+	INTEL_PATCH_PREP_PATCH,
+	INTEL_PATCH_PATCHING,
+	INTEL_PATCH_POST,
+	INTEL_PATCH_COMPLETED,
+	INTEL_PATCH_ERROR
+};
+
+struct intel_patch_data {
+	struct hci_dev		*hdev;
+
+	int			state;
+};
+
+int btusb_intel_init(struct hci_dev *hdev)
+{
+	struct intel_patch_data *data;
+
+	BT_INFO("Intel BT USB: device initialization - patching device");
+
+	/* initialize the data structure */
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		BT_ERR("failed to allocate the memory for patch data");
+		return -ENOMEM;
+	}
+	hdev->vsdev_init_data = data;
+
+	data->hdev = hdev;
+	data->state = INTEL_PATCH_PRE;
+
+	kfree(data);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btusb_intel_init);
+
+void btusb_intel_event(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct intel_patch_data *data = hdev->vsdev_init_data;
+
+	BT_DBG("Intel BT USB: HCI event handler state=%d", data->state);
+
+	del_timer(&hdev->cmd_timer);
+	atomic_set(&hdev->cmd_cnt, 1);
+	kfree_skb(skb);
+	return;
+}
+EXPORT_SYMBOL_GPL(btusb_intel_event);
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6a3337e..cde0ddd 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -275,6 +275,12 @@ struct hci_dev {
 	int (*send)(struct sk_buff *skb);
 	void (*notify)(struct hci_dev *hdev, unsigned int evt);
 	int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+
+	int  			vsdev_init_completed;
+	void 			*vsdev_init_data;
+
+	int  (*vsdev_init)(struct hci_dev *hdev);
+	void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
 };
 
 struct hci_conn {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e407051..4b23812 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -685,6 +685,17 @@ int hci_dev_open(__u16 dev)
 		set_bit(HCI_INIT, &hdev->flags);
 		hdev->init_last_cmd = 0;
 
+		if (hdev->vsdev_init && !hdev->vsdev_init_completed) {
+			ret = hdev->vsdev_init(hdev);
+			BT_DBG("vsdev_init completed: %d", ret);
+			/* set this flag so vsdev_init() execute only once */
+			hdev->vsdev_init_completed = 1;
+			/* make sure to use generic event handler */
+			hdev->vsdev_event = NULL;
+			if (ret < 0)
+				goto done;
+		}
+
 		ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
 
 		if (lmp_host_le_capable(hdev))
@@ -2119,6 +2130,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
 
 	return 0;
 }
+EXPORT_SYMBOL(hci_send_cmd);
 
 /* Get data from the previously sent command */
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
@@ -2800,7 +2812,11 @@ static void hci_rx_work(struct work_struct *work)
 		switch (bt_cb(skb)->pkt_type) {
 		case HCI_EVENT_PKT:
 			BT_DBG("%s Event packet", hdev->name);
+			/* send packet to device init event handler */
+			if (hdev->vsdev_init_completed || !hdev->vsdev_event)
 			hci_event_packet(hdev, skb);
+			else
+				hdev->vsdev_event(hdev, skb);
 			break;
 
 		case HCI_ACLDATA_PKT:
-- 
1.7.9.5


[-- Attachment #2: Type: text/html, Size: 56148 bytes --]

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC 1/3] Bluetooth: Add initial skeleton for Intel BT USB support
@ 2012-09-10 22:35 Tedd Ho-Jeong An
  2012-09-17 13:37 ` Marcel Holtmann
  0 siblings, 1 reply; 3+ messages in thread
From: Tedd Ho-Jeong An @ 2012-09-10 22:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, albert.o.ho

From: Tedd Ho-Jeong An <tedd.an@intel.com>

This patch adds an initial skeleton for Intel BT USB support.

- Extension to execute of vendor specific initialization at early stage
  which is before normal BT controller initialization and after the USB
  is initialized.

- Add initial skeleton of Intel specific initialization functions

- Add Intel BT USB VID/PID

Outpu from /sys/kernel/debug/usb/devices:

T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=8087 ProdID=07dc Rev= 0.00
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=81(I) Atr=03(Int.) MxPS=  64 Ivl=1ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
I:  If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
I:  If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
I:  If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
I:  If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
I:  If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms

Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
---
 drivers/bluetooth/Makefile       |    2 +-
 drivers/bluetooth/btusb.c        |   29 ++++++++++++++
 drivers/bluetooth/btusb.h        |   31 +++++++++++++++
 drivers/bluetooth/btusb_intel.c  |   81 ++++++++++++++++++++++++++++++++++++++
 include/net/bluetooth/hci_core.h |    6 +++
 net/bluetooth/hci_core.c         |   16 ++++++++
 6 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 drivers/bluetooth/btusb.h
 create mode 100644 drivers/bluetooth/btusb_intel.c

diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 4afae20..57c7fe2 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_BT_HCIBT3C)	+= bt3c_cs.o
 obj-$(CONFIG_BT_HCIBLUECARD)	+= bluecard_cs.o
 obj-$(CONFIG_BT_HCIBTUART)	+= btuart_cs.o
 
-obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o
+obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o btusb_intel.o
 obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o
 
 obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index f637c25..029c5b7 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -27,6 +27,8 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
+#include "btusb.h"
+
 #define VERSION "0.6"
 
 static bool ignore_dga;
@@ -47,6 +49,8 @@ static struct usb_driver btusb_driver;
 #define BTUSB_BROKEN_ISOC	0x20
 #define BTUSB_WRONG_SCO_MTU	0x40
 #define BTUSB_ATH3012		0x80
+#define BTUSB_INTEL			0x100
+#define BTUSB_DEV_INIT		0x8000
 
 static struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -190,6 +194,9 @@ static struct usb_device_id blacklist_table[] = {
 	/* Frontline ComProbe Bluetooth Sniffer */
 	{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
 
+	/* Intel Bluetooth device */
+	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_DEV_INIT | BTUSB_INTEL },
+
 	{ }	/* Terminating entry */
 };
 
@@ -235,6 +242,17 @@ struct btusb_data {
 	int suspend_count;
 };
 
+struct btusb_vendor_dev {
+	unsigned long info;
+	int (*vsdev_init)(struct hci_dev *hdev);
+	void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
+};
+
+static struct btusb_vendor_dev vendor_dev[] = {
+	{ BTUSB_INTEL, btusb_intel_init, btusb_intel_event },
+	{ 0 }
+};
+
 static int inc_tx(struct btusb_data *data)
 {
 	unsigned long flags;
@@ -1069,6 +1087,17 @@ static int btusb_probe(struct usb_interface *intf,
 		}
 	}
 
+	/* vendor specific device initialization */
+	if (id->driver_info & BTUSB_DEV_INIT) {
+		for (i = 0; vendor_dev[i].info; i++) {
+			if (id->driver_info & vendor_dev[i].info) {
+				hdev->vsdev_init = vendor_dev[i].vsdev_init;
+				hdev->vsdev_event = vendor_dev[i].vsdev_event;
+				break;
+			}
+		}
+	}
+
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		hci_free_dev(hdev);
diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h
new file mode 100644
index 0000000..f03040f
--- /dev/null
+++ b/drivers/bluetooth/btusb.h
@@ -0,0 +1,31 @@
+/*
+ *
+ *  Generic Bluetooth USB driver
+ *
+ *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __BTUSB_H
+#define __BTUSB_H
+
+/* Intel specific device initialization callbacks */
+int btusb_intel_init(struct hci_dev *hdev);
+void btusb_intel_event(struct hci_dev *hdev, struct sk_buff *skb);
+
+#endif /* __BTUSB_H */
diff --git a/drivers/bluetooth/btusb_intel.c b/drivers/bluetooth/btusb_intel.c
new file mode 100644
index 0000000..51c019d
--- /dev/null
+++ b/drivers/bluetooth/btusb_intel.c
@@ -0,0 +1,81 @@
+/*
+ *
+ *  Bluetooth USB Driver - Intel device initialization
+ *
+ *  Copyright (C) 2012  Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "btusb.h"
+
+/* patch state */
+enum intel_patch_state {
+	INTEL_PATCH_PRE,
+	INTEL_PATCH_VER,
+	INTEL_PATCH_PREP_PATCH,
+	INTEL_PATCH_PATCHING,
+	INTEL_PATCH_POST,
+	INTEL_PATCH_COMPLETED,
+	INTEL_PATCH_ERROR
+};
+
+struct intel_patch_data {
+	struct hci_dev		*hdev;
+
+	int			state;
+};
+
+int btusb_intel_init(struct hci_dev *hdev)
+{
+	struct intel_patch_data *data;
+
+	BT_INFO("Intel BT USB: device initialization - patching device");
+
+	/* initialize the data structure */
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		BT_ERR("failed to allocate the memory for patch data");
+		return -ENOMEM;
+	}
+	hdev->vsdev_init_data = data;
+
+	data->hdev = hdev;
+	data->state = INTEL_PATCH_PRE;
+
+	kfree(data);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btusb_intel_init);
+
+void btusb_intel_event(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct intel_patch_data *data = hdev->vsdev_init_data;
+
+	BT_DBG("Intel BT USB: HCI event handler state=%d", data->state);
+
+	del_timer(&hdev->cmd_timer);
+	atomic_set(&hdev->cmd_cnt, 1);
+	kfree_skb(skb);
+	return;
+}
+EXPORT_SYMBOL_GPL(btusb_intel_event);
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 6a3337e..cde0ddd 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -275,6 +275,12 @@ struct hci_dev {
 	int (*send)(struct sk_buff *skb);
 	void (*notify)(struct hci_dev *hdev, unsigned int evt);
 	int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+
+	int  			vsdev_init_completed;
+	void 			*vsdev_init_data;
+
+	int  (*vsdev_init)(struct hci_dev *hdev);
+	void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
 };
 
 struct hci_conn {
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e407051..4b23812 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -685,6 +685,17 @@ int hci_dev_open(__u16 dev)
 		set_bit(HCI_INIT, &hdev->flags);
 		hdev->init_last_cmd = 0;
 
+		if (hdev->vsdev_init && !hdev->vsdev_init_completed) {
+			ret = hdev->vsdev_init(hdev);
+			BT_DBG("vsdev_init completed: %d", ret);
+			/* set this flag so vsdev_init() execute only once */
+			hdev->vsdev_init_completed = 1;
+			/* make sure to use generic event handler */
+			hdev->vsdev_event = NULL;
+			if (ret < 0)
+				goto done;
+		}
+
 		ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
 
 		if (lmp_host_le_capable(hdev))
@@ -2119,6 +2130,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
 
 	return 0;
 }
+EXPORT_SYMBOL(hci_send_cmd);
 
 /* Get data from the previously sent command */
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
@@ -2800,7 +2812,11 @@ static void hci_rx_work(struct work_struct *work)
 		switch (bt_cb(skb)->pkt_type) {
 		case HCI_EVENT_PKT:
 			BT_DBG("%s Event packet", hdev->name);
+			/* send packet to device init event handler */
+			if (hdev->vsdev_init_completed || !hdev->vsdev_event)
 			hci_event_packet(hdev, skb);
+			else
+				hdev->vsdev_event(hdev, skb);
 			break;
 
 		case HCI_ACLDATA_PKT:
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [RFC 1/3] Bluetooth: Add initial skeleton for Intel BT USB support
  2012-09-10 22:35 [RFC 1/3] Bluetooth: Add initial skeleton for Intel BT USB support Tedd Ho-Jeong An
@ 2012-09-17 13:37 ` Marcel Holtmann
  0 siblings, 0 replies; 3+ messages in thread
From: Marcel Holtmann @ 2012-09-17 13:37 UTC (permalink / raw)
  To: Tedd Ho-Jeong An; +Cc: linux-bluetooth, albert.o.ho

Hi Tedd,

> This patch adds an initial skeleton for Intel BT USB support.
> 
> - Extension to execute of vendor specific initialization at early stage
>   which is before normal BT controller initialization and after the USB
>   is initialized.
> 
> - Add initial skeleton of Intel specific initialization functions
> 
> - Add Intel BT USB VID/PID
> 
> Outpu from /sys/kernel/debug/usb/devices:
> 
> T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
> D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=8087 ProdID=07dc Rev= 0.00
> C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=81(I) Atr=03(Int.) MxPS=  64 Ivl=1ms
> E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> I:  If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> I:  If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> I:  If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> I:  If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> I:  If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> 
> Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
> ---
>  drivers/bluetooth/Makefile       |    2 +-
>  drivers/bluetooth/btusb.c        |   29 ++++++++++++++
>  drivers/bluetooth/btusb.h        |   31 +++++++++++++++
>  drivers/bluetooth/btusb_intel.c  |   81 ++++++++++++++++++++++++++++++++++++++
>  include/net/bluetooth/hci_core.h |    6 +++
>  net/bluetooth/hci_core.c         |   16 ++++++++
>  6 files changed, 164 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/bluetooth/btusb.h
>  create mode 100644 drivers/bluetooth/btusb_intel.c

I am strictly against mixing this all into one patch. Core changes need
to be separate, btusb general changes need to be separate and then Intel
btusb specific code as well.

> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
> index 4afae20..57c7fe2 100644
> --- a/drivers/bluetooth/Makefile
> +++ b/drivers/bluetooth/Makefile
> @@ -12,7 +12,7 @@ obj-$(CONFIG_BT_HCIBT3C)	+= bt3c_cs.o
>  obj-$(CONFIG_BT_HCIBLUECARD)	+= bluecard_cs.o
>  obj-$(CONFIG_BT_HCIBTUART)	+= btuart_cs.o
>  
> -obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o
> +obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o btusb_intel.o
>  obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o

It sounds like a bad idea hiding the btusb_intel.ko kernel module behing
the generic option for btusb.ko module.
 
>  obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index f637c25..029c5b7 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -27,6 +27,8 @@
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
>  
> +#include "btusb.h"
> +
>  #define VERSION "0.6"
>  
>  static bool ignore_dga;
> @@ -47,6 +49,8 @@ static struct usb_driver btusb_driver;
>  #define BTUSB_BROKEN_ISOC	0x20
>  #define BTUSB_WRONG_SCO_MTU	0x40
>  #define BTUSB_ATH3012		0x80
> +#define BTUSB_INTEL			0x100
> +#define BTUSB_DEV_INIT		0x8000
>  
>  static struct usb_device_id btusb_table[] = {
>  	/* Generic Bluetooth USB device */
> @@ -190,6 +194,9 @@ static struct usb_device_id blacklist_table[] = {
>  	/* Frontline ComProbe Bluetooth Sniffer */
>  	{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
>  
> +	/* Intel Bluetooth device */
> +	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_DEV_INIT | BTUSB_INTEL },
> +
>  	{ }	/* Terminating entry */
>  };
>  
> @@ -235,6 +242,17 @@ struct btusb_data {
>  	int suspend_count;
>  };
>  
> +struct btusb_vendor_dev {
> +	unsigned long info;
> +	int (*vsdev_init)(struct hci_dev *hdev);
> +	void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
> +};
> +
> +static struct btusb_vendor_dev vendor_dev[] = {
> +	{ BTUSB_INTEL, btusb_intel_init, btusb_intel_event },
> +	{ 0 }
> +};
> +

This does not scale. We can not do it like this. Especially since I also
already have seen some Broadcom dongles requiring special init handling.
And there is still the Atheros stuff that keep popping up.

It seems like that we might better follow a similar approach here that
usbnet and its drivers does.

We can have a library like btusb that provides btusb_probe and
btusb_disconnect. And then have a btusb_driver_info specific structure
that allows overwriting certain setup/fixup functions that we then
trigger from btusb or from the Bluetooth core.

This would also mean that btusb_intel.ko can become its own module with
its own usb_driver table. Which would avoid cluttering btusb.c with
vendor specific details all over the place.

Assuming that the USB driver matching uses VID/PID matches over
interface matches and does not go via module loading order.

If not, then USB_DEVICE_INFO(0xe0, 0x01, 0x01) might get us in trouble.
And then we need come up with our own btusb_driver. Same idea, just a
little bit more work.

Regards

Marcel



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-09-17 13:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-10 22:35 [RFC 1/3] Bluetooth: Add initial skeleton for Intel BT USB support Tedd Ho-Jeong An
2012-09-17 13:37 ` Marcel Holtmann
  -- strict thread matches above, loose matches on Subject: below --
2012-09-10 21:29 Tedd Ho-Jeong An

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).