Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v2 1/2] Bluetooth: Move discovery state check inside hci_dev_lock()
From: Jaganath Kanakkassery @ 2012-12-21 12:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jaganath Kanakkassery
In-Reply-To: <1356094225-12706-1-git-send-email-jaganath.k@samsung.com>

After checking the discovery state, if other thread modifies it
then it will be overwritten by the assignment in the first thread.

Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
---
 net/bluetooth/hci_event.c |    9 ++++-----
 net/bluetooth/mgmt.c      |    4 ----
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 9fb656b..e248e7c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1106,14 +1106,13 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 
 		clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
 
+		hci_dev_lock(hdev);
 		if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
-		    hdev->discovery.state == DISCOVERY_FINDING) {
+		    hdev->discovery.state == DISCOVERY_FINDING)
 			mgmt_interleaved_discovery(hdev);
-		} else {
-			hci_dev_lock(hdev);
+		else
 			hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
-			hci_dev_unlock(hdev);
-		}
+		hci_dev_unlock(hdev);
 
 		break;
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 729fb8c..d6c0d78 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2289,14 +2289,10 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev)
 
 	BT_DBG("%s", hdev->name);
 
-	hci_dev_lock(hdev);
-
 	err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE);
 	if (err < 0)
 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
 
-	hci_dev_unlock(hdev);
-
 	return err;
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 0/2] Fix stop discovery not handled if discovery state is STARTING
From: Jaganath Kanakkassery @ 2012-12-21 12:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jaganath Kanakkassery

If user calls stop_discovery when the discovery state is STARTING, then it fails.
In this scenario discovery will continue. 

This patch handles stop_discovery even if state is STARTING

v2---> Incorporated Gustavo's comments

Jaganath Kanakkassery (2):
  Bluetooth: Move discovery state check inside hci_dev_lock()
  Bluetooth: Fix stop discovery while in STARTING state

 include/net/bluetooth/hci_core.h |    2 ++
 net/bluetooth/hci_event.c        |   23 ++++++++++++++++-------
 net/bluetooth/mgmt.c             |   35 ++++++++++++++++++++++++++++++-----
 3 files changed, 48 insertions(+), 12 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* Re: [RFC/RFT] rtk_btusb: Bluetooth driver for Realtek RTL8723AE combo device
From: Oliver Neukum @ 2012-12-21 12:00 UTC (permalink / raw)
  To: Larry Finger
  Cc: linville, Marcel Holtmann, Gustavo Padovan, Johan Hedberg,
	linux-wireless, linux-bluetooth, Champion Chen
In-Reply-To: <1356058371-17152-1-git-send-email-Larry.Finger@lwfinger.net>

On Thursday 20 December 2012 20:52:51 Larry Finger wrote:
> This new driver works with the RTL8723AE wireless/BT combo device. The
> corresponding firmware has been submitted to linux-firmware.

Very well. However, you cannot simply duplicate the whole code
of btusb without very good reason. The patch as is is absolutely
inacceptable.

	Regards
		Oliver

^ permalink raw reply

* newbie question: how to confirm bluetooth version a system support
From: 明 @ 2012-12-21 10:33 UTC (permalink / raw)
  To: linux-bluetooth

1.  bluetooth 4.0  ?=  bluetooth 4.0 LE , i.e. iPhone4s supports
bluetooth 4.0, does that mean it support bluetooth 4.0 LE ?
     I know that bluetooth 3.0 != bluetooth 3.0 HS

2.  my android phone project, msm7225A platform , bluetooth chip is
WCN2243 .  which version can be defined?

3.  in short ,  from hardware and software aspects, how to confirm
bluetooth version (when using bluez stack)

it is really a problem that confusing me for a long time.
appreciate anyone give some help.

^ permalink raw reply

* Re: [RFC/RFT] rtk_btusb: Bluetooth driver for Realtek RTL8723AE combo device
From: Marcel Holtmann @ 2012-12-21  7:17 UTC (permalink / raw)
  To: Larry Finger
  Cc: linville, Gustavo Padovan, Johan Hedberg, linux-wireless,
	linux-bluetooth, Champion Chen
In-Reply-To: <1356058371-17152-1-git-send-email-Larry.Finger@lwfinger.net>

Hi Larry,

> This new driver works with the RTL8723AE wireless/BT combo device. The
> corresponding firmware has been submitted to linux-firmware.
> 
> Signed-off-by: Champion Chen <champion_chen@realsil.com.cn>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
>  drivers/bluetooth/Kconfig     |   10 +
>  drivers/bluetooth/Makefile    |    1 +
>  drivers/bluetooth/rtk_btusb.c | 1649 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1660 insertions(+)
>  create mode 100644 drivers/bluetooth/rtk_btusb.c
>
> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
> index e9f203e..efd3766 100644
> --- a/drivers/bluetooth/Kconfig
> +++ b/drivers/bluetooth/Kconfig
> @@ -241,4 +241,14 @@ config BT_WILINK
>  
>  	  Say Y here to compile support for Texas Instrument's WiLink7 driver
>  	  into the kernel or say M to compile it as module.
> +
> +config BT_RTKUSB
> +	tristate "Realtek BT driver for RTL8723AE"
> +	select FW_LOADER
> +	help
> +	  This enables the Bluetooth driver for the Realtek RTL8723AE Wifi/BT
> +	  combo device.
> +
> +	  Say Y here to compile support for these devices into the kernel
> +	  or say M to build it as a module.
>  endmenu
> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
> index 4afae20..167ccc0 100644
> --- a/drivers/bluetooth/Makefile
> +++ b/drivers/bluetooth/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
>  obj-$(CONFIG_BT_MRVL)		+= btmrvl.o
>  obj-$(CONFIG_BT_MRVL_SDIO)	+= btmrvl_sdio.o
>  obj-$(CONFIG_BT_WILINK)		+= btwilink.o
> +obj-$(CONFIG_BT_RTKUSB)		+= rtk_btusb.o
>  
>  btmrvl-y			:= btmrvl_main.o
>  btmrvl-$(CONFIG_DEBUG_FS)	+= btmrvl_debugfs.o
> diff --git a/drivers/bluetooth/rtk_btusb.c b/drivers/bluetooth/rtk_btusb.c
> new file mode 100644
> index 0000000..31c128a
> --- /dev/null
> +++ b/drivers/bluetooth/rtk_btusb.c
> @@ -0,0 +1,1650 @@
> +/*
> + *
> + *  Realtek Bluetooth USB driver
> + *
> + *  Copyright (C) 2012-2015  Edward Bian <edward_bian@realsil.com.cn>
> + *

NAK. This is pretty much a blunt copy of btusb.c and not acceptable.

And last time I checked, I own a big portion of btusb.c and I find it
funny how that copyright just got replaced. 2015? Really? Time travel
much lately ;)

There have been patches for hdev->setup stage and discussions on
creating a mini-driver approach on the mailing list. That is the way to
go.

Regards

Marcel



^ permalink raw reply

* [RFC/RFT] rtk_btusb: Bluetooth driver for Realtek RTL8723AE combo device
From: Larry Finger @ 2012-12-21  2:52 UTC (permalink / raw)
  To: linville, Marcel Holtmann, Gustavo Padovan, Johan Hedberg
  Cc: linux-wireless, Larry Finger, linux-bluetooth, Champion Chen

This new driver works with the RTL8723AE wireless/BT combo device. The
corresponding firmware has been submitted to linux-firmware.

Signed-off-by: Champion Chen <champion_chen@realsil.com.cn>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 drivers/bluetooth/Kconfig     |   10 +
 drivers/bluetooth/Makefile    |    1 +
 drivers/bluetooth/rtk_btusb.c | 1649 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1660 insertions(+)
 create mode 100644 drivers/bluetooth/rtk_btusb.c

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index e9f203e..efd3766 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -241,4 +241,14 @@ config BT_WILINK
 
 	  Say Y here to compile support for Texas Instrument's WiLink7 driver
 	  into the kernel or say M to compile it as module.
+
+config BT_RTKUSB
+	tristate "Realtek BT driver for RTL8723AE"
+	select FW_LOADER
+	help
+	  This enables the Bluetooth driver for the Realtek RTL8723AE Wifi/BT
+	  combo device.
+
+	  Say Y here to compile support for these devices into the kernel
+	  or say M to build it as a module.
 endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 4afae20..167ccc0 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
 obj-$(CONFIG_BT_MRVL)		+= btmrvl.o
 obj-$(CONFIG_BT_MRVL_SDIO)	+= btmrvl_sdio.o
 obj-$(CONFIG_BT_WILINK)		+= btwilink.o
+obj-$(CONFIG_BT_RTKUSB)		+= rtk_btusb.o
 
 btmrvl-y			:= btmrvl_main.o
 btmrvl-$(CONFIG_DEBUG_FS)	+= btmrvl_debugfs.o
diff --git a/drivers/bluetooth/rtk_btusb.c b/drivers/bluetooth/rtk_btusb.c
new file mode 100644
index 0000000..31c128a
--- /dev/null
+++ b/drivers/bluetooth/rtk_btusb.c
@@ -0,0 +1,1650 @@
+/*
+ *
+ *  Realtek Bluetooth USB driver
+ *
+ *  Copyright (C) 2012-2015  Edward Bian <edward_bian@realsil.com.cn>
+ *
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+#include <linux/completion.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#define VERSION "0.8"
+
+static struct usb_driver btusb_driver;
+#if 1
+#define RTKBT_DBG(fmt, arg...) pr_info("rtk_btusb: " fmt "\n" , ## arg)
+#else
+#define RTKBT_DBG(fmt, arg...)
+#endif
+
+
+/*******************************/
+#include <linux/version.h>
+#include <linux/pm_runtime.h>
+#define HDEV_BUS		(hdev->bus)
+#define USB_RPM			1
+
+#define GET_DRV_DATA(x)		hci_get_drvdata(x)
+
+
+#define BTUSB_RPM		0	/*1 SS enable; 0 SS disable */
+#define LOAD_CONFIG		0
+#define URB_CANCELING_DELAY_MS	10   /*  Added by Realtek */
+
+static int patch_add(struct usb_interface *intf);
+static void patch_remove(struct usb_interface *intf);
+static int download_patch(struct usb_interface *intf);
+static int set_btoff(struct usb_interface *intf);
+
+
+static struct usb_device_id btusb_table[] = {
+	{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
+			 USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor = 0x0bda,
+	  .bInterfaceClass = 0xe0,
+	  .bInterfaceSubClass = 0x01,
+	  .bInterfaceProtocol = 0x01 },
+	{ }
+};
+/*******************************/
+
+
+MODULE_DEVICE_TABLE(usb, btusb_table);
+
+
+#define BTUSB_MAX_ISOC_FRAMES		10
+#define BTUSB_INTR_RUNNING		0
+#define BTUSB_BULK_RUNNING		1
+#define BTUSB_ISOC_RUNNING		2
+#define BTUSB_SUSPENDING		3
+#define BTUSB_DID_ISO_RESUME		4
+
+struct btusb_data {
+	struct hci_dev       *hdev;
+	struct usb_device    *udev;
+	struct usb_interface *intf;
+	struct usb_interface *isoc;
+
+	spinlock_t lock;
+
+	unsigned long flags;
+
+	struct work_struct work;
+	struct work_struct waker;
+
+	struct usb_anchor tx_anchor;
+	struct usb_anchor intr_anchor;
+	struct usb_anchor bulk_anchor;
+	struct usb_anchor isoc_anchor;
+	struct usb_anchor deferred;
+	int tx_in_flight;
+	spinlock_t txlock;
+
+	struct usb_endpoint_descriptor *intr_ep;
+	struct usb_endpoint_descriptor *bulk_tx_ep;
+	struct usb_endpoint_descriptor *bulk_rx_ep;
+	struct usb_endpoint_descriptor *isoc_tx_ep;
+	struct usb_endpoint_descriptor *isoc_rx_ep;
+
+	__u8 cmdreq_type;
+
+	unsigned int sco_num;
+	int isoc_altsetting;
+	int suspend_count;
+};
+
+static int inc_tx(struct btusb_data *data)
+{
+	unsigned long flags;
+	int rv;
+
+	spin_lock_irqsave(&data->txlock, flags);
+	rv = test_bit(BTUSB_SUSPENDING, &data->flags);
+	if (!rv)
+		data->tx_in_flight++;
+	spin_unlock_irqrestore(&data->txlock, flags);
+
+	return rv;
+}
+
+static void btusb_intr_complete(struct urb *urb)
+{
+	struct hci_dev *hdev = urb->context;
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	int err;
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return;
+
+	if (urb->status == 0) {
+		hdev->stat.byte_rx += urb->actual_length;
+
+		if (hci_recv_fragment(hdev, HCI_EVENT_PKT,
+		    urb->transfer_buffer, urb->actual_length) < 0) {
+			BT_ERR("%s corrupted event packet", hdev->name);
+			hdev->stat.err_rx++;
+		}
+	}
+
+	if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
+		return;
+
+	usb_mark_last_busy(data->udev);
+	usb_anchor_urb(urb, &data->intr_anchor);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0) {
+		/* -EPERM: urb is being killed;
+		 * -ENODEV: device got disconnected */
+		if (err != -EPERM && err != -ENODEV)
+			BT_ERR("btusb_intr_complete %s urb %p failed to resubmit (%d)",
+				hdev->name, urb, -err);
+		usb_unanchor_urb(urb);
+	}
+}
+
+static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	struct urb *urb;
+	unsigned char *buf;
+	unsigned int pipe;
+	int err, size;
+
+	BT_DBG("%s", hdev->name);
+
+	if (!data->intr_ep)
+		return -ENODEV;
+
+	urb = usb_alloc_urb(0, mem_flags);
+	if (!urb)
+		return -ENOMEM;
+
+	size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
+
+	buf = kmalloc(size, mem_flags);
+	if (!buf) {
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+
+	pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress);
+
+	usb_fill_int_urb(urb, data->udev, pipe, buf, size,
+			 btusb_intr_complete, hdev,
+			 data->intr_ep->bInterval);
+
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	usb_anchor_urb(urb, &data->intr_anchor);
+
+	err = usb_submit_urb(urb, mem_flags);
+	if (err < 0) {
+		BT_ERR("btusb_submit_intr_urb %s urb %p submission failed (%d)",
+			hdev->name, urb, -err);
+		usb_unanchor_urb(urb);
+	}
+
+	usb_free_urb(urb);
+
+	return err;
+}
+
+static void btusb_bulk_complete(struct urb *urb)
+{
+	struct hci_dev *hdev = urb->context;
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	int err;
+
+	BT_DBG("%s urb %p status %d count %d", hdev->name,
+		urb, urb->status, urb->actual_length);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return;
+
+	if (urb->status == 0) {
+		hdev->stat.byte_rx += urb->actual_length;
+
+		if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT,
+		    urb->transfer_buffer, urb->actual_length) < 0) {
+			BT_ERR("%s corrupted ACL packet", hdev->name);
+			hdev->stat.err_rx++;
+		}
+	}
+
+	if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
+		return;
+
+	usb_anchor_urb(urb, &data->bulk_anchor);
+	usb_mark_last_busy(data->udev);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0) {
+		/* -EPERM: urb is being killed;
+		 * -ENODEV: device got disconnected */
+		if (err != -EPERM && err != -ENODEV)
+			BT_ERR("btusb_bulk_complete %s urb %p failed to resubmit (%d)",
+				hdev->name, urb, -err);
+		usb_unanchor_urb(urb);
+	}
+}
+
+static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	struct urb *urb;
+	unsigned char *buf;
+	unsigned int pipe;
+	int err, size = HCI_MAX_FRAME_SIZE;
+
+	BT_DBG("%s", hdev->name);
+
+	if (!data->bulk_rx_ep)
+		return -ENODEV;
+
+	urb = usb_alloc_urb(0, mem_flags);
+	if (!urb)
+		return -ENOMEM;
+
+	buf = kmalloc(size, mem_flags);
+	if (!buf) {
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+
+	pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
+
+	usb_fill_bulk_urb(urb, data->udev, pipe,
+			  buf, size, btusb_bulk_complete, hdev);
+
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	usb_mark_last_busy(data->udev);
+	usb_anchor_urb(urb, &data->bulk_anchor);
+
+	err = usb_submit_urb(urb, mem_flags);
+	if (err < 0) {
+		BT_ERR("btusb_submit_bulk_urb %s urb %p submission failed (%d)",
+			hdev->name, urb, -err);
+		usb_unanchor_urb(urb);
+	}
+
+	usb_free_urb(urb);
+
+	return err;
+}
+
+static void btusb_isoc_complete(struct urb *urb)
+{
+	struct hci_dev *hdev = urb->context;
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	int i, err;
+
+	BT_DBG("%s urb %p status %d count %d", hdev->name,
+		urb, urb->status, urb->actual_length);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return;
+
+	if (urb->status == 0) {
+		for (i = 0; i < urb->number_of_packets; i++) {
+			unsigned int offset = urb->iso_frame_desc[i].offset;
+			unsigned int length;
+
+			length = urb->iso_frame_desc[i].actual_length;
+			if (urb->iso_frame_desc[i].status)
+				continue;
+
+			hdev->stat.byte_rx += length;
+
+			if (hci_recv_fragment(hdev, HCI_SCODATA_PKT,
+						urb->transfer_buffer + offset,
+								length) < 0) {
+				BT_ERR("%s corrupted SCO packet", hdev->name);
+				hdev->stat.err_rx++;
+			}
+		}
+	}
+
+	if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
+		return;
+
+	usb_anchor_urb(urb, &data->isoc_anchor);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0) {
+		/* -EPERM: urb is being killed;
+		 * -ENODEV: device got disconnected */
+		if (err != -EPERM && err != -ENODEV)
+			BT_ERR("btusb_isoc_complete %s urb %p failed to resubmit (%d)",
+			       hdev->name, urb, -err);
+		usb_unanchor_urb(urb);
+	}
+}
+
+static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
+{
+	int i, offset = 0;
+
+	BT_DBG("len %d mtu %d", len, mtu);
+
+	for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu;
+					i++, offset += mtu, len -= mtu) {
+		urb->iso_frame_desc[i].offset = offset;
+		urb->iso_frame_desc[i].length = mtu;
+	}
+
+	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
+		urb->iso_frame_desc[i].offset = offset;
+		urb->iso_frame_desc[i].length = len;
+		i++;
+	}
+
+	urb->number_of_packets = i;
+}
+
+static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	struct urb *urb;
+	unsigned char *buf;
+	unsigned int pipe;
+	int err, size;
+
+	BT_DBG("%s", hdev->name);
+
+	if (!data->isoc_rx_ep)
+		return -ENODEV;
+
+	urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, mem_flags);
+	if (!urb)
+		return -ENOMEM;
+
+	size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
+			   BTUSB_MAX_ISOC_FRAMES;
+
+	buf = kmalloc(size, mem_flags);
+	if (!buf) {
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+
+	pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
+
+	urb->dev      = data->udev;
+	urb->pipe     = pipe;
+	urb->context  = hdev;
+	urb->complete = btusb_isoc_complete;
+	urb->interval = data->isoc_rx_ep->bInterval;
+
+	urb->transfer_flags  = URB_FREE_BUFFER | URB_ISO_ASAP;
+	urb->transfer_buffer = buf;
+	urb->transfer_buffer_length = size;
+
+	__fill_isoc_descriptor(urb, size,
+			le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
+
+	usb_anchor_urb(urb, &data->isoc_anchor);
+
+	err = usb_submit_urb(urb, mem_flags);
+	if (err < 0) {
+		BT_ERR("btusb_submit_isoc_urb %s urb %p submission failed (%d)",
+		       hdev->name, urb, -err);
+		usb_unanchor_urb(urb);
+	}
+
+	usb_free_urb(urb);
+
+	return err;
+}
+
+static void btusb_tx_complete(struct urb *urb)
+{
+	struct sk_buff *skb = urb->context;
+	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		goto done;
+
+	if (!urb->status)
+		hdev->stat.byte_tx += urb->transfer_buffer_length;
+	else
+		hdev->stat.err_tx++;
+
+done:
+	spin_lock(&data->txlock);
+	data->tx_in_flight--;
+	spin_unlock(&data->txlock);
+
+	kfree(urb->setup_packet);
+
+	kfree_skb(skb);
+}
+
+static void btusb_isoc_tx_complete(struct urb *urb)
+{
+	struct sk_buff *skb = urb->context;
+	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+
+	BT_DBG("btusb_isoc_tx_complete %s urb %p status %d count %d",
+	       hdev->name, urb, urb->status, urb->actual_length);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		goto done;
+
+	if (!urb->status)
+		hdev->stat.byte_tx += urb->transfer_buffer_length;
+	else
+		hdev->stat.err_tx++;
+
+done:
+	kfree(urb->setup_packet);
+
+	kfree_skb(skb);
+}
+
+static int btusb_open(struct hci_dev *hdev)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	int err;
+
+	err = usb_autopm_get_interface(data->intf);
+	if (err < 0)
+		return err;
+
+	data->intf->needs_remote_wakeup = 1;
+	RTKBT_DBG("%s start pm_usage_cnt(0x%x)", __func__,
+		  atomic_read(&(data->intf->pm_usage_cnt)));
+
+	/*******************************/
+	if (0 == atomic_read(&hdev->promisc)) {
+		RTKBT_DBG("btusb_open hdev->promisc == 0");
+		err = -1;
+	}
+	err = download_patch(data->intf);
+	if (err < 0)
+		goto failed;
+	/*******************************/
+
+	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
+		goto done;
+
+	if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
+		goto done;
+
+	err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
+	if (err < 0)
+		goto failed;
+
+	err = btusb_submit_bulk_urb(hdev, GFP_KERNEL);
+	if (err < 0) {
+		mdelay(URB_CANCELING_DELAY_MS);      /*  Added by Realtek */
+		usb_kill_anchored_urbs(&data->intr_anchor);
+		goto failed;
+	}
+
+	set_bit(BTUSB_BULK_RUNNING, &data->flags);
+	btusb_submit_bulk_urb(hdev, GFP_KERNEL);
+
+done:
+	usb_autopm_put_interface(data->intf);
+	RTKBT_DBG("%s end  pm_usage_cnt(0x%x)", __func__,
+		  atomic_read(&(data->intf->pm_usage_cnt)));
+
+	return 0;
+
+failed:
+	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+	clear_bit(HCI_RUNNING, &hdev->flags);
+	usb_autopm_put_interface(data->intf);
+	RTKBT_DBG("%s failed  pm_usage_cnt(0x%x)", __func__,
+		  atomic_read(&(data->intf->pm_usage_cnt)));
+	return err;
+}
+
+static void btusb_stop_traffic(struct btusb_data *data)
+{
+	mdelay(URB_CANCELING_DELAY_MS);    /*  Added by Realtek */
+	usb_kill_anchored_urbs(&data->intr_anchor);
+	usb_kill_anchored_urbs(&data->bulk_anchor);
+	usb_kill_anchored_urbs(&data->isoc_anchor);
+}
+
+static int btusb_close(struct hci_dev *hdev)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	int i, err;
+
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+		return 0;
+
+	RTKBT_DBG("btusb_close");
+	/*******************************/
+	for (i = 0; i < NUM_REASSEMBLY; i++) {
+		if (hdev->reassembly[i])	{
+			kfree_skb(hdev->reassembly[i]);
+			hdev->reassembly[i] = NULL;
+			RTKBT_DBG("%s free ressembly i =%d", __func__, i);
+		}
+	}
+	/*******************************/
+	cancel_work_sync(&data->work);
+	cancel_work_sync(&data->waker);
+
+	clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+	clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+
+	btusb_stop_traffic(data);
+	err = usb_autopm_get_interface(data->intf);
+	if (err < 0)
+		goto failed;
+
+	data->intf->needs_remote_wakeup = 0;
+	usb_autopm_put_interface(data->intf);
+
+failed:
+	mdelay(URB_CANCELING_DELAY_MS);     /*  Added by Realtek */
+	usb_scuttle_anchored_urbs(&data->deferred);
+	return 0;
+}
+
+static int btusb_flush(struct hci_dev *hdev)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+
+	RTKBT_DBG("%s add delay ", __func__);
+	mdelay(URB_CANCELING_DELAY_MS);     /*  Added by Realtek */
+	usb_kill_anchored_urbs(&data->tx_anchor);
+
+	return 0;
+}
+
+static int btusb_send_frame(struct sk_buff *skb)
+{
+	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	struct usb_ctrlrequest *dr;
+	struct urb *urb;
+	unsigned int pipe;
+	int err;
+
+	BT_DBG("%s", hdev->name);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return -EBUSY;
+
+	switch (bt_cb(skb)->pkt_type) {
+	case HCI_COMMAND_PKT:
+		urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!urb)
+			return -ENOMEM;
+
+		dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+		if (!dr) {
+			usb_free_urb(urb);
+			return -ENOMEM;
+		}
+
+		dr->bRequestType = data->cmdreq_type;
+		dr->bRequest     = 0;
+		dr->wIndex       = 0;
+		dr->wValue       = 0;
+		dr->wLength      = __cpu_to_le16(skb->len);
+
+		pipe = usb_sndctrlpipe(data->udev, 0x00);
+
+		usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
+				skb->data, skb->len, btusb_tx_complete, skb);
+
+		hdev->stat.cmd_tx++;
+		break;
+
+	case HCI_ACLDATA_PKT:
+		if (!data->bulk_tx_ep)
+			return -ENODEV;
+
+		urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!urb)
+			return -ENOMEM;
+
+		pipe = usb_sndbulkpipe(data->udev,
+					data->bulk_tx_ep->bEndpointAddress);
+
+		usb_fill_bulk_urb(urb, data->udev, pipe,
+				skb->data, skb->len, btusb_tx_complete, skb);
+
+		hdev->stat.acl_tx++;
+		break;
+
+	case HCI_SCODATA_PKT:
+		if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1)
+			return -ENODEV;
+
+		urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC);
+		if (!urb)
+			return -ENOMEM;
+
+		pipe = usb_sndisocpipe(data->udev,
+					data->isoc_tx_ep->bEndpointAddress);
+
+		usb_fill_int_urb(urb, data->udev, pipe,
+				skb->data, skb->len, btusb_isoc_tx_complete,
+				skb, data->isoc_tx_ep->bInterval);
+
+		urb->transfer_flags  = URB_ISO_ASAP;
+
+		__fill_isoc_descriptor(urb, skb->len,
+				le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
+
+		hdev->stat.sco_tx++;
+		goto skip_waking;
+
+	default:
+		return -EILSEQ;
+	}
+
+	err = inc_tx(data);
+	if (err) {
+		usb_anchor_urb(urb, &data->deferred);
+		schedule_work(&data->waker);
+		err = 0;
+		goto done;
+	}
+
+skip_waking:
+	usb_anchor_urb(urb, &data->tx_anchor);
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err < 0) {
+		BT_ERR("btusb_send_frame %s urb %p submission failed",
+		       hdev->name, urb);
+		kfree(urb->setup_packet);
+		usb_unanchor_urb(urb);
+	} else {
+		usb_mark_last_busy(data->udev);
+	}
+	usb_free_urb(urb);
+
+done:
+	return err;
+}
+
+static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+
+	BT_DBG("%s evt %d", hdev->name, evt);
+	RTKBT_DBG("btusb_notify : %s evt %d", hdev->name, evt);
+
+	if (hdev->conn_hash.sco_num != data->sco_num) {
+		data->sco_num = hdev->conn_hash.sco_num;
+		schedule_work(&data->work);
+	}
+}
+
+static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
+{
+	struct btusb_data *data = GET_DRV_DATA(hdev);
+	struct usb_interface *intf = data->isoc;
+	struct usb_endpoint_descriptor *ep_desc;
+	int i, err;
+
+	if (!data->isoc)
+		return -ENODEV;
+
+	err = usb_set_interface(data->udev, 1, altsetting);
+	if (err < 0) {
+		BT_ERR("%s setting interface failed (%d)", hdev->name, -err);
+		return err;
+	}
+
+	data->isoc_altsetting = altsetting;
+
+	data->isoc_tx_ep = NULL;
+	data->isoc_rx_ep = NULL;
+
+	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+		if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
+			data->isoc_tx_ep = ep_desc;
+			continue;
+		}
+
+		if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
+			data->isoc_rx_ep = ep_desc;
+			continue;
+		}
+	}
+
+	if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
+		BT_ERR("%s invalid SCO descriptors", hdev->name);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void btusb_work(struct work_struct *work)
+{
+	struct btusb_data *data = container_of(work, struct btusb_data, work);
+	struct hci_dev *hdev = data->hdev;
+	int err;
+
+	if (hdev->conn_hash.sco_num > 0) {
+		if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
+			err = usb_autopm_get_interface(data->isoc ? data->isoc :
+						       data->intf);
+			if (err < 0) {
+				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+				/*  Delay added by Realtek */
+				mdelay(URB_CANCELING_DELAY_MS);
+				usb_kill_anchored_urbs(&data->isoc_anchor);
+				return;
+			}
+
+			set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
+		}
+		if (data->isoc_altsetting != 2) {
+			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+			mdelay(URB_CANCELING_DELAY_MS);  /*  Added by Realtek */
+			usb_kill_anchored_urbs(&data->isoc_anchor);
+
+			if (__set_isoc_interface(hdev, 2) < 0)
+				return;
+		}
+
+		if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+			if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
+				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+			else
+				btusb_submit_isoc_urb(hdev, GFP_KERNEL);
+		}
+	} else {
+		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		mdelay(URB_CANCELING_DELAY_MS);      /*  Added by Realtek */
+		usb_kill_anchored_urbs(&data->isoc_anchor);
+
+		__set_isoc_interface(hdev, 0);
+		if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
+			usb_autopm_put_interface(data->isoc ? data->isoc :
+						 data->intf);
+	}
+}
+
+static void btusb_waker(struct work_struct *work)
+{
+	struct btusb_data *data = container_of(work, struct btusb_data, waker);
+	int err;
+
+	err = usb_autopm_get_interface(data->intf);
+	RTKBT_DBG("%s start  pm_usage_cnt(0x%x)", __func__,
+		  atomic_read(&(data->intf->pm_usage_cnt)));
+	if (err < 0)
+		return;
+
+	usb_autopm_put_interface(data->intf);
+	RTKBT_DBG("%s end  pm_usage_cnt(0x%x)", __func__,
+		  atomic_read(&(data->intf->pm_usage_cnt)));
+}
+
+static int btusb_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	struct usb_endpoint_descriptor *ep_desc;
+	struct btusb_data *data;
+	struct hci_dev *hdev;
+	int i, err, flag1, flag2;
+	struct usb_device *udev;
+	udev = interface_to_usbdev(intf);
+
+	/* interface numbers are hardcoded in the spec */
+	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+		return -ENODEV;
+
+	/*******************************/
+	flag1 = device_can_wakeup(&udev->dev);
+	flag2 = device_may_wakeup(&udev->dev);
+	RTKBT_DBG("btusb_probe 1 ========== can_wakeup =%x	 flag2 =%x",
+		  flag1, flag2);
+	device_wakeup_disable(&udev->dev);
+	flag1 = device_can_wakeup(&udev->dev);
+	flag2 = device_may_wakeup(&udev->dev);
+	RTKBT_DBG("wakeup_disable ========== can_wakeup =%x	 flag2 =%x",
+		  flag1, flag2);
+	err = patch_add(intf);
+	if (err < 0)
+		return -1;
+	/*******************************/
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+
+	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+		ep_desc = &intf->cur_altsetting->endpoint[i].desc;
+
+		if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
+			data->intr_ep = ep_desc;
+			continue;
+		}
+
+		if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
+			data->bulk_tx_ep = ep_desc;
+			continue;
+		}
+
+		if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
+			data->bulk_rx_ep = ep_desc;
+			continue;
+		}
+	}
+
+	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
+		kfree(data);
+		return -ENODEV;
+	}
+
+	data->cmdreq_type = USB_TYPE_CLASS;
+
+	data->udev = interface_to_usbdev(intf);
+	data->intf = intf;
+
+	spin_lock_init(&data->lock);
+
+	INIT_WORK(&data->work, btusb_work);
+	INIT_WORK(&data->waker, btusb_waker);
+	spin_lock_init(&data->txlock);
+
+	init_usb_anchor(&data->tx_anchor);
+	init_usb_anchor(&data->intr_anchor);
+	init_usb_anchor(&data->bulk_anchor);
+	init_usb_anchor(&data->isoc_anchor);
+	init_usb_anchor(&data->deferred);
+
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		kfree(data);
+		return -ENOMEM;
+	}
+
+	HDEV_BUS = HCI_USB;
+
+	data->hdev = hdev;
+
+	SET_HCIDEV_DEV(hdev, &intf->dev);
+
+	hdev->open     = btusb_open;
+	hdev->close    = btusb_close;
+	hdev->flush    = btusb_flush;
+	hdev->send     = btusb_send_frame;
+	hdev->notify   = btusb_notify;
+
+
+	hci_set_drvdata(hdev, data);
+
+	/* Interface numbers are hardcoded in the specification */
+	data->isoc = usb_ifnum_to_if(data->udev, 1);
+
+	if (data->isoc) {
+		err = usb_driver_claim_interface(&btusb_driver,
+						 data->isoc, data);
+		if (err < 0) {
+			hci_free_dev(hdev);
+			kfree(data);
+			return err;
+		}
+	}
+
+	err = hci_register_dev(hdev);
+	if (err < 0) {
+		hci_free_dev(hdev);
+		kfree(data);
+		return err;
+	}
+
+	usb_set_intfdata(intf, data);
+
+	return 0;
+}
+
+static void btusb_disconnect(struct usb_interface *intf)
+{
+	struct btusb_data *data = usb_get_intfdata(intf);
+	struct hci_dev *hdev;
+	struct usb_device *udev;
+	udev = interface_to_usbdev(intf);
+
+	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+		return;
+
+	if (!data)
+		return;
+
+	RTKBT_DBG("btusb_disconnect");
+	/*******************************/
+	patch_remove(intf);
+	/*******************************/
+
+	hdev = data->hdev;
+
+	usb_set_intfdata(data->intf, NULL);
+
+	if (data->isoc)
+		usb_set_intfdata(data->isoc, NULL);
+
+	hci_unregister_dev(hdev);
+
+	if (intf == data->isoc)
+		usb_driver_release_interface(&btusb_driver, data->intf);
+	else if (data->isoc)
+		usb_driver_release_interface(&btusb_driver, data->isoc);
+
+	hci_free_dev(hdev);
+	kfree(data);
+}
+
+#ifdef CONFIG_PM
+static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct btusb_data *data = usb_get_intfdata(intf);
+
+	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+		return 0;
+
+	/*******************************/
+	RTKBT_DBG("btusb_suspend message.event = 0x%x, data->suspend_count =%d",
+		  message.event, data->suspend_count);
+	if (!test_bit(HCI_RUNNING, &data->hdev->flags)) {
+		RTKBT_DBG("btusb_suspend-----bt is off");
+		set_btoff(data->intf);
+	}
+	/*******************************/
+
+	if (data->suspend_count++)
+		return 0;
+
+	spin_lock_irq(&data->txlock);
+	if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
+		set_bit(BTUSB_SUSPENDING, &data->flags);
+		spin_unlock_irq(&data->txlock);
+	} else {
+		spin_unlock_irq(&data->txlock);
+		data->suspend_count--;
+		return -EBUSY;
+	}
+
+	cancel_work_sync(&data->work);
+
+	btusb_stop_traffic(data);
+	mdelay(URB_CANCELING_DELAY_MS);      /*  Added by Realtek */
+	usb_kill_anchored_urbs(&data->tx_anchor);
+
+	return 0;
+}
+
+static void play_deferred(struct btusb_data *data)
+{
+	struct urb *urb;
+	int err;
+
+	while ((urb = usb_get_from_anchor(&data->deferred))) {
+
+		/************************************/
+		usb_anchor_urb(urb, &data->tx_anchor);
+		err = usb_submit_urb(urb, GFP_ATOMIC);
+		if (err < 0) {
+			BT_ERR("play_deferred urb %p submission failed",  urb);
+			kfree(urb->setup_packet);
+			usb_unanchor_urb(urb);
+		} else {
+			usb_mark_last_busy(data->udev);
+		}
+		usb_free_urb(urb);
+		/************************************/
+		data->tx_in_flight++;
+	}
+	mdelay(URB_CANCELING_DELAY_MS);     /*  Added by Realtek */
+	usb_scuttle_anchored_urbs(&data->deferred);
+}
+
+static int btusb_resume(struct usb_interface *intf)
+{
+	struct btusb_data *data = usb_get_intfdata(intf);
+	struct hci_dev *hdev = data->hdev;
+	int err = 0;
+
+	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+		return 0;
+
+
+	/*******************************/
+	RTKBT_DBG("btusb_resume data->suspend_count =%d", data->suspend_count);
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+		RTKBT_DBG("btusb_resume-----bt is off, download patch");
+		download_patch(intf);
+	} else {
+		RTKBT_DBG("btusb_resume,----bt is on");
+	}
+	/*******************************/
+	if (--data->suspend_count)
+		return 0;
+
+	if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
+		err = btusb_submit_intr_urb(hdev, GFP_NOIO);
+		if (err < 0) {
+			clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+			goto failed;
+		}
+	}
+
+	if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
+		err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
+		if (err < 0) {
+			clear_bit(BTUSB_BULK_RUNNING, &data->flags);
+			goto failed;
+		}
+
+		btusb_submit_bulk_urb(hdev, GFP_NOIO);
+	}
+
+	if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
+		if (btusb_submit_isoc_urb(hdev, GFP_NOIO) < 0)
+			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
+		else
+			btusb_submit_isoc_urb(hdev, GFP_NOIO);
+	}
+
+	spin_lock_irq(&data->txlock);
+	play_deferred(data);
+	clear_bit(BTUSB_SUSPENDING, &data->flags);
+	spin_unlock_irq(&data->txlock);
+	schedule_work(&data->work);
+
+	return 0;
+
+failed:
+	mdelay(URB_CANCELING_DELAY_MS);      /*  Added by Realtek */
+	usb_scuttle_anchored_urbs(&data->deferred);
+/* done: */
+	spin_lock_irq(&data->txlock);
+	clear_bit(BTUSB_SUSPENDING, &data->flags);
+	spin_unlock_irq(&data->txlock);
+
+	return err;
+}
+#endif
+
+static struct usb_driver btusb_driver = {
+	.name		= "rtk_btusb",
+	.probe		= btusb_probe,
+	.disconnect	= btusb_disconnect,
+#ifdef CONFIG_PM
+	.suspend	= btusb_suspend,
+	.resume		= btusb_resume,
+#endif
+	.id_table	= btusb_table,
+	.supports_autosuspend = 1,
+};
+
+static int __init btusb_init(void)
+{
+	RTKBT_DBG("Realtek Bluetooth USB driver ver %s", VERSION);
+
+	return usb_register(&btusb_driver);
+}
+
+static void __exit btusb_exit(void)
+{
+	usb_deregister(&btusb_driver);
+}
+
+module_init(btusb_init);
+module_exit(btusb_exit);
+
+MODULE_AUTHOR("Edward Bian <edward_bian@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek Bluetooth USB driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("rtl_bt/rtl8723a.bin");
+
+/*******************************
+**    Reasil patch code
+********************************/
+
+
+#include <linux/firmware.h>
+#include <linux/suspend.h>
+#include <net/bluetooth/hci.h>
+
+
+#define CMD_CMP_EVT		0x0e
+#define PKT_LEN			300
+#define MSG_TO			1000
+#define PATCH_SEG_MAX	252
+#define DATA_END		0x80
+#define DOWNLOAD_OPCODE	0xfc20
+#define BTOFF_OPCODE	0xfc28
+#define TRUE			1
+#define FALSE			0
+#define CMD_HDR_LEN		sizeof(struct hci_command_hdr)
+#define EVT_HDR_LEN		sizeof(struct hci_event_hdr)
+#define CMD_CMP_LEN		sizeof(struct hci_ev_cmd_complete)
+
+
+enum rtk_endpoit {
+	CTRL_EP = 0,
+	INTR_EP = 1,
+	BULK_EP = 2,
+	ISOC_EP = 3
+};
+
+struct patch_info {
+	uint16_t	prod_id;
+	uint16_t	lmp_sub;
+	char		*patch_name;
+	char		*config_name;
+	uint8_t		*fw_cache;
+	int		fw_len;
+};
+
+struct xchange_data {
+	struct dev_data	*dev_entry;
+	int pipe_in, pipe_out;
+	uint8_t send_pkt[PKT_LEN];
+	uint8_t rcv_pkt[PKT_LEN];
+	struct hci_command_hdr *cmd_hdr;
+	struct hci_event_hdr *evt_hdr;
+	struct hci_ev_cmd_complete *cmd_cmp;
+	uint8_t *req_para, *rsp_para;
+	uint8_t *fw_data;
+	int pkt_len, fw_len;
+};
+
+struct dev_data {
+	struct list_head	list_node;
+	struct usb_interface	*intf;
+	struct usb_device	*udev;
+	struct notifier_block	pm_notifier;
+	struct patch_info	*patch_entry;
+	struct xchange_data	xdata;
+	struct completion firmware_loading_complete;
+	const struct firmware *fw;
+};
+
+struct download_cp {
+	uint8_t index;
+	uint8_t data[PATCH_SEG_MAX];
+} __packed;
+
+struct download_rp {
+	uint8_t status;
+	uint8_t index;
+} __packed;
+
+
+static struct dev_data *dev_data_find(struct usb_interface *intf);
+static struct patch_info *get_patch_entry(struct usb_device *udev);
+static int rtkbt_pm_notify(struct notifier_block *notifier, ulong pm_event,
+			   void *unused);
+static int load_firmware(struct dev_data *dev_entry, uint8_t **buff);
+static void init_xdata(struct xchange_data *xdata, struct dev_data *dev_entry);
+static int check_fw_version(struct xchange_data *xdata);
+static int get_firmware(struct xchange_data *xdata);
+static int download_data(struct xchange_data *xdata);
+static int send_hci_cmd(struct xchange_data *xdata);
+static int rcv_hci_evt(struct xchange_data *xdata);
+
+
+static struct patch_info patch_table[] = {
+	{0, 0x1200, "rtl_bt/rtl8723a.bin", "rtk8723_bt_config", NULL, 0}
+};
+
+static LIST_HEAD(dev_data_list);
+
+
+static int patch_add(struct usb_interface *intf)
+{
+	struct dev_data	*dev_entry;
+	struct usb_device *udev;
+
+	RTKBT_DBG("patch_add");
+	dev_entry = dev_data_find(intf);
+	if (NULL != dev_entry)
+		return -1;
+
+	udev = interface_to_usbdev(intf);
+#if BTUSB_RPM
+	RTKBT_DBG("auto suspend is enabled");
+	usb_enable_autosuspend(udev);
+	pm_runtime_set_autosuspend_delay(&(udev->dev), 2000);
+#endif
+
+	dev_entry = kzalloc(sizeof(struct dev_data), GFP_KERNEL);
+	dev_entry->intf = intf;
+	dev_entry->udev = udev;
+	dev_entry->pm_notifier.notifier_call = rtkbt_pm_notify;
+	dev_entry->patch_entry = get_patch_entry(udev);
+	list_add(&dev_entry->list_node, &dev_data_list);
+	register_pm_notifier(&dev_entry->pm_notifier);
+
+	return 0;
+}
+
+static void patch_remove(struct usb_interface *intf)
+{
+	struct dev_data *dev_entry;
+	struct usb_device *udev;
+
+	udev = interface_to_usbdev(intf);
+#if BTUSB_RPM
+	usb_disable_autosuspend(udev);
+#endif
+
+	dev_entry = dev_data_find(intf);
+	if (NULL == dev_entry)
+		return;
+
+	RTKBT_DBG("patch_remove");
+	list_del(&dev_entry->list_node);
+	unregister_pm_notifier(&dev_entry->pm_notifier);
+	kfree(dev_entry);
+}
+
+static int download_patch(struct usb_interface *intf)
+{
+	struct dev_data		*dev_entry;
+	uint8_t			*fw_buf;
+	int			ret_val;
+
+	RTKBT_DBG("download_patch start");
+	dev_entry = dev_data_find(intf);
+	if (NULL == dev_entry) {
+		ret_val = -1;
+		RTKBT_DBG("NULL == dev_entry");
+		goto patch_end;
+	}
+
+	init_xdata(&dev_entry->xdata, dev_entry);
+	ret_val = check_fw_version(&dev_entry->xdata);
+	if (ret_val != 0)
+		goto patch_end;
+
+	ret_val = get_firmware(&dev_entry->xdata);
+	if (ret_val < 0) {
+		RTKBT_DBG("get_firmware failed!");
+		goto patch_end;
+	}
+	fw_buf = dev_entry->xdata.fw_data;
+
+	ret_val = download_data(&dev_entry->xdata);
+	if (ret_val < 0) {
+		RTKBT_DBG("download_data failed!");
+		goto patch_fail;
+	}
+
+	ret_val = check_fw_version(&dev_entry->xdata);
+	if (ret_val <= 0) {
+		ret_val = -1;
+		goto patch_fail;
+	}
+
+	ret_val = 0;
+patch_fail:
+	kfree(fw_buf);
+patch_end:
+	RTKBT_DBG("Rtk patch end %d", ret_val);
+	return ret_val;
+}
+
+static int set_btoff(struct usb_interface *intf)
+{
+	struct dev_data *dev_entry;
+	int ret_val;
+
+	RTKBT_DBG("set_btoff");
+	dev_entry = dev_data_find(intf);
+	if (NULL == dev_entry)
+		return -1;
+
+	init_xdata(&dev_entry->xdata, dev_entry);
+	dev_entry->xdata.cmd_hdr->opcode = cpu_to_le16(BTOFF_OPCODE);
+	dev_entry->xdata.cmd_hdr->plen = 1;
+	dev_entry->xdata.pkt_len = CMD_HDR_LEN + 1;
+	dev_entry->xdata.send_pkt[CMD_HDR_LEN] = 1;
+
+	ret_val = send_hci_cmd(&dev_entry->xdata);
+	if (ret_val < 0)
+		return ret_val;
+
+	ret_val = rcv_hci_evt(&dev_entry->xdata);
+	if (ret_val < 0)
+		return ret_val;
+
+	RTKBT_DBG("set_btoff done");
+	return 0;
+}
+
+static struct dev_data *dev_data_find(struct usb_interface *intf)
+{
+	struct dev_data *dev_entry;
+
+	list_for_each_entry(dev_entry, &dev_data_list, list_node) {
+		if (dev_entry->intf == intf)
+			return dev_entry;
+	}
+
+	return NULL;
+}
+
+static struct patch_info *get_patch_entry(struct usb_device *udev)
+{
+	struct patch_info	*patch_entry;
+	uint16_t	pid;
+
+	patch_entry = patch_table;
+	pid = le16_to_cpu(udev->descriptor.idProduct);
+	while (pid != patch_entry->prod_id) {
+		if (0 == patch_entry->prod_id)
+			break;
+		patch_entry++;
+	}
+
+	return patch_entry;
+}
+
+static int rtkbt_pm_notify(struct notifier_block *notifier, ulong pm_event,
+		    void *unused)
+{
+	struct dev_data	*dev_entry;
+	struct patch_info	*patch_entry;
+	struct usb_device *udev;
+
+	dev_entry = container_of(notifier, struct dev_data, pm_notifier);
+	patch_entry = dev_entry->patch_entry;
+	udev = dev_entry->udev;
+	RTKBT_DBG("rtkbt_pm_notify pm_event =%ld", pm_event);
+	switch (pm_event) {
+	case PM_SUSPEND_PREPARE:
+	case PM_HIBERNATION_PREPARE:
+		patch_entry->fw_len = load_firmware(dev_entry,
+						    &patch_entry->fw_cache);
+		if (patch_entry->fw_len <= 0) {
+			RTKBT_DBG("rtkbt_pm_notify return NOTIFY_BAD");
+			return NOTIFY_BAD;
+		}
+
+		if (!device_may_wakeup(&udev->dev)) {
+			dev_entry->intf->needs_binding = 1;
+			RTKBT_DBG("remote wakeup not support, set intf->needs_binding = 1");
+		}
+		break;
+
+	case PM_POST_SUSPEND:
+	case PM_POST_HIBERNATION:
+	case PM_POST_RESTORE:
+		if (patch_entry->fw_len > 0) {
+			kfree(patch_entry->fw_cache);
+			patch_entry->fw_cache = NULL;
+			patch_entry->fw_len = 0;
+		}
+#if BTUSB_RPM
+		usb_disable_autosuspend(udev);
+		usb_enable_autosuspend(udev);
+		pm_runtime_set_autosuspend_delay(&(udev->dev), 2000);
+#endif
+		break;
+
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static void bt_fw_cb(const struct firmware *firmware, void *context)
+{
+	struct dev_data *dev_entry = context;
+
+	dev_entry->fw = firmware;
+	if (!firmware)
+		pr_err("In callback routine, firmware file not available\n");
+	complete(&dev_entry->firmware_loading_complete);
+}
+
+static int load_firmware(struct dev_data *dev_entry, uint8_t **buff)
+{
+#if LOAD_CONFIG
+	const struct firmware *fw;
+#endif
+	struct usb_device *udev;
+	struct patch_info *patch_entry;
+	char *fw_name;
+	int fw_len = 0, ret_val;
+
+	udev = dev_entry->udev;
+	init_completion(&dev_entry->firmware_loading_complete);
+	patch_entry = dev_entry->patch_entry;
+	fw_name = patch_entry->patch_name;
+	RTKBT_DBG("Reading firmware file %s", fw_name);
+	ret_val = request_firmware_nowait(THIS_MODULE, 1, fw_name, &udev->dev,
+					  GFP_KERNEL, dev_entry, bt_fw_cb);
+	if (ret_val < 0)
+		goto fw_fail;
+
+	wait_for_completion(&dev_entry->firmware_loading_complete);
+	if (!dev_entry->fw)
+		goto fw_fail;
+	*buff = kzalloc(dev_entry->fw->size, GFP_KERNEL);
+	if (NULL == *buff)
+		goto alloc_fail;
+	memcpy(*buff, dev_entry->fw->data, dev_entry->fw->size);
+	fw_len = dev_entry->fw->size;
+
+#if LOAD_CONFIG
+	release_firmware(dev_entry->fw);
+	fw_name = patch_entry->config_name;
+	ret_val = request_firmware(&fw, fw_name, &udev->dev);
+	if (ret_val < 0) {
+		fw_len = 0;
+		kfree(*buff);
+		*buff = NULL;
+		goto fw_fail;
+	}
+
+	*buff = krealloc(*buff, fw_len + fw->size, GFP_KERNEL);
+	if (NULL == *buff) {
+		fw_len = 0;
+		release_firmware(fw);
+		goto fw_fail;
+	}
+	memcpy(*buff + fw_len, fw->data, fw->size);
+	fw_len += fw->size;
+#endif
+
+alloc_fail:
+	release_firmware(dev_entry->fw);
+fw_fail:
+	return fw_len;
+}
+
+static void init_xdata(struct xchange_data *xdata, struct dev_data *dev_entry)
+{
+	memset(xdata, 0, sizeof(struct xchange_data));
+	xdata->dev_entry = dev_entry;
+	xdata->pipe_in = usb_rcvintpipe(dev_entry->udev, INTR_EP);
+	xdata->pipe_out = usb_sndctrlpipe(dev_entry->udev, CTRL_EP);
+	xdata->cmd_hdr = (struct hci_command_hdr *)(xdata->send_pkt);
+	xdata->evt_hdr = (struct hci_event_hdr *)(xdata->rcv_pkt);
+	xdata->cmd_cmp = (struct hci_ev_cmd_complete *)(xdata->rcv_pkt +
+							EVT_HDR_LEN);
+	xdata->req_para = xdata->send_pkt + CMD_HDR_LEN;
+	xdata->rsp_para = xdata->rcv_pkt + EVT_HDR_LEN + CMD_CMP_LEN;
+}
+
+static int check_fw_version(struct xchange_data *xdata)
+{
+	struct hci_rp_read_local_version *read_ver_rsp;
+	struct patch_info *patch_entry;
+	int ret_val;
+
+	xdata->cmd_hdr->opcode = cpu_to_le16(HCI_OP_READ_LOCAL_VERSION);
+	xdata->cmd_hdr->plen = 0;
+	xdata->pkt_len = CMD_HDR_LEN;
+
+	ret_val = send_hci_cmd(xdata);
+	if (ret_val < 0)
+		goto version_end;
+
+	ret_val = rcv_hci_evt(xdata);
+	if (ret_val < 0)
+		goto version_end;
+
+	patch_entry = xdata->dev_entry->patch_entry;
+	read_ver_rsp = (struct hci_rp_read_local_version *)(xdata->rsp_para);
+	RTKBT_DBG("check_fw_version : read_ver_rsp->lmp_subver = 0x%x",
+		  le16_to_cpu(read_ver_rsp->lmp_subver));
+	if (patch_entry->lmp_sub != le16_to_cpu(read_ver_rsp->lmp_subver))
+		return 1;
+
+	ret_val = 0;
+version_end:
+	return ret_val;
+}
+
+static int get_firmware(struct xchange_data *xdata)
+{
+	struct dev_data	*dev_entry;
+	struct patch_info *patch_entry;
+
+	dev_entry = xdata->dev_entry;
+	patch_entry = dev_entry->patch_entry;
+	if (patch_entry->fw_len > 0) {
+		xdata->fw_data = kzalloc(patch_entry->fw_len, GFP_KERNEL);
+		if (NULL == xdata->fw_data)
+			return -ENOMEM;
+		memcpy(xdata->fw_data, patch_entry->fw_cache,
+		       patch_entry->fw_len);
+		xdata->fw_len = patch_entry->fw_len;
+	} else {
+		xdata->fw_len = load_firmware(dev_entry, &xdata->fw_data);
+		if (xdata->fw_len <= 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int download_data(struct xchange_data *xdata)
+{
+	struct download_cp *cmd_para;
+	struct download_rp *evt_para;
+	uint8_t *pcur;
+	int pkt_len, frag_num, frag_len;
+	int i, ret_val;
+
+	cmd_para = (struct download_cp *)xdata->req_para;
+	evt_para = (struct download_rp *)xdata->rsp_para;
+	pcur = xdata->fw_data;
+	pkt_len = CMD_HDR_LEN + sizeof(struct download_cp);
+	frag_num = xdata->fw_len / PATCH_SEG_MAX + 1;
+	frag_len = PATCH_SEG_MAX;
+
+	for (i = 0; i < frag_num; i++) {
+		cmd_para->index = i;
+		if (i == (frag_num - 1)) {
+			cmd_para->index |= DATA_END;
+			frag_len = xdata->fw_len % PATCH_SEG_MAX;
+			pkt_len -= (PATCH_SEG_MAX - frag_len);
+		}
+		xdata->cmd_hdr->opcode = cpu_to_le16(DOWNLOAD_OPCODE);
+		xdata->cmd_hdr->plen = sizeof(uint8_t) + frag_len;
+		xdata->pkt_len = pkt_len;
+		memcpy(cmd_para->data, pcur, frag_len);
+
+		ret_val = send_hci_cmd(xdata);
+		if (ret_val < 0)
+			return ret_val;
+
+		ret_val = rcv_hci_evt(xdata);
+		if (ret_val < 0)
+			return ret_val;
+		if (0 != evt_para->status)
+			return -1;
+
+		pcur += PATCH_SEG_MAX;
+	}
+
+	return xdata->fw_len;
+}
+
+static int send_hci_cmd(struct xchange_data *xdata)
+{
+	int ret_val;
+
+	ret_val = usb_control_msg(
+		xdata->dev_entry->udev, xdata->pipe_out,
+		0, USB_TYPE_CLASS, 0, 0,
+		(void *)(xdata->send_pkt),
+		xdata->pkt_len, MSG_TO);
+
+	return ret_val;
+}
+
+static int rcv_hci_evt(struct xchange_data *xdata)
+{
+	int ret_len, ret_val;
+	int i;   /*  Added by Realtek */
+
+	while (1) {
+
+		/*  **************************** Modifed by Realtek (begin) */
+		for (i = 0; i < 5; i++) {
+			/*  Try to send USB interrupt message 5 times. */
+			ret_val = usb_interrupt_msg(
+				xdata->dev_entry->udev, xdata->pipe_in,
+				(void *)(xdata->rcv_pkt), PKT_LEN,
+				&ret_len, MSG_TO);
+			if (ret_val >= 0)
+				break;
+		}
+		/*  **************************** Modifed by Realtek (end) */
+
+		if (ret_val < 0)
+			return ret_val;
+
+		if (CMD_CMP_EVT == xdata->evt_hdr->evt) {
+			if (xdata->cmd_hdr->opcode == xdata->cmd_cmp->opcode)
+				return ret_len;
+		}
+	}
+}
-- 
1.7.10.4

^ permalink raw reply related

* Re: [RFC 5/5] Bluetooth: AMP: Use set_bit / test_bit for amp_mgr state
From: Gustavo Padovan @ 2012-12-21  1:38 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1354885148-4677-5-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

* Andrei Emeltchenko <Andrei.Emeltchenko.news@gmail.com> [2012-12-07 14:59:08 +0200]:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> Using bit operations solves problems with multiple requests
> and clearing state.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  include/net/bluetooth/a2mp.h |    2 +-
>  net/bluetooth/a2mp.c         |    6 +++---
>  net/bluetooth/amp.c          |    4 ++--
>  3 files changed, 6 insertions(+), 6 deletions(-)

Patch 2 to 5 have been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply

* Re: [PATCH] Bluetooth: Add support for IMC Networks [13d3:3393]
From: Gustavo Padovan @ 2012-12-21  1:27 UTC (permalink / raw)
  To: AceLan Kao
  Cc: linux-bluetooth, Gustavo F. Padovan, Marcel Holtmann,
	Johan Hedberg
In-Reply-To: <1355197280-18742-1-git-send-email-acelan.kao@canonical.com>

Hi AceLan,

* AceLan Kao <acelan.kao@canonical.com> [2012-12-11 11:41:20 +0800]:

> Add support for the AR9462 chip
> 
> T:  Bus=02 Lev=02 Prnt=02 Port=04 Cnt=01 Dev#=  3 Spd=12  MxCh= 0
> D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=13d3 ProdID=3393 Rev=00.01
> 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
> I:  If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
> 
> Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
> ---
>  drivers/bluetooth/ath3k.c |    2 ++
>  drivers/bluetooth/btusb.c |    1 +
>  2 files changed, 3 insertions(+)

Patch has been applied to bluetooth.git. Thanks.

	Gustavo

^ permalink raw reply

* Re: [PATCH] Bluetooth: remove an unused variable in a header file.
From: Gustavo Padovan @ 2012-12-21  1:19 UTC (permalink / raw)
  To: Rami Rosen; +Cc: linux-bluetooth, marcel, johan.hedberg
In-Reply-To: <1355824081-5381-1-git-send-email-ramirose@gmail.com>

Hi Rami,

* Rami Rosen <ramirose@gmail.com> [2012-12-18 11:48:01 +0200]:

> This patch removes srej_queue_next from include/net/bluetooth/l2cap.h as it 
> is not used.
> 
> Signed-off-by: Rami Rosen <ramirose@gmail.com>
> ---
>  include/net/bluetooth/l2cap.h | 1 -
>  1 file changed, 1 deletion(-)

Patch has been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply

* Re: Question for setting IO capability parameter for RegisterAgent
From: Johan Hedberg @ 2012-12-20 22:35 UTC (permalink / raw)
  To: Xian Pan; +Cc: linux-bluetooth
In-Reply-To: <363D4FFF-53E5-40A3-92A4-FDA0BB60EEA6@gmail.com>

Hi Xian,

First of all, please don't top-post. It's particularly confusing when
mixed with inline quoting (which is the only quoting style you should
use on this list).

On Thu, Dec 20, 2012, Xian Pan wrote:
> Thanks for your help. It is more clear now.

I'm glad I could help.

> The 5 io capability is related to low energy smp. And the first 4 IO
> capability parameters are the same as the values for SSP.
> And the DisplayYesNo IO capability can support the numeric comparison
> mode in SSP.
> 
> right?

Right.

Johan

^ permalink raw reply

* Re: Question for setting IO capability parameter for RegisterAgent
From: Xian Pan @ 2012-12-20 21:51 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <20121220075542.GA32641@x220>

Hi Johan,

Thanks for your help. It is more clear now. The 5 io capability is related to low energy smp. And the first 4 IO capability parameters are the same as the values for SSP.
And the DisplayYesNo IO capability can support the numeric comparison mode in SSP.

right?
Thanks a lot.

BEST
Xian


On Dec 20, 2012, at 2:55 AM, Johan Hedberg wrote:

> Hi Xian,
> 
> On Wed, Dec 19, 2012, Xian Pan wrote:
>> I confuse the relationship between the 4 pairing mode in SSP with the
>> IO capability parameter for the agent. From the agent-api.txt file,
>> the capability parameter can have 5 values: DisplayOnly, DisplayYesNo,
>> KeyboardOnly, NoInputNoOutput and KeyboardDisplay. I think there are
>> only 4 pairing mode in SSP: just works, numeric comparison, out of
>> band, and passkey entry. How the 5 IO capabilities can map to those 4
>> pairing modes?
> 
> Low Energy SMP based pairing introduces the additional KeyboardDisplay
> IO capability. If you want to support LE it's recommended you provide
> that as your agent capability and BlueZ will then automatically
> downgrade it to DisplayYesNo for BR/EDR (SSP) pairing and use it as is
> for LE SMP pairing.
> 
> Johan


^ permalink raw reply

* Re: Authentication issue during connection if remote deletes link key
From: Johan Hedberg @ 2012-12-20 15:33 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth
In-Reply-To: <442B171E16C14289B5160678267146C3@sisodomain.com>

Hi Jaganath,

On Thu, Dec 20, 2012, Jaganath Kanakkassery wrote:
> I am facing one issue with authentication during profile connection.
> Two devices are there A and B which are paired.
> From B I deleted the pairing of A.
> Now from A I initiated a file transfer to B which failed during
> authentication
> since remote link key is not there.
> Please see the hcidump logs.
> < HCI Command: Authentication Requested (0x01|0x0011) plen 2
>    handle 12
> < ACL data: handle 12 flags 0x00 dlen 12
>    L2CAP(s): Disconn req: dcid 0x0046 scid 0x0040
> >HCI Event: Command Status (0x0f) plen 4
>    Authentication Requested (0x01|0x0011) status 0x00 ncmd 1
> >HCI Event: Link Key Request (0x17) plen 6
>    bdaddr BC:85:1F:74:7F:29
> < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
>    bdaddr BC:85:1F:74:7F:29 key 0E7B8C5C01CBF6CA7FF08050591C21BB
> >HCI Event: Command Complete (0x0e) plen 10
>    Link Key Request Reply (0x01|0x000b) ncmd 1
>    status 0x00 bdaddr BC:85:1F:74:7F:29
> >ACL data: handle 12 flags 0x02 dlen 12
>    L2CAP(s): Disconn rsp: dcid 0x0046 scid 0x0040
> >HCI Event: Auth Complete (0x06) plen 3
>    status 0x06 handle 12
>    Error: PIN or Key Missing
> 
> Is it controller issue or BlueZ has to take care this?
> Please let me know your opinion.

This is normal behavior. The core spec gives us two options, either fail
or ask the user if he wants to try to repair. Right now the former is
implemented and you'll need to explicitly remove the local pairing
before attempting to repair.

We could (and maybe should) implement the latter option, but we need to
be very careful since it's important that we do not drop the old link
key until the new pairing is successful and we should also refuse to
accept the new pairing if it results in a less secure link key
(unauthenticated vs authenticated) than the original one. This is to
avoid attacks from devices spoofing the address of the other (paired)
device and therefore not having the link key available.

The way this should be implemented is that upon getting the "PIN or Key
Missing" error after having responded with a positive link key reply on
our side the kernel should fire off a mgmt event to user space to
request repairing (on the D-Bus agent level I think we could probably
reuse the RequestAuthorization callback for this). If a positive
response is received from user space the kernel would proceed with a new
pairing attempt, holding on to the old link key but still giving a
negative link key reply, and then follow the procedure which I described
in the previous paragraph.

If you're interested to implement this I'd be happy to provide more
feedback and guidance. The implementation should also be extended to LE
SMP where I believe we have a similar improvement opportunity.

Johan

^ permalink raw reply

* Authentication issue during connection if remote deletes link key
From: Jaganath Kanakkassery @ 2012-12-20 14:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <50D2C258.4000908@linux.intel.com>

Hi,

I am facing one issue with authentication during profile connection.
Two devices are there A and B which are paired.
>From B I deleted the pairing of A.
Now from A I initiated a file transfer to B which failed during 
authentication
since remote link key is not there.
Please see the hcidump logs.
< HCI Command: Authentication Requested (0x01|0x0011) plen 2
    handle 12
< ACL data: handle 12 flags 0x00 dlen 12
    L2CAP(s): Disconn req: dcid 0x0046 scid 0x0040
> HCI Event: Command Status (0x0f) plen 4
    Authentication Requested (0x01|0x0011) status 0x00 ncmd 1
> HCI Event: Link Key Request (0x17) plen 6
    bdaddr BC:85:1F:74:7F:29
< HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
    bdaddr BC:85:1F:74:7F:29 key 0E7B8C5C01CBF6CA7FF08050591C21BB
> HCI Event: Command Complete (0x0e) plen 10
    Link Key Request Reply (0x01|0x000b) ncmd 1
    status 0x00 bdaddr BC:85:1F:74:7F:29
> ACL data: handle 12 flags 0x02 dlen 12
    L2CAP(s): Disconn rsp: dcid 0x0046 scid 0x0040
> HCI Event: Auth Complete (0x06) plen 3
    status 0x06 handle 12
    Error: PIN or Key Missing

But the same scenario with legacy pairing it is working fine. Pin code 
request is coming
from the controller.
< HCI Command: Authentication Requested (0x01|0x0011) plen 2
    handle 11
< ACL data: handle 11 flags 0x00 dlen 12
    L2CAP(s): Disconn req: dcid 0x0040 scid 0x0040
> HCI Event: Command Status (0x0f) plen 4
    Authentication Requested (0x01|0x0011) status 0x00 ncmd 1
> HCI Event: Link Key Request (0x17) plen 6
    bdaddr 00:80:98:E7:34:07
< HCI Command: Link Key Request Reply (0x01|0x000b) plen 22
    bdaddr 00:80:98:E7:34:07 key 0E174763D381917A5AF973E22C49A3FE
> HCI Event: Command Complete (0x0e) plen 10
    Link Key Request Reply (0x01|0x000b) ncmd 1
    status 0x00 bdaddr 00:80:98:E7:34:07
> ACL data: handle 11 flags 0x02 dlen 12
    L2CAP(s): Disconn rsp: dcid 0x0040 scid 0x0040
> HCI Event: PIN Code Request (0x16) plen 6
    bdaddr 00:80:98:E7:34:07
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 11 packets 1
< HCI Command: PIN Code Request Reply (0x01|0x000d) plen 23
    bdaddr 00:80:98:E7:34:07 len 1 pin '0'
> HCI Event: Command Complete (0x0e) plen 10
    PIN Code Request Reply (0x01|0x000d) ncmd 1
    status 0x00 bdaddr 00:80:98:E7:34:07
> HCI Event: Link Key Notification (0x18) plen 23
    bdaddr 00:80:98:E7:34:07 key 573CC496BB0C02EE461B4A18C2D758C0 type 0
    Type: Combination Key
> HCI Event: Auth Complete (0x06) plen 3
    status 0x00 handle 11


Is it controller issue or BlueZ has to take care this?
Please let me know your opinion.

Thanks,
Jaganath
 


^ permalink raw reply

* Re: Question for setting IO capability parameter for RegisterAgent
From: Marcel Holtmann @ 2012-12-20 13:59 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: Xian Pan, linux-bluetooth
In-Reply-To: <20121220075542.GA32641@x220>

Hi Johan,

> > I confuse the relationship between the 4 pairing mode in SSP with the
> > IO capability parameter for the agent. From the agent-api.txt file,
> > the capability parameter can have 5 values: DisplayOnly, DisplayYesNo,
> > KeyboardOnly, NoInputNoOutput and KeyboardDisplay. I think there are
> > only 4 pairing mode in SSP: just works, numeric comparison, out of
> > band, and passkey entry. How the 5 IO capabilities can map to those 4
> > pairing modes?
> 
> Low Energy SMP based pairing introduces the additional KeyboardDisplay
> IO capability. If you want to support LE it's recommended you provide
> that as your agent capability and BlueZ will then automatically
> downgrade it to DisplayYesNo for BR/EDR (SSP) pairing and use it as is
> for LE SMP pairing.

we should mention that in the documentation.

And additionally that "" maps to DisplayYesNo for BR/EDR and
KeyboardDisplay for LE.

Regards

Marcel



^ permalink raw reply

* Re: Authentication Rejected when pairing stereo headset
From: Andrey Voropaev @ 2012-12-20 11:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <CAFOXTden8JeVHe+SXKt7GeG+QXHP01Nku2ubQ_m88LxJ1ATUmg@mail.gmail.com>

On Thu, Dec 20, 2012 at 11:22 AM, Andrey Voropaev
<voropaev.andrey@gmail.com> wrote:
> But seems like Alsa still does not see it. I've added
>
>  pcm.bluetooth {
>   type bluetooth
>   device 00:1A:7D:25:2C:A4
>   profile "auto"
>  }
>
>
> to /etc/asound.conf, restarted alsasound, but bluetooth does not show
> up among available outputs. Well, I'm almost there. The Skype has
> "bluetooth" in the list of devices and it works. Just mplayer does not
> want to work with option
>
>  -ao alsa:device=bluetooth

Sorry. I've found the solution.
https://wiki.archlinux.org/index.php/Bluetooth gives different
configuration for Alsa

pcm.btheadset {
   type plug
   slave {
       pcm {
           type bluetooth
           device XX:XX:XX:XX:XX:XX
           profile "auto"
       }
   }
   hint {
       show on
       description "BT Headset"
   }
}
ctl.btheadset {
  type bluetooth
}

With this configuration the headset becomes visible in aplay -L.

So, the issue is resolved. Thank you for help!

Andrei

^ permalink raw reply

* Re: Authentication Rejected when pairing stereo headset
From: Andrey Voropaev @ 2012-12-20 10:51 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20121220093840.GA21122@aemeltch-MOBL1>

On Thu, Dec 20, 2012 at 10:38 AM, Andrei Emeltchenko
<andrei.emeltchenko.news@gmail.com> wrote:
>
> The patch is below:
>
> commit 7a7f1e7c857959f5298020969741e389f21edbae
> Author: Hemant Gupta <hemant.gupta@stericsson.com>
> Date:   Mon Jan 16 13:34:29 2012 +0530
>
>     Bluetooth: Send correct response to IO Capability Request
>
>     This patch sends correct IO Capability response to remote device
>     in case Local Device supports KeyBoardDisplay IO Capability as
>     this capability is not valid as per BT spec for IO capability
>     Request Reply Command.
>     This capability is mapped to DisplayYesNo which is in accordance
>     with BT spec.
>
>     Signed-off-by: Hemant Gupta <hemant.gupta@stericsson.com>
>     Acked-by: Marcel Holtmann <marcel@holtmann.org>
>     Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
>
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 6fb9016..041a35e 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -2965,7 +2965,10 @@ static inline void hci_io_capa_request_evt(struct
> hci_dev *hdev, struct sk_buff
>                 struct hci_cp_io_capability_reply cp;
>
>                 bacpy(&cp.bdaddr, &ev->bdaddr);
> -               cp.capability = conn->io_capability;
> +               /* Change the IO capability from KeyboardDisplay
> +                * to DisplayYesNo as it is not supported by BT spec. */
> +               cp.capability = (conn->io_capability == 0x04) ?
> +                                               0x01 :
> conn->io_capability;
>                 conn->auth_type = hci_get_auth_req(conn);
>                 cp.authentication = conn->auth_type;

Interesting. This patch is present in the sources for 3.5.7 kernel
that I have. But somehow it does not work. Fixing simple-agent did
work though.

Andrei

^ permalink raw reply

* Re: Authentication Rejected when pairing stereo headset
From: Andrey Voropaev @ 2012-12-20 10:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20121220093742.GA6548@x220>

On Thu, Dec 20, 2012 at 10:37 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> An quicker way for you to overcome the issue is to change the user space
> side pairing call to pass "DisplayYesNo" instead of "KeyboardDisplay" to
> BlueZ. I.e. edit the simple-agent script, find the (two) occurrences of
> "KeyboardDisplay" and change them to "DisplayYesNo" and try to pair
> again.

Thanks. This trick worked (though there was only 1 KeyboardDisplay).
I've paired the device and now hcitool con reports

Connections:
    < ACL 00:1A:7D:25:2C:A4 handle 43 state 1 lm MASTER AUTH ENCRYPT


And I get

hcitool info 00:1A:7D:25:2C:A4
Requesting information ...
    BD Address:  00:1A:7D:25:2C:A4
    OUI Company: cyber-blue(HK)Ltd (00-1A-7D)
    Device Name: BTH220
    LMP Version: 2.1 (0x4) LMP Subversion: 0x14fa
    Manufacturer: Cambridge Silicon Radio (10)
    Features page 0: 0xff 0xfe 0x0f 0xc6 0x8b 0xef 0x59 0x83
        <3-slot packets> <5-slot packets> <encryption> <slot offset>
        <timing accuracy> <role switch> <hold mode> <sniff mode>
        <RSSI> <channel quality> <SCO link> <HV2 packets>
        <HV3 packets> <u-law log> <A-law log> <CVSD> <paging scheme>
        <power control> <transparent SCO> <EDR ACL 2 Mbps>
        <EDR ACL 3 Mbps> <inquiry with RSSI> <extended SCO>
        <EV4 packets> <EV5 packets> <AFH cap. slave> <3-slot EDR ACL>
        <5-slot EDR ACL> <sniff subrating> <pause encryption>
        <AFH cap. master> <EDR eSCO 2 Mbps> <EDR eSCO 3 Mbps>
        <3-slot EDR eSCO> <extended inquiry> <simple pairing>
        <encapsulated PDU> <non-flush flag> <LSTO> <inquiry TX power>
        <extended features>
    Features page 1: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00

But seems like Alsa still does not see it. I've added

 pcm.bluetooth {
  type bluetooth
  device 00:1A:7D:25:2C:A4
  profile "auto"
 }


to /etc/asound.conf, restarted alsasound, but bluetooth does not show
up among available outputs. Well, I'm almost there. The Skype has
"bluetooth" in the list of devices and it works. Just mplayer does not
want to work with option

 -ao alsa:device=bluetooth


Probably there's some capabilities problem. Any advice here? :) Sorry ...

^ permalink raw reply

* Re: Authentication Rejected when pairing stereo headset
From: Andrei Emeltchenko @ 2012-12-20  9:38 UTC (permalink / raw)
  To: Andrey Voropaev; +Cc: linux-bluetooth
In-Reply-To: <CAFOXTdf9qrtXD0GPDBFLhLX66QGQCgF_VzyS8WWz5xTAH8+0zQ@mail.gmail.com>

Hi Andrey,

On Thu, Dec 20, 2012 at 10:27:15AM +0100, Andrey Voropaev wrote:
> On Thu, Dec 20, 2012 at 10:19 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> > First of all, please don't do top posting. It messes up the thread,
> > especially when mixed with inline quoting.
> 
> Sorry. First time replying to list from gmail. Didn't pay attention to
> that little mark at the bottom of the editor :)
> 
> > Actually the hcidump helped a lot. It shows an issue on the kernel side:
> >
> >  < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9
> >      bdaddr 00:1A:7D:25:2C:A4 capability 0x04 oob 0x00 auth 0x03
> >      Capability: Reserved (OOB data not present)
> >      Authentication: Dedicated Bonding (MITM Protection)
> >  > HCI Event: Command Complete (0x0e) plen 10
> >      IO Capability Request Reply (0x01|0x002b) ncmd 1
> >      status 0x12 bdaddr 00:1A:7D:25:2C:A4
> >      Error: Invalid HCI Command Parameters
> >
> > The IO capability value 0x04 that the kernel is responding with is
> > invalid and shouldn't be sent to the controller. This was already fixed
> > quite long time ago (about 1 year ago) by the following patch from
> > Hemant Gupta: "Bluetooth: Send correct response to IO Capability Request"
> >
> > It adds the following code to the IO capability handling to avoid 0x04
> > from being sent:
> >
> >         /* Change the IO capability from KeyboardDisplay
> >          * to DisplayYesNo as it is not supported by BT spec. */
> >         cp.capability = (conn->io_capability == 0x04) ?
> >                                         0x01 : conn->io_capability;
> >
> > It seems however that your kernel is missing this patch and the right
> > way forward would be to include it.
> 
> I'm using Gentoo with "stable" version 3.5.7. Can you please tell me
> which file shall contain this patch? I'll try to find "development"
> version of kernel that contains it.

The patch is below:

commit 7a7f1e7c857959f5298020969741e389f21edbae
Author: Hemant Gupta <hemant.gupta@stericsson.com>
Date:   Mon Jan 16 13:34:29 2012 +0530

    Bluetooth: Send correct response to IO Capability Request
    
    This patch sends correct IO Capability response to remote device
    in case Local Device supports KeyBoardDisplay IO Capability as
    this capability is not valid as per BT spec for IO capability
    Request Reply Command.
    This capability is mapped to DisplayYesNo which is in accordance
    with BT spec.
    
    Signed-off-by: Hemant Gupta <hemant.gupta@stericsson.com>
    Acked-by: Marcel Holtmann <marcel@holtmann.org>
    Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6fb9016..041a35e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2965,7 +2965,10 @@ static inline void hci_io_capa_request_evt(struct
hci_dev *hdev, struct sk_buff
                struct hci_cp_io_capability_reply cp;
 
                bacpy(&cp.bdaddr, &ev->bdaddr);
-               cp.capability = conn->io_capability;
+               /* Change the IO capability from KeyboardDisplay
+                * to DisplayYesNo as it is not supported by BT spec. */
+               cp.capability = (conn->io_capability == 0x04) ?
+                                               0x01 :
conn->io_capability;
                conn->auth_type = hci_get_auth_req(conn);
                cp.authentication = conn->auth_type;


Best regards 
Andrei Emeltchenko 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: Authentication Rejected when pairing stereo headset
From: Johan Hedberg @ 2012-12-20  9:37 UTC (permalink / raw)
  To: Andrey Voropaev; +Cc: linux-bluetooth
In-Reply-To: <CAFOXTdf9qrtXD0GPDBFLhLX66QGQCgF_VzyS8WWz5xTAH8+0zQ@mail.gmail.com>

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

Hi Andrey,

On Thu, Dec 20, 2012, Andrey Voropaev wrote:
> > Actually the hcidump helped a lot. It shows an issue on the kernel side:
> >
> >  < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9
> >      bdaddr 00:1A:7D:25:2C:A4 capability 0x04 oob 0x00 auth 0x03
> >      Capability: Reserved (OOB data not present)
> >      Authentication: Dedicated Bonding (MITM Protection)
> >  > HCI Event: Command Complete (0x0e) plen 10
> >      IO Capability Request Reply (0x01|0x002b) ncmd 1
> >      status 0x12 bdaddr 00:1A:7D:25:2C:A4
> >      Error: Invalid HCI Command Parameters
> >
> > The IO capability value 0x04 that the kernel is responding with is
> > invalid and shouldn't be sent to the controller. This was already fixed
> > quite long time ago (about 1 year ago) by the following patch from
> > Hemant Gupta: "Bluetooth: Send correct response to IO Capability Request"
> >
> > It adds the following code to the IO capability handling to avoid 0x04
> > from being sent:
> >
> >         /* Change the IO capability from KeyboardDisplay
> >          * to DisplayYesNo as it is not supported by BT spec. */
> >         cp.capability = (conn->io_capability == 0x04) ?
> >                                         0x01 : conn->io_capability;
> >
> > It seems however that your kernel is missing this patch and the right
> > way forward would be to include it.
> 
> I'm using Gentoo with "stable" version 3.5.7. Can you please tell me
> which file shall contain this patch? I'll try to find "development"
> version of kernel that contains it.

The file involved is net/bluetooth/hci_event.c. I've attached the patch
to this email.

An quicker way for you to overcome the issue is to change the user space
side pairing call to pass "DisplayYesNo" instead of "KeyboardDisplay" to
BlueZ. I.e. edit the simple-agent script, find the (two) occurrences of
"KeyboardDisplay" and change them to "DisplayYesNo" and try to pair
again.

Johan

[-- Attachment #2: 0001-Bluetooth-Send-correct-response-to-IO-Capability-Req.patch --]
[-- Type: text/plain, Size: 1459 bytes --]

>From 7a7f1e7c857959f5298020969741e389f21edbae Mon Sep 17 00:00:00 2001
From: Hemant Gupta <hemant.gupta@stericsson.com>
Date: Mon, 16 Jan 2012 13:34:29 +0530
Subject: [PATCH] Bluetooth: Send correct response to IO Capability Request

This patch sends correct IO Capability response to remote device
in case Local Device supports KeyBoardDisplay IO Capability as
this capability is not valid as per BT spec for IO capability
Request Reply Command.
This capability is mapped to DisplayYesNo which is in accordance
with BT spec.

Signed-off-by: Hemant Gupta <hemant.gupta@stericsson.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/hci_event.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6fb9016..041a35e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2965,7 +2965,10 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
 		struct hci_cp_io_capability_reply cp;
 
 		bacpy(&cp.bdaddr, &ev->bdaddr);
-		cp.capability = conn->io_capability;
+		/* Change the IO capability from KeyboardDisplay
+		 * to DisplayYesNo as it is not supported by BT spec. */
+		cp.capability = (conn->io_capability == 0x04) ?
+						0x01 : conn->io_capability;
 		conn->auth_type = hci_get_auth_req(conn);
 		cp.authentication = conn->auth_type;
 
-- 
1.8.0.2


^ permalink raw reply related

* Re: Authentication Rejected when pairing stereo headset
From: Andrey Voropaev @ 2012-12-20  9:27 UTC (permalink / raw)
  To: Andrey Voropaev, linux-bluetooth
In-Reply-To: <20121220091943.GA5862@x220>

On Thu, Dec 20, 2012 at 10:19 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> First of all, please don't do top posting. It messes up the thread,
> especially when mixed with inline quoting.

Sorry. First time replying to list from gmail. Didn't pay attention to
that little mark at the bottom of the editor :)

> Actually the hcidump helped a lot. It shows an issue on the kernel side:
>
>  < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9
>      bdaddr 00:1A:7D:25:2C:A4 capability 0x04 oob 0x00 auth 0x03
>      Capability: Reserved (OOB data not present)
>      Authentication: Dedicated Bonding (MITM Protection)
>  > HCI Event: Command Complete (0x0e) plen 10
>      IO Capability Request Reply (0x01|0x002b) ncmd 1
>      status 0x12 bdaddr 00:1A:7D:25:2C:A4
>      Error: Invalid HCI Command Parameters
>
> The IO capability value 0x04 that the kernel is responding with is
> invalid and shouldn't be sent to the controller. This was already fixed
> quite long time ago (about 1 year ago) by the following patch from
> Hemant Gupta: "Bluetooth: Send correct response to IO Capability Request"
>
> It adds the following code to the IO capability handling to avoid 0x04
> from being sent:
>
>         /* Change the IO capability from KeyboardDisplay
>          * to DisplayYesNo as it is not supported by BT spec. */
>         cp.capability = (conn->io_capability == 0x04) ?
>                                         0x01 : conn->io_capability;
>
> It seems however that your kernel is missing this patch and the right
> way forward would be to include it.

I'm using Gentoo with "stable" version 3.5.7. Can you please tell me
which file shall contain this patch? I'll try to find "development"
version of kernel that contains it.

^ permalink raw reply

* Re: Authentication Rejected when pairing stereo headset
From: Johan Hedberg @ 2012-12-20  9:19 UTC (permalink / raw)
  To: Andrey Voropaev; +Cc: linux-bluetooth
In-Reply-To: <CAFOXTde8iSouGKEVZKG-egvPUr4LAyLnFigVa6avhpqTjXNq8A@mail.gmail.com>

Hi Andrey,

First of all, please don't do top posting. It messes up the thread,
especially when mixed with inline quoting.

On Thu, Dec 20, 2012, Andrey Voropaev wrote:
> I've copied the output from hcidump -w to http://vandal.sdf-eu.org/hcidump.file
>
> So far, I'm not sure how to add -d switch to bluetoothd. It is started
> via dbus and this monster is not familiar to me. Can you please tell
> me, which file should I edit to add the switch?

Actually the hcidump helped a lot. It shows an issue on the kernel side:

 < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9
     bdaddr 00:1A:7D:25:2C:A4 capability 0x04 oob 0x00 auth 0x03
     Capability: Reserved (OOB data not present)
     Authentication: Dedicated Bonding (MITM Protection)
 > HCI Event: Command Complete (0x0e) plen 10
     IO Capability Request Reply (0x01|0x002b) ncmd 1
     status 0x12 bdaddr 00:1A:7D:25:2C:A4
     Error: Invalid HCI Command Parameters

The IO capability value 0x04 that the kernel is responding with is
invalid and shouldn't be sent to the controller. This was already fixed
quite long time ago (about 1 year ago) by the following patch from
Hemant Gupta: "Bluetooth: Send correct response to IO Capability Request"

It adds the following code to the IO capability handling to avoid 0x04
from being sent:

        /* Change the IO capability from KeyboardDisplay
         * to DisplayYesNo as it is not supported by BT spec. */
        cp.capability = (conn->io_capability == 0x04) ?
                                        0x01 : conn->io_capability;

It seems however that your kernel is missing this patch and the right
way forward would be to include it.

Johan

^ permalink raw reply

* Re: Authentication Rejected when pairing stereo headset
From: Andrey Voropaev @ 2012-12-20  9:02 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20121220080447.GA561@x220>

I've copied the output from hcidump -w to http://vandal.sdf-eu.org/hcidump.file

So far, I'm not sure how to add -d switch to bluetoothd. It is started
via dbus and this monster is not familiar to me. Can you please tell
me, which file should I edit to add the switch?

Andrey

On Thu, Dec 20, 2012 at 9:04 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Andrey,
>
> On Thu, Dec 20, 2012, Andrey Voropaev wrote:
>> when I try 'simple-agent hci0 XX:XX:XX' I always get error
>>
>> Creating device failed: org.bluez.Error.AuthenticationRejected:
>> Authentication Rejected
>>
>> I'm doing everything as root, so what could be the reason for
>> "Authentication Rejected"? Incompatible hardware? Wrong configuration?
>>
>> In which direction should I be searching?
>
> The bluetoothd debug logs (run with -d switch) would be interesting as
> well as the HCI level trace (for which you can use e.g. hcidump).
>
> Johan

^ permalink raw reply

* Re: Authentication Rejected when pairing stereo headset
From: Johan Hedberg @ 2012-12-20  8:04 UTC (permalink / raw)
  To: Andrey Voropaev; +Cc: linux-bluetooth
In-Reply-To: <CAFOXTdcaRvGHesU_J7rW93Yp_5d438+x5xryCzAhY9QQL_-Y4Q@mail.gmail.com>

Hi Andrey,

On Thu, Dec 20, 2012, Andrey Voropaev wrote:
> when I try 'simple-agent hci0 XX:XX:XX' I always get error
> 
> Creating device failed: org.bluez.Error.AuthenticationRejected:
> Authentication Rejected
> 
> I'm doing everything as root, so what could be the reason for
> "Authentication Rejected"? Incompatible hardware? Wrong configuration?
> 
> In which direction should I be searching?

The bluetoothd debug logs (run with -d switch) would be interesting as
well as the HCI level trace (for which you can use e.g. hcidump).

Johan

^ permalink raw reply

* Re: Question for setting IO capability parameter for RegisterAgent
From: Johan Hedberg @ 2012-12-20  7:55 UTC (permalink / raw)
  To: Xian Pan; +Cc: linux-bluetooth
In-Reply-To: <679160B2-3B1E-4D5E-978E-E3358F6126E9@gmail.com>

Hi Xian,

On Wed, Dec 19, 2012, Xian Pan wrote:
> I confuse the relationship between the 4 pairing mode in SSP with the
> IO capability parameter for the agent. From the agent-api.txt file,
> the capability parameter can have 5 values: DisplayOnly, DisplayYesNo,
> KeyboardOnly, NoInputNoOutput and KeyboardDisplay. I think there are
> only 4 pairing mode in SSP: just works, numeric comparison, out of
> band, and passkey entry. How the 5 IO capabilities can map to those 4
> pairing modes?

Low Energy SMP based pairing introduces the additional KeyboardDisplay
IO capability. If you want to support LE it's recommended you provide
that as your agent capability and BlueZ will then automatically
downgrade it to DisplayYesNo for BR/EDR (SSP) pairing and use it as is
for LE SMP pairing.

Johan

^ permalink raw reply

* Re: [PATCH] gdbus: Fix double free when calling g_dbus_remove_all_watches
From: Tomasz Bursztyka @ 2012-12-20  7:46 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <CAMOw1v40+w62ToR4SKnNLnKfLzBSz_MKK1fXwoW66z7cXbTw4A@mail.gmail.com>

Hi Lucas,

> @@ -309,6 +309,9 @@ static void filter_data_call_and_free(struct filter_data *data)
>                  g_free(cb);
>          }
>
> +       g_slist_free(data->callbacks);
> +       data->callbacks = NULL;
> +
>
> why not just removing the g_free(cb)  above?
>

I did so to avoid filter_data_free() to go through the list once again,
but indeed if the list is not going to be big, it's superfluous then.

Tomasz

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox