* [PATCH 4/4] bnep: Calculate ifindex after NULL check
From: Andrei Emeltchenko @ 2014-02-07 12:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391775078-25010-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
profiles/network/bnep.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 1aa0783..ece979f 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -523,13 +523,15 @@ static int bnep_add_to_bridge(const char *devname, const char *bridge)
static int bnep_del_from_bridge(const char *devname, const char *bridge)
{
- int ifindex = if_nametoindex(devname);
+ int ifindex;
struct ifreq ifr;
int sk, err;
if (!devname || !bridge)
return -EINVAL;
+ ifindex = if_nametoindex(devname);
+
sk = socket(AF_INET, SOCK_STREAM, 0);
if (sk < 0)
return -1;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/4] avdtp: Fix passing NULL pointer to memcpy
From: Andrei Emeltchenko @ 2014-02-07 12:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391775078-25010-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
The patch fixes following clang warning:
...
profiles/audio/avdtp.c:3293:2: warning: Null pointer passed as an
argument to a 'nonnull' parameter
memcpy(cap->data, data, length);
^ ~~~~
1 warning generated.
...
---
profiles/audio/avdtp.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index da10ab4..b7ddb6c 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -3290,7 +3290,9 @@ struct avdtp_service_capability *avdtp_service_cap_new(uint8_t category,
cap = g_malloc(sizeof(struct avdtp_service_capability) + length);
cap->category = category;
cap->length = length;
- memcpy(cap->data, data, length);
+
+ if (data)
+ memcpy(cap->data, data, length);
return cap;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/4] avdtp: Fix passing NULL pointer to memcpy
From: Andrei Emeltchenko @ 2014-02-07 12:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1391775078-25010-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
send_request can be called as
send_request(session, FALSE, NULL, AVDTP_DISCOVER, NULL, 0) with NULL
pointer which is passed to memcpy().
---
profiles/audio/avdtp.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index fbf61f0..da10ab4 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -2731,11 +2731,14 @@ static int send_request(struct avdtp *session, gboolean priority,
req = g_new0(struct pending_req, 1);
req->signal_id = signal_id;
- req->data = g_malloc(size);
- memcpy(req->data, buffer, size);
- req->data_size = size;
req->stream = stream;
+ if (buffer && size) {
+ req->data = g_malloc(size);
+ memcpy(req->data, buffer, size);
+ req->data_size = size;
+ }
+
return send_req(session, priority, req);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/4] android/haltest: Remove unneeded assignment
From: Andrei Emeltchenko @ 2014-02-07 12:11 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/client/if-audio.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 8c640a1..5ab11a6 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -225,10 +225,8 @@ static void *playback_thread(void *data)
pthread_mutex_unlock(&outstream_mutex);
} while (len && w_len > 0);
- if (in) {
+ if (in)
fclose(in);
- in = NULL;
- }
pthread_cleanup_pop(1);
return NULL;
--
1.8.3.2
^ permalink raw reply related
* [RFC 2/2] bluetooth: Add initial support for BT chip over SMD
From: Lukasz Rymanowski @ 2014-02-07 11:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1391772937-12802-1-git-send-email-lukasz.rymanowski@tieto.com>
This patch adds support for Qualcomm chips which uses msm
shared memory driver as a transport layer.
This driver based on SMD driver found in msm kernel branch.
Signed-off-by: Lukasz Rymanowski <lukasz.rymanowski@tieto.com>
---
drivers/bluetooth/Kconfig | 9 +
drivers/bluetooth/Makefile | 1 +
drivers/bluetooth/hci_smd.c | 460 ++++++++++++++++++++++++++++++++++++++++++++
include/net/bluetooth/hci.h | 1 +
4 files changed, 471 insertions(+)
create mode 100644 drivers/bluetooth/hci_smd.c
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 11a6104..f8a46c5 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -242,4 +242,13 @@ 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_HCISMD
+ tristate "Qualcomm HCI Shared Memory Driver"
+ help
+ This enables the Bluetooth driver for Qualcomm BT devices uses SMD interface.
+
+ Say Y here to compile support for Qualcomm over SMD driver into kernel or
+ say M to compile it as module (hci_smd)
+
endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 9fe8a87..0666e60 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_HCISMD) += hci_smd.o
btmrvl-y := btmrvl_main.o
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
new file mode 100644
index 0000000..9eb3675
--- /dev/null
+++ b/drivers/bluetooth/hci_smd.c
@@ -0,0 +1,460 @@
+
+/*
+ *
+ * HCI_SMD (HCI Shared Memory Driver) is Qualcomm's Shared memory driver
+ * for the HCI protocol.
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2014, Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include <linux/smd.h>
+
+#define VERSION "0.1"
+
+#define SMD_CMD_CHANNEL "APPS_RIVA_BT_CMD"
+#define SMD_ACL_CHANNEL "APPS_RIVA_BT_ACL"
+
+#define SMD_APPS_RIVA_BT_CMD_READY 0x01
+#define SMD_APPS_RIVA_BT_ACL_READY 0x02
+#define SMD_READY ((SMD_APPS_RIVA_BT_CMD_READY) | (SMD_APPS_RIVA_BT_ACL_READY))
+
+struct rx_work {
+ struct work_struct work;
+ struct smd_data *smd;
+ struct hci_dev *hdev;
+ u8 pkt_type;
+};
+
+struct smd_channel_data {
+ struct hci_dev *hdev;
+ struct workqueue_struct *wq;
+ struct smd_data *smd;
+};
+
+struct hci_smd_data {
+ struct hci_dev *hdev;
+
+ struct smd_channel_data *smd_cmd;
+ struct smd_channel_data *smd_acl;
+ u8 ready_flags;
+ struct completion smd_ready;
+
+ /* Protects ready_flags */
+ spinlock_t flags_lock;
+};
+
+static struct hci_smd_data hs;
+
+static void hci_smd_channel_open(struct smd_channel_data *scd)
+{
+ const char *name = scd->smd->pdev->name;
+
+ spin_lock(&hs.flags_lock);
+ if (scd->hdev) {
+ set_bit(HCI_RUNNING, &scd->hdev->flags);
+ spin_unlock(&hs.flags_lock);
+ return;
+ }
+
+ if (!strncmp(name, SMD_CMD_CHANNEL, sizeof(SMD_CMD_CHANNEL)))
+ hs.ready_flags |= SMD_APPS_RIVA_BT_CMD_READY;
+
+ if (!strncmp(name, SMD_ACL_CHANNEL, sizeof(SMD_ACL_CHANNEL)))
+ hs.ready_flags |= SMD_APPS_RIVA_BT_ACL_READY;
+
+ if ((SMD_READY & hs.ready_flags) != SMD_READY) {
+ spin_unlock(&hs.flags_lock);
+ return;
+ }
+
+ spin_unlock(&hs.flags_lock);
+ complete_all(&hs.smd_ready);
+}
+
+static void hci_smd_channel_close(struct smd_channel_data *scd)
+{
+ if (!scd->hdev)
+ return;
+
+ clear_bit(HCI_RUNNING, &scd->hdev->flags);
+}
+
+static int hci_smd_open(struct hci_dev *hdev)
+{
+ BT_DBG("hdev %s, %p", hdev->name, hdev);
+
+ set_bit(HCI_RUNNING, &hdev->flags);
+ return 0;
+}
+
+static int hci_smd_close(struct hci_dev *hdev)
+{
+ BT_DBG("hdev %s %p", hdev->name, hdev);
+
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ return 0;
+}
+
+static void hci_smd_rx_work(struct work_struct *work)
+{
+ struct rx_work *wk = container_of(work, struct rx_work, work);
+ u8 type = wk->pkt_type;
+ struct smd_data *smd = wk->smd;
+ struct hci_dev *hdev = wk->hdev;
+ struct sk_buff *skb;
+ int len;
+
+ BT_DBG("hdev %p, %02x", hdev, type);
+
+ /*It s save to free work here */
+ kfree(wk);
+
+ len = smd->ops.read_avail(smd);
+ if (len > HCI_MAX_FRAME_SIZE)
+ return;
+
+ while (len) {
+ int rc = 0;
+ skb = bt_skb_alloc(len, GFP_KERNEL);
+ if (!skb)
+ return;
+
+ rc = smd->ops.read(smd, skb_put(skb, len), len);
+ if (rc < len) {
+ kfree_skb(skb);
+ return;
+ }
+
+ skb->dev = (void *)hdev;
+ bt_cb(skb)->pkt_type = type;
+ skb_orphan(skb);
+
+ rc = hci_recv_frame(hdev, skb);
+ if (rc < 0) {
+ BT_ERR("Failed to pass skb to Bluetooth module");
+ kfree_skb(skb);
+ return;
+ }
+
+ len = smd->ops.read_avail(smd);
+ if (len > HCI_MAX_FRAME_SIZE)
+ return;
+ }
+}
+
+static int hci_smd_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_smd_data *hs = hci_get_drvdata(hdev);
+ struct smd_data *smd;
+ int sent;
+
+ if (!hdev) {
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
+ return -ENODEV;
+ }
+
+ if (!test_bit(HCI_RUNNING, &(hdev->flags)))
+ return -EBUSY;
+
+ switch (bt_cb(skb)->pkt_type) {
+ case HCI_COMMAND_PKT:
+ smd = hs->smd_cmd->smd;
+ sent = smd->ops.write(smd, skb->data, skb->len);
+ break;
+ case HCI_ACLDATA_PKT:
+ case HCI_SCODATA_PKT:
+ smd = hs->smd_acl->smd;
+ sent = smd->ops.write(smd, skb->data, skb->len);
+ break;
+ default:
+ BT_ERR("Unknown package");
+ kfree_skb(skb);
+ return -EPROTO;
+ }
+
+ kfree_skb(skb);
+
+ if (sent < 0) {
+ BT_ERR("Failed to send all data");
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+static struct rx_work *alloc_rx_work(u8 pkt_type, struct smd_data *smd,
+ struct hci_dev *hdev)
+{
+ struct rx_work *w = kmalloc(sizeof(*w), GFP_ATOMIC);
+
+ if (!w) {
+ BT_ERR("Could not allocate work");
+ return NULL;
+ }
+
+ INIT_WORK(&w->work, hci_smd_rx_work);
+ w->pkt_type = pkt_type;
+ w->smd = smd;
+ w->hdev = hdev;
+
+ return w;
+}
+
+static void hci_smd_notify(struct platform_device *pdev,
+ unsigned int event, u8 pkt_type)
+{
+ struct smd_channel_data *scd = dev_get_drvdata(&pdev->dev);
+ struct hci_dev *hdev = scd->hdev;
+ struct rx_work *w;
+
+ if (!scd || !scd->smd) {
+ BT_ERR("SMD channel data not avaiable");
+ return;
+ }
+
+ switch (event) {
+ case SMD_EVENT_DATA:
+ w = alloc_rx_work(pkt_type, scd->smd, hdev);
+ if (w && hdev)
+ queue_work(scd->wq, &w->work);
+ else
+ BT_ERR("Read failed hdev:%p, work:%p ", hdev, w);
+ break;
+ case SMD_EVENT_OPEN:
+ hci_smd_channel_open(scd);
+ break;
+ case SMD_EVENT_CLOSE:
+ hci_smd_channel_close(scd);
+ break;
+ default:
+ break;
+ }
+}
+
+static void hci_smd_notify_cmd(struct platform_device *pdev,
+ unsigned int event)
+{
+ hci_smd_notify(pdev, event, HCI_EVENT_PKT);
+}
+
+static void hci_smd_notify_data(struct platform_device *pdev,
+ unsigned int event)
+{
+ hci_smd_notify(pdev, event, HCI_ACLDATA_PKT);
+}
+
+static int hci_smd_register(void)
+{
+ struct hci_dev *hdev;
+ int err;
+
+ BT_DBG("hci_smd_register");
+
+ /*
+ * Lets use two different worqueues for Event and ACL data so we make
+ * sure that Event will never be blocked by ACL data.
+ */
+ hs.smd_cmd->wq = alloc_workqueue("smd_event", WQ_HIGHPRI |
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!hs.smd_cmd->wq) {
+ BT_ERR("Error allocating event workqueue");
+ err = -ENOMEM;
+ goto close_smd;
+ }
+
+ hs.smd_acl->wq = alloc_workqueue("data_event", WQ_HIGHPRI |
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!hs.smd_acl->wq) {
+ BT_ERR("Error allocating data workqueue");
+ destroy_workqueue(hs.smd_cmd->wq);
+ err = -ENOMEM;
+ goto close_smd;
+ }
+
+ /* Initialize and register HCI device */
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ BT_ERR("Error allocating HCI dev");
+ err = -ENOMEM;
+ goto cleanup;
+ }
+
+ hdev->bus = HCI_SMD;
+ hci_set_drvdata(hdev, &hs);
+
+ hdev->open = hci_smd_open;
+ hdev->close = hci_smd_close;
+ hdev->send = hci_smd_send_frame;
+
+ hs.smd_cmd->hdev = hdev;
+ hs.smd_acl->hdev = hdev;
+
+ err = hci_register_dev(hdev);
+ if (!err)
+ return 0;
+
+ BT_ERR("Can't register HCI device");
+ hci_free_dev(hdev);
+
+cleanup:
+ destroy_workqueue(hs.smd_cmd->wq);
+ destroy_workqueue(hs.smd_acl->wq);
+close_smd:
+ hs.smd_cmd->smd->ops.close(hs.smd_cmd->smd);
+ hs.smd_acl->smd->ops.close(hs.smd_acl->smd);
+
+ return err;
+}
+
+static int smd_cmd_channel_probe(struct platform_device *pdev)
+{
+ struct smd_data *smd = dev_get_platdata(&pdev->dev);
+ struct smd_channel_data *scd = kzalloc(sizeof(*scd), GFP_KERNEL);
+ int err;
+
+ scd->smd = smd;
+ hs.smd_cmd = scd;
+
+ dev_set_drvdata(&pdev->dev, scd);
+
+ err = smd->ops.open(smd, hci_smd_notify_cmd);
+ if (err < 0) {
+ BT_ERR("Can not open %s", SMD_CMD_CHANNEL);
+ return err;
+ }
+
+ return 0;
+}
+
+static int smd_data_channel_probe(struct platform_device *pdev)
+{
+ struct smd_data *smd = dev_get_platdata(&pdev->dev);
+ struct smd_channel_data *scd = kzalloc(sizeof(*scd), GFP_KERNEL);
+ int err;
+
+ scd->smd = smd;
+ hs.smd_acl = scd;
+
+ dev_set_drvdata(&pdev->dev, scd);
+
+ err = smd->ops.open(smd, hci_smd_notify_data);
+ if (err < 0) {
+ BT_ERR("Can not open %s", SMD_ACL_CHANNEL);
+ return err;
+ }
+
+ return 0;
+}
+
+
+static int smd_channel_remove(struct platform_device *pdev)
+{
+ struct smd_data *smd = dev_get_platdata(&pdev->dev);
+ return smd->ops.close(smd);
+}
+
+static struct platform_driver cmd_drv = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SMD_CMD_CHANNEL,
+ },
+ .probe = smd_cmd_channel_probe,
+ .remove = smd_channel_remove,
+
+};
+
+static struct platform_driver acl_drv = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SMD_ACL_CHANNEL,
+ },
+ .probe = smd_data_channel_probe,
+ .remove = smd_channel_remove,
+};
+
+static int __init hci_smd_init(void)
+{
+ int err;
+
+ BT_INFO("hci smd driver ver %s", VERSION);
+
+ memset(&hs, 0, sizeof(hs));
+
+ spin_lock_init(&hs.flags_lock);
+ init_completion(&hs.smd_ready);
+
+ /*
+ * SMD channels are represented by platform devices. We need them two
+ * for BT operations. Channel for BT CMD/EVENT traffic and BT ACL DATA
+ * traffic.
+ */
+ err = platform_driver_register(&cmd_drv);
+ if (err < 0) {
+ BT_ERR("Failed to register drv: %s err: %d",
+ cmd_drv.driver.name, err);
+ return err;
+ }
+
+ err = platform_driver_register(&acl_drv);
+ if (err < 0) {
+ BT_ERR("Failed to register drv: %s, err: %d",
+ acl_drv.driver.name, err);
+ platform_driver_unregister(&cmd_drv);
+ return err;
+ }
+
+ /* Let's wait until SMD channels are ready */
+ err = wait_for_completion_killable_timeout(&hs.smd_ready,
+ msecs_to_jiffies(5000));
+ if (err <= 0)
+ return err;
+
+ return hci_smd_register();
+}
+
+static void __exit hci_smd_exit(void)
+{
+ kfree(hs.smd_cmd);
+ kfree(hs.smd_acl);
+
+ platform_driver_unregister(&cmd_drv);
+ platform_driver_unregister(&acl_drv);
+}
+
+module_init(hci_smd_init);
+module_exit(hci_smd_exit);
+
+MODULE_AUTHOR("Lukasz Rymanowski <lukasz.rymanowski@tieto.com>");
+MODULE_AUTHOR("Ankur Nandwani <ankurn@codeaurora.org>");
+MODULE_DESCRIPTION("Bluetooth SMD driver ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 352d3d7..149b06a 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -58,6 +58,7 @@
#define HCI_RS232 4
#define HCI_PCI 5
#define HCI_SDIO 6
+#define HCI_SMD 7
/* HCI controller types */
#define HCI_BREDR 0x00
--
1.8.4
^ permalink raw reply related
* [RFC 1/2] Add basic API for shared memory driver
From: Lukasz Rymanowski @ 2014-02-07 11:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Lukasz Rymanowski
In-Reply-To: <1391772937-12802-1-git-send-email-lukasz.rymanowski@tieto.com>
This patch adds simple API to shared memory driver based on msm-smd.h
This is required in order to add support for support Qualcomm BT chips
via SMD
Signed-off-by: Lukasz Rymanowski <lukasz.rymanowski@tieto.com>
---
include/linux/smd.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
create mode 100644 include/linux/smd.h
diff --git a/include/linux/smd.h b/include/linux/smd.h
new file mode 100644
index 0000000..58de0d4
--- /dev/null
+++ b/include/linux/smd.h
@@ -0,0 +1,69 @@
+/*
+* smd.h - API for Shared Memory Driver
+*
+* Copyright (c) 2014 Intel Corporation
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#ifndef _SMD_H_
+#define _SMD_H_
+
+#include <linux/platform_device.h>
+
+/**
+* Events from smd device.
+*/
+#define SMD_EVENT_DATA 1
+#define SMD_EVENT_OPEN 2
+#define SMD_EVENT_CLOSE 3
+
+struct smd_channel;
+struct smd_notify_data;
+struct smd_data;
+
+/**
+* struct smd_ops - specific operation for smd channel
+*
+* @open: Open SMD channel. It should return zero once device is opened.
+* On open there is need to pass notification cb which is used
+* for notifications form SMD device.
+* @close Close SMD channel
+* @write: Write data to SMD channel. It should return number of written
+* bytes or negative value in case of error.
+* @read: Read data from SMD channel.It should return number of written
+* bytes or negative value in case of error.
+*@read_avail: Returns number of bytes ready to be read. This should be called
+* before read in order to allocate enought skb
+*
+*/
+struct smd_ops {
+ int (*open)(struct smd_data *s,
+ void (*notify)(struct platform_device *pdev,
+ unsigned int event));
+ int (*close)(struct smd_data *s);
+ int (*write)(struct smd_data *s, const void *data, int len);
+ int (*read)(struct smd_data *s, void *buf, int len);
+ int (*read_avail)(struct smd_data *s);
+};
+/**
+* struct smd_data - smd device data for shared memory channel
+*
+* @pdev: Platform device for given smd channel.
+* @ops: SMD specific operations for this smd channel.
+* @ch: SMD channel which is used by SMD device. Should not be
+* used by the driver
+* @notifier: SMD notifier data. Shall not be used by driver.
+*
+* smd_data are initialized by the platform and are available for driver
+* in platform_data.
+*/
+struct smd_data {
+ struct platform_device *pdev;
+ struct smd_ops ops;
+ struct smd_channel *ch;
+ struct smd_notify_data *notify_data;
+};
+#endif
--
1.8.4
^ permalink raw reply related
* [RFC 0/2] Add hci_smd driver
From: Lukasz Rymanowski @ 2014-02-07 11:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Lukasz Rymanowski
Hello,
This is a try (long shoot) to upstream hci shared memory driver (hci_smd)
which is used on Qualcomm platforms and BT chips.
To make it build with upstream tree I had to introduce some simple SMD API.
The idea here is that since SMD channel is represented by platform device
(as it is done in mach-msm),
then platfrom_data contains smd_data which contains API for that channel.
Writing this SMD API I was inspired with MSM-SMD and since I'm not an expert
in this area I'm asking for comments here.
Maybe instead of SMD API I made, I should expose functions like smd_open(), smd_write()
etc. something similar how sdio does, and just deliver to upstream dummy device
implementing this SMD API?
Other options I was considering is to implement module inside mach-msm which
would handle registering SMD BT Channels and when it is done, it would register
new platform device like "smd-bt". Then I could move smd.h to some bluetooth includes
(althought don't now where at the moment) and hci_smd would register driver for "smd-bt"
In this case I would also could rid of one static variable I have now in hci_smd
Comments on those options are welcome.
Anyway, Hci_smd is based on one of the older version of this driver found in msm kernel
branch, so there are no wakelocks as in new version and also workqueues are used
instead of takslet.
Since SMD expose two channels, one for CMD/EVENT and one for ACL Data I decide to
do separate worqueues for this. This is to make sure that ACL data never blocks EVENT
packages
Lukasz Rymanowski (2):
Add basic API for shared memory driver
bluetooth: Add initial support for BT chip over SMD
drivers/bluetooth/Kconfig | 9 +
drivers/bluetooth/Makefile | 1 +
drivers/bluetooth/hci_smd.c | 461 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/smd.h | 68 +++++++
include/net/bluetooth/hci.h | 1 +
5 files changed, 540 insertions(+)
create mode 100644 drivers/bluetooth/hci_smd.c
create mode 100644 include/linux/smd.h
--
1.8.4
^ permalink raw reply
* Re: [PATCHv2 1/2] android/haltest: Close file in case of error
From: Szymon Janc @ 2014-02-07 10:05 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1391696563-7478-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Thursday 06 of February 2014 16:22:42 Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> ---
> android/client/if-audio.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/android/client/if-audio.c b/android/client/if-audio.c
> index 66f8364..3b34c95 100644
> --- a/android/client/if-audio.c
> +++ b/android/client/if-audio.c
> @@ -258,19 +258,26 @@ static void play_p(int argc, const char **argv)
>
> if (buffer_size == 0) {
> haltest_error("Invalid buffer size. Was stream_out opened?\n");
> - return;
> + goto fail;
> }
>
> pthread_mutex_lock(&state_mutex);
> if (current_state != STATE_STOPPED) {
> haltest_error("Already playing or stream suspended!\n");
> pthread_mutex_unlock(&state_mutex);
> - return;
> + goto fail;
> }
> pthread_mutex_unlock(&state_mutex);
>
> - if (pthread_create(&play_thread, NULL, playback_thread, in) != 0)
> + if (pthread_create(&play_thread, NULL, playback_thread, in) != 0) {
> haltest_error("Cannot create playback thread!\n");
> + goto fail;
> + }
> +
> + return;
> +fail:
> + if (in)
> + fclose(in);
> }
>
> static void stop_p(int argc, const char **argv)
>
This patch is now upstream, thanks.
--
Best regards,
Szymon Janc
^ permalink raw reply
* Re: [PATCH 5/6] android/a2dp: Disconnect headset on IPC failure
From: Luiz Augusto von Dentz @ 2014-02-07 9:58 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZKZGX54FnUPEZWM_4A+5otRHk+wyA-xhppfD8FeZckMjg@mail.gmail.com>
Hi Andrzej,
On Fri, Feb 7, 2014 at 11:45 AM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Andrzej,
>
> On Thu, Feb 6, 2014 at 7:54 PM, Andrzej Kaczmarek
> <andrzej.kaczmarek@tieto.com> wrote:
>> In case audio IPC is suddenly disconnected (most likely due to crash of
>> mediaserver process) we should disconnect headset since it is no longer
>> associated with valid setup and cannot be used properly.
>> ---
>> android/a2dp.c | 7 +++++++
>> 1 file changed, 7 insertions(+)
>>
>> diff --git a/android/a2dp.c b/android/a2dp.c
>> index 8eabfeb..f67a593 100644
>> --- a/android/a2dp.c
>> +++ b/android/a2dp.c
>> @@ -1515,6 +1515,7 @@ static gboolean audio_retry_register(void *data)
>>
>> static void audio_disconnected(void *data)
>> {
>> + GSList *l;
>> bool restart;
>>
>> DBG("");
>> @@ -1526,6 +1527,12 @@ static void audio_disconnected(void *data)
>>
>> bt_audio_unregister();
>>
>> + for (l = devices; l; l = g_slist_next(l)) {
>> + struct a2dp_device *dev = l->data;
>> +
>> + avdtp_shutdown(dev->session);
>> + }
>> +
>> if (!restart)
>> return;
>
> If we are unregistering the endpoints properly this should not happen,
> perhaps what is wrong is avdtp_unregister_sep is not aborting existing
> streams properly. Btw we should probably add a unit test if this is
> happening in practice because otherwise the remote won't notice.
I checked the code and actually this should not be a problem since we
drop the stream transport connection it should indicate a unclean
abort as it should be, in the past we had many times this happening
with PA crashing and it seems the headsets react properly to the
stream transport dropping unexpectedly, we can still do abort though.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH 5/6] android/a2dp: Disconnect headset on IPC failure
From: Luiz Augusto von Dentz @ 2014-02-07 9:45 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391709250-8047-5-git-send-email-andrzej.kaczmarek@tieto.com>
Hi Andrzej,
On Thu, Feb 6, 2014 at 7:54 PM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> In case audio IPC is suddenly disconnected (most likely due to crash of
> mediaserver process) we should disconnect headset since it is no longer
> associated with valid setup and cannot be used properly.
> ---
> android/a2dp.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/android/a2dp.c b/android/a2dp.c
> index 8eabfeb..f67a593 100644
> --- a/android/a2dp.c
> +++ b/android/a2dp.c
> @@ -1515,6 +1515,7 @@ static gboolean audio_retry_register(void *data)
>
> static void audio_disconnected(void *data)
> {
> + GSList *l;
> bool restart;
>
> DBG("");
> @@ -1526,6 +1527,12 @@ static void audio_disconnected(void *data)
>
> bt_audio_unregister();
>
> + for (l = devices; l; l = g_slist_next(l)) {
> + struct a2dp_device *dev = l->data;
> +
> + avdtp_shutdown(dev->session);
> + }
> +
> if (!restart)
> return;
If we are unregistering the endpoints properly this should not happen,
perhaps what is wrong is avdtp_unregister_sep is not aborting existing
streams properly. Btw we should probably add a unit test if this is
happening in practice because otherwise the remote won't notice.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH v3 0/8] Android PAN fixes
From: Luiz Augusto von Dentz @ 2014-02-07 9:37 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391700522-9036-1-git-send-email-szymon.janc@tieto.com>
Hi Szymon,
On Thu, Feb 6, 2014 at 5:28 PM, Szymon Janc <szymon.janc@tieto.com> wrote:
> V3:
> - fixed not bringing bridge if down
> - add forward_delay with ioctl patch
> - other minor bugfixes
>
> V2:
> This is based on patch from Ravi (sent 23.01.2013). Changes include
> patch split and some bugfixes.
>
> Ravi kumar Veeramally (1):
> android/pan: Fix bnep interface name
>
> Szymon Janc (7):
> profiles/network: Use interface name passed to bnep_connadd
> profiles/network: Allow to pass interface name to bnep_new
> android/pan: Move functions up to avoid forward declarations
> android/pan: Fix unregistering NAP bridge
> android/pan: Use ioctl instead of sysfs for setting forward delay
> android/pan: Pass error in nap_remove_bridge
> android/pan: Bring bridge interface down before removing it
>
> android/pan.c | 205 ++++++++++++++++++++++++++----------------
> profiles/network/bnep.c | 10 ++-
> profiles/network/bnep.h | 3 +-
> profiles/network/connection.c | 6 +-
> profiles/network/server.c | 4 +
> 5 files changed, 146 insertions(+), 82 deletions(-)
>
> --
> 1.8.3.2
Applied, thanks.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH 1/6] android/a2dp: Close AVDTP gracefully
From: Luiz Augusto von Dentz @ 2014-02-07 9:18 UTC (permalink / raw)
To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1391709250-8047-1-git-send-email-andrzej.kaczmarek@tieto.com>
Hi Andrzej,
On Thu, Feb 6, 2014 at 7:54 PM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> When closing AVDTP we should wait for for CLOSE request to complete
> (so stream go to idle state) before disconnecting signalling socket.
> In case CLOSE is rejected, we simply abort stream.
> ---
> android/a2dp.c | 4 +++-
> android/avdtp.c | 21 +++++++++++++++++----
> 2 files changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/android/a2dp.c b/android/a2dp.c
> index 8cff535..8d6e7bf 100644
> --- a/android/a2dp.c
> +++ b/android/a2dp.c
> @@ -1166,8 +1166,10 @@ static void sep_close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
>
> DBG("");
>
> - if (err)
> + if (err) {
> + avdtp_abort(session, stream);
> return;
> + }
>
> setup_remove_by_id(endpoint->id);
> }
> diff --git a/android/avdtp.c b/android/avdtp.c
> index e26d6ec..b9d1992 100644
> --- a/android/avdtp.c
> +++ b/android/avdtp.c
> @@ -398,6 +398,8 @@ struct avdtp {
> struct pending_req *req;
>
> GSList *disconnect;
> +
> + bool shutdown;
> };
>
> static GSList *lseps = NULL;
> @@ -913,6 +915,11 @@ static void avdtp_sep_set_state(struct avdtp *session,
> session->streams = g_slist_remove(session->streams, stream);
> stream_free(stream);
> }
> +
> + if (session->io && session->shutdown && session->streams == NULL) {
> + int sock = g_io_channel_unix_get_fd(session->io);
> + shutdown(sock, SHUT_RDWR);
> + }
> }
>
> static void finalize_discovery(struct avdtp *session, int err)
> @@ -2141,7 +2148,7 @@ gboolean avdtp_remove_disconnect_cb(struct avdtp *session, unsigned int id)
> void avdtp_shutdown(struct avdtp *session)
> {
> GSList *l;
> - int sock;
> + bool closing = false;
>
> if (!session->io)
> return;
> @@ -2149,12 +2156,18 @@ void avdtp_shutdown(struct avdtp *session)
> for (l = session->streams; l; l = g_slist_next(l)) {
> struct avdtp_stream *stream = l->data;
>
> - avdtp_close(session, stream, TRUE);
> + if (avdtp_close(session, stream, TRUE) == 0)
> + closing = true;
You could assign true directly to session->shutdown and return, also
it is probably a good idea to check if the flag is already set and if
it does call avdtp_abort, in fact I think we should call avdtp_abort
not avdtp_close anyway since we are shutting it down there is no point
of given the remote even a chance to reject.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: BISECTED Re: 3.14-mw regression: circular locking dependency (&tty->legacy_mutex){+.+.+.}, at: [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
From: Gianluca Anzolin @ 2014-02-07 6:55 UTC (permalink / raw)
To: Sander Eikelenboom
Cc: Marcel Holtmann, Greg Kroah-Hartman, linux-wireless,
linux-bluetooth, linux-serial
In-Reply-To: <754206689.20140207013750@eikelenboom.it>
Hi Sander,
On Fri, Feb 07, 2014 at 01:37:50AM +0100, Sander Eikelenboom wrote:
> Hi Marcel / Gianluca,
>
> Bisection points to this commit:
>
> 4a2fb3ecc7467c775b154813861f25a0ddc11aa0 is the first bad commit
> commit 4a2fb3ecc7467c775b154813861f25a0ddc11aa0
> Author: Gianluca Anzolin <gianluca@sottospazio.it>
> Date: Mon Jan 6 21:23:52 2014 +0100
Thank you for you report. I'm aware of this bug, no need to investigate
further.
This and other bugs are being tackled by Peter Hurley, who knows the tty
code way better than me.
You just have to wait for his patches, I think they will come shortly.
Thank you,
Gianluca
^ permalink raw reply
* Re: possible bug in blueZ 5.8 gatt tool or library
From: Anderson Lizardo @ 2014-02-07 0:55 UTC (permalink / raw)
To: Caleb Reinhold; +Cc: BlueZ development
In-Reply-To: <000001cf238d$a774e310$f65ea930$@lampreynetworks.com>
Hi,
On Thu, Feb 6, 2014 at 6:48 PM, Caleb Reinhold
<creinhold@lampreynetworks.com> wrote:
> It seemed that calling g_attrib_register() in the connection callback might
> be causing the client to start listening for indications and notifications
> too late, but registering right after the gatt_connect() call doesn't seem
> to help. Nor does placing a watch on the GIOChannel inside bt_io_connect(),
> so registering earlier doesn't appear to be the right approach. Do you know
> why we keep missing this initial indication on medium security, and how we
> might fix this issue?
If I remember correctly, the issue is in the kernel: if connect() is
called when security level is medium, the socket only gets POLLOUT
once SMP pairing finishes, and any ATT PDU received during that time
is lost.
Note that it's almost certain that your device is sending the
indication without requiring encryption. Otherwise, it would have sent
a Security Request (which triggers a Pairing Request from the Linux
side) and wait for the encryption to be enabled before sending the
indication. If that was the case, the kernel would deliver the ATT PDU
to gatttool after encryption is enabled and it would work as expected.
PS: Please, as common netiquette, avoid top-posting (i.e. answer
before the original message) and quote only the text that gives
context to your answer.
Best Regards,
--
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil
^ permalink raw reply
* BISECTED Re: 3.14-mw regression: circular locking dependency (&tty->legacy_mutex){+.+.+.}, at: [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
From: Sander Eikelenboom @ 2014-02-07 0:37 UTC (permalink / raw)
To: Marcel Holtmann, gianluca
Cc: Greg Kroah-Hartman, linux-wireless, linux-bluetooth, linux-serial
In-Reply-To: <378824645.20140126114721@eikelenboom.it>
Hi Marcel / Gianluca,
Bisection points to this commit:
4a2fb3ecc7467c775b154813861f25a0ddc11aa0 is the first bad commit
commit 4a2fb3ecc7467c775b154813861f25a0ddc11aa0
Author: Gianluca Anzolin <gianluca@sottospazio.it>
Date: Mon Jan 6 21:23:52 2014 +0100
Bluetooth: Always wait for a connection on RFCOMM open()
This patch fixes two regressions introduced with the recent rfcomm tty
rework.
The current code uses the carrier_raised() method to wait for the
bluetooth connection when a process opens the tty.
However processes may open the port with the O_NONBLOCK flag or set the
CLOCAL termios flag: in these cases the open() syscall returns
immediately without waiting for the bluetooth connection to
complete.
This behaviour confuses userspace which expects an established bluetooth
connection.
The patch restores the old behaviour by waiting for the connection in
rfcomm_dev_activate() and removes carrier_raised() from the tty_port ops.
As a side effect the new code also fixes the case in which the rfcomm
tty device is created with the flag RFCOMM_REUSE_DLC: the old code
didn't call device_move() and ModemManager skipped the detection
probe. Now device_move() is always called inside rfcomm_dev_activate().
Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
Reported-by: Andrey Vihrov <andrey.vihrov@gmail.com>
Reported-by: Beson Chow <blc+bluez@mail.vanade.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
BTW perhaps time to update your tree ?
Bisection took me back to 3.12 like areas .. the risk of bisection failing of other unrelated bugs seems to increase that way
Sunday, January 26, 2014, 11:47:21 AM, you wrote:
> Hi,
> I have got a regression with a 3.14-mw kernel (last commit is 4ba9920e5e9c0e16b5ed24292d45322907bb9035)
> when a script is started that reads from serial over bluetooth, that wasn't in the 3.13 release kernel:
> Jan 26 11:36:10 serveerstertje kernel: [ 72.892926]
> Jan 26 11:36:10 serveerstertje kernel: [ 72.900249] ======================================================
> Jan 26 11:36:10 serveerstertje kernel: [ 72.907697] [ INFO: possible circular locking dependency detected ]
> Jan 26 11:36:10 serveerstertje kernel: [ 72.915214] 3.13.0-20140125-mw-pcireset+ #1 Not tainted
> Jan 26 11:36:10 serveerstertje kernel: [ 72.922307] -------------------------------------------------------
> Jan 26 11:36:10 serveerstertje kernel: [ 72.928315] zabbix_slimmeme/5909 is trying to acquire lock:
> Jan 26 11:36:10 serveerstertje kernel: [ 72.934323] (&tty->legacy_mutex){+.+.+.}, at: [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 72.940434]
> Jan 26 11:36:10 serveerstertje kernel: [ 72.940434] but task is already holding lock:
> Jan 26 11:36:10 serveerstertje kernel: [ 72.952263] (&port->mutex){+.+.+.}, at: [<ffffffff81518aa7>] tty_port_open+0x67/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 72.958292]
> Jan 26 11:36:10 serveerstertje kernel: [ 72.958292] which lock already depends on the new lock.
> Jan 26 11:36:10 serveerstertje kernel: [ 72.958292]
> Jan 26 11:36:10 serveerstertje kernel: [ 72.976267]
> Jan 26 11:36:10 serveerstertje kernel: [ 72.976267] the existing dependency chain (in reverse order) is:
> Jan 26 11:36:10 serveerstertje kernel: [ 72.988276]
> Jan 26 11:36:10 serveerstertje kernel: [ 72.988276] -> #1 (&port->mutex){+.+.+.}:
> Jan 26 11:36:10 serveerstertje kernel: [ 73.000386] [<ffffffff81102dfd>] lock_acquire+0xcd/0x110
> Jan 26 11:36:10 serveerstertje kernel: [ 73.006526] [<ffffffff81ad3f97>] mutex_lock_nested+0x47/0x560
> Jan 26 11:36:10 serveerstertje kernel: [ 73.012612] [<ffffffff81518aa7>] tty_port_open+0x67/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.018637] [<ffffffff81aa4356>] rfcomm_tty_open+0x26/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.024674] [<ffffffff8150fcea>] tty_open+0x16a/0x5c0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.030748] [<ffffffff811b4013>] chrdev_open+0xa3/0x1c0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.036833] [<ffffffff811ad686>] do_dentry_open.isra.16+0x246/0x2f0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.043001] [<ffffffff811ad81d>] finish_open+0x1d/0x30
> Jan 26 11:36:10 serveerstertje kernel: [ 73.049106] [<ffffffff811befae>] do_last+0x7ce/0xdf0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.055191] [<ffffffff811bf68d>] path_openat+0xbd/0x6b0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.061211] [<ffffffff811c004e>] do_filp_open+0x3e/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.067177] [<ffffffff811aeaec>] do_sys_open+0x13c/0x230
> Jan 26 11:36:10 serveerstertje kernel: [ 73.073141] [<ffffffff811aebfd>] SyS_open+0x1d/0x20
> Jan 26 11:36:10 serveerstertje kernel: [ 73.079047] [<ffffffff81ad6f39>] system_call_fastpath+0x16/0x1b
> Jan 26 11:36:10 serveerstertje kernel: [ 73.084962]
> Jan 26 11:36:10 serveerstertje kernel: [ 73.084962] -> #0 (&tty->legacy_mutex){+.+.+.}:
> Jan 26 11:36:10 serveerstertje kernel: [ 73.096600] [<ffffffff8110230b>] __lock_acquire+0x1d4b/0x2220
> Jan 26 11:36:10 serveerstertje kernel: [ 73.102559] [<ffffffff81102dfd>] lock_acquire+0xcd/0x110
> Jan 26 11:36:10 serveerstertje kernel: [ 73.108475] [<ffffffff81ad3f97>] mutex_lock_nested+0x47/0x560
> Jan 26 11:36:10 serveerstertje kernel: [ 73.114419] [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.120354] [<ffffffff81ad63ab>] tty_lock+0xb/0x10
> Jan 26 11:36:10 serveerstertje kernel: [ 73.126258] [<ffffffff81aa4677>] rfcomm_dev_activate+0xb7/0x250
> Jan 26 11:36:10 serveerstertje kernel: [ 73.132222] [<ffffffff81518ad7>] tty_port_open+0x97/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.138195] [<ffffffff81aa4356>] rfcomm_tty_open+0x26/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.144207] [<ffffffff8150fcea>] tty_open+0x16a/0x5c0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.150164] [<ffffffff811b4013>] chrdev_open+0xa3/0x1c0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.156127] [<ffffffff811ad686>] do_dentry_open.isra.16+0x246/0x2f0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.162070] [<ffffffff811ad81d>] finish_open+0x1d/0x30
> Jan 26 11:36:10 serveerstertje kernel: [ 73.167933] [<ffffffff811befae>] do_last+0x7ce/0xdf0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.173787] [<ffffffff811bf68d>] path_openat+0xbd/0x6b0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.179600] [<ffffffff811c004e>] do_filp_open+0x3e/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.185302] [<ffffffff811aeaec>] do_sys_open+0x13c/0x230
> Jan 26 11:36:10 serveerstertje kernel: [ 73.190880] [<ffffffff811aebfd>] SyS_open+0x1d/0x20
> Jan 26 11:36:10 serveerstertje kernel: [ 73.196247] [<ffffffff81ad6f39>] system_call_fastpath+0x16/0x1b
> Jan 26 11:36:10 serveerstertje kernel: [ 73.201486]
> Jan 26 11:36:10 serveerstertje kernel: [ 73.201486] other info that might help us debug this:
> Jan 26 11:36:10 serveerstertje kernel: [ 73.201486]
> Jan 26 11:36:10 serveerstertje kernel: [ 73.216718] Possible unsafe locking scenario:
> Jan 26 11:36:10 serveerstertje kernel: [ 73.216718]
> Jan 26 11:36:10 serveerstertje kernel: [ 73.226933] CPU0 CPU1
> Jan 26 11:36:10 serveerstertje kernel: [ 73.231978] ---- ----
> Jan 26 11:36:10 serveerstertje kernel: [ 73.237001] lock(&port->mutex);
> Jan 26 11:36:10 serveerstertje kernel: [ 73.241994] lock(&tty->legacy_mutex);
> Jan 26 11:36:10 serveerstertje kernel: [ 73.247043] lock(&port->mutex);
> Jan 26 11:36:10 serveerstertje kernel: [ 73.251999] lock(&tty->legacy_mutex);
> Jan 26 11:36:10 serveerstertje kernel: [ 73.256902]
> Jan 26 11:36:10 serveerstertje kernel: [ 73.256902] *** DEADLOCK ***
> Jan 26 11:36:10 serveerstertje kernel: [ 73.256902]
> Jan 26 11:36:10 serveerstertje kernel: [ 73.270890] 1 lock held by zabbix_slimmeme/5909:
> Jan 26 11:36:10 serveerstertje kernel: [ 73.275398] #0: (&port->mutex){+.+.+.}, at: [<ffffffff81518aa7>] tty_port_open+0x67/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.280124]
> Jan 26 11:36:10 serveerstertje kernel: [ 73.280124] stack backtrace:
> Jan 26 11:36:10 serveerstertje kernel: [ 73.289130] CPU: 5 PID: 5909 Comm: zabbix_slimmeme Not tainted 3.13.0-20140125-mw-pcireset+ #1
> Jan 26 11:36:10 serveerstertje kernel: [ 73.293860] Hardware name: MSI MS-7640/890FXA-GD70 (MS-7640) , BIOS V1.8B1 09/13/2010
> Jan 26 11:36:10 serveerstertje kernel: [ 73.298625] ffffffff826e2b70 ffff88005858f818 ffffffff81acbcfa ffff880057c72300
> Jan 26 11:36:10 serveerstertje kernel: [ 73.303571] ffffffff826e2b70 ffff88005858f868 ffffffff81ac7011 ffff880057c72300
> Jan 26 11:36:10 serveerstertje kernel: [ 73.308511] ffff880057c72300 ffff88005858f868 ffff880057c72ac0 0000000000000000
> Jan 26 11:36:10 serveerstertje kernel: [ 73.313325] Call Trace:
> Jan 26 11:36:10 serveerstertje kernel: [ 73.318092] [<ffffffff81acbcfa>] dump_stack+0x46/0x58
> Jan 26 11:36:10 serveerstertje kernel: [ 73.322900] [<ffffffff81ac7011>] print_circular_bug+0x2f6/0x32a
> Jan 26 11:36:10 serveerstertje kernel: [ 73.327723] [<ffffffff8110230b>] __lock_acquire+0x1d4b/0x2220
> Jan 26 11:36:10 serveerstertje kernel: [ 73.332545] [<ffffffff810fedbd>] ? trace_hardirqs_on+0xd/0x10
> Jan 26 11:36:10 serveerstertje kernel: [ 73.337414] [<ffffffff810e6141>] ? finish_task_switch+0x41/0xf0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.342279] [<ffffffff81ad0244>] ? sleep_on_timeout+0x4/0x20
> Jan 26 11:36:10 serveerstertje kernel: [ 73.347128] [<ffffffff81102dfd>] lock_acquire+0xcd/0x110
> Jan 26 11:36:10 serveerstertje kernel: [ 73.351950] [<ffffffff81ad6344>] ? tty_lock_nested+0x44/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.356792] [<ffffffff81ad3f97>] mutex_lock_nested+0x47/0x560
> Jan 26 11:36:10 serveerstertje kernel: [ 73.361599] [<ffffffff81ad6344>] ? tty_lock_nested+0x44/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.366363] [<ffffffff810fec6b>] ? trace_hardirqs_on_caller+0xfb/0x240
> Jan 26 11:36:10 serveerstertje kernel: [ 73.371200] [<ffffffff810fedbd>] ? trace_hardirqs_on+0xd/0x10
> Jan 26 11:36:10 serveerstertje kernel: [ 73.376030] [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.380842] [<ffffffff81ad63ab>] tty_lock+0xb/0x10
> Jan 26 11:36:10 serveerstertje kernel: [ 73.385616] [<ffffffff81aa4677>] rfcomm_dev_activate+0xb7/0x250
> Jan 26 11:36:10 serveerstertje kernel: [ 73.390398] [<ffffffff81ad4287>] ? mutex_lock_nested+0x337/0x560
> Jan 26 11:36:10 serveerstertje kernel: [ 73.395154] [<ffffffff810f90f0>] ? __init_waitqueue_head+0x60/0x60
> Jan 26 11:36:10 serveerstertje kernel: [ 73.399861] [<ffffffff81518ad7>] tty_port_open+0x97/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.404552] [<ffffffff81aa4356>] rfcomm_tty_open+0x26/0xe0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.409263] [<ffffffff8150fcea>] tty_open+0x16a/0x5c0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.413954] [<ffffffff811b4013>] chrdev_open+0xa3/0x1c0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.418657] [<ffffffff81457bfd>] ? lockref_get+0x1d/0x30
> Jan 26 11:36:10 serveerstertje kernel: [ 73.423379] [<ffffffff811b3f70>] ? cdev_put+0x30/0x30
> Jan 26 11:36:10 serveerstertje kernel: [ 73.428056] [<ffffffff811ad686>] do_dentry_open.isra.16+0x246/0x2f0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.432768] [<ffffffff811ad81d>] finish_open+0x1d/0x30
> Jan 26 11:36:10 serveerstertje kernel: [ 73.437464] [<ffffffff811befae>] do_last+0x7ce/0xdf0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.442166] [<ffffffff811baff3>] ? inode_permission+0x13/0x50
> Jan 26 11:36:10 serveerstertje kernel: [ 73.446861] [<ffffffff811bb5ce>] ? link_path_walk+0x21e/0x880
> Jan 26 11:36:10 serveerstertje kernel: [ 73.451533] [<ffffffff810fec6b>] ? trace_hardirqs_on_caller+0xfb/0x240
> Jan 26 11:36:10 serveerstertje kernel: [ 73.456280] [<ffffffff811bf68d>] path_openat+0xbd/0x6b0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.461029] [<ffffffff8104cb03>] ? __do_page_fault+0x103/0x4e0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.465782] [<ffffffff81102e1d>] ? lock_acquire+0xed/0x110
> Jan 26 11:36:10 serveerstertje kernel: [ 73.470553] [<ffffffff811c004e>] do_filp_open+0x3e/0xa0
> Jan 26 11:36:10 serveerstertje kernel: [ 73.475321] [<ffffffff811cda31>] ? __alloc_fd+0xd1/0x120
> Jan 26 11:36:10 serveerstertje kernel: [ 73.480064] [<ffffffff811aeaec>] do_sys_open+0x13c/0x230
> Jan 26 11:36:10 serveerstertje kernel: [ 73.484743] [<ffffffff810fec6b>] ? trace_hardirqs_on_caller+0xfb/0x240
> Jan 26 11:36:10 serveerstertje kernel: [ 73.489470] [<ffffffff811aebfd>] SyS_open+0x1d/0x20
> Jan 26 11:36:10 serveerstertje kernel: [ 73.494191] [<ffffffff81ad6f39>] system_call_fastpath+0x16/0x1b
--
Best regards,
Sander mailto:linux@eikelenboom.it
^ permalink raw reply
* RE: possible bug in blueZ 5.8 gatt tool or library
From: Caleb Reinhold @ 2014-02-06 22:48 UTC (permalink / raw)
To: 'Anderson Lizardo'; +Cc: 'BlueZ development'
In-Reply-To: <CAJdJm_PEQEmCz1owo8MZ+29R-O5u8qm8x85WgeuKy9U1x74zGw@mail.gmail.com>
Hi Anderson,
Thanks for your advice. Connecting to the device on low security and then
switching to medium does allow gatttool to receive and confirm the
indication.
Our interest in gatttool is mainly as a demonstration of BlueZ's GATT API.
Our own GATT client application borrows heavily from gatttool and adds
features such as support for multiple simultaneous connections.
It seemed that calling g_attrib_register() in the connection callback might
be causing the client to start listening for indications and notifications
too late, but registering right after the gatt_connect() call doesn't seem
to help. Nor does placing a watch on the GIOChannel inside bt_io_connect(),
so registering earlier doesn't appear to be the right approach. Do you know
why we keep missing this initial indication on medium security, and how we
might fix this issue?
Thanks for your time,
Tom Harada
-----Original Message-----
From: Anderson Lizardo [mailto:anderson.lizardo@openbossa.org]
Sent: Tuesday, February 04, 2014 6:06 PM
To: Caleb Reinhold
Cc: BlueZ development
Subject: Re: possible bug in blueZ 5.8 gatt tool or library
Hi Caleb,
On Tue, Feb 4, 2014 at 5:12 PM, Caleb Reinhold
<creinhold@lampreynetworks.com> wrote:
> We are working with the 5.8 version of the library, kernel version
> 3.12.9, bluetoothctl, and gatttool when we encountered a possible error.
> We expected on the reconnection of two bonded devices, one of which
> had stored measurements, that data would transfer. When running gatt
> tool in medium security the first measurement to be indicated was lost.
First of all, gatttool is a developer tool, and it is far from being a
compliant GATT endpoint (e.g. it does not report to requests, which is
mandatory by the spec). With moderate effort though, the missing features
can be added.
> However upon attempting to reconnect to the simulated agent device
> with medium security two unexpected behaviors occurred. First, and
> more immediately apparent was that the simulated agent did not receive
> a confirmation of the indication. A slightly closer look using the
> hcidump, trying to find what had happened, showed that the indication
> had arrived at the hci layer but was not received at events_handler.
Are you using gatttool in interactive mode (i.e. the -I option) ? If yes,
try first connecting to the device with "connect" followed by setting the
security level to medium with "sec-level medium". This will imitate the
behavior of the BlueZ daemon when connecting to LE devices. Also be sure to
use the "--listen" option so the confirmation is sent by gatttool.
Let us know if it works :)
> While the indication
> is sent very swiftly upon the reconnection of the devices we
> understand this to be the manner in which low energy devices are
> supposed to behave given stored measurements and a bonded device.
You are correct that this is the expected behavior. But gatttool is far from
perfect. Did you try implementing a BlueZ plugin?
Best Regards,
--
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil
--
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
* FW: How to install bluez in Linux mint
From: Eric Shields @ 2014-02-06 22:21 UTC (permalink / raw)
To: linux-bluetooth
Sorry about that. No idea you didn't accept html. Below is the original
message in plain text, as is the rest of this email. I would NEVER be so
mean as to even attempt to send a virus or junk through your system. I just
need help, that's all. I shouldn't have used Gmail. Isn't configured for
plain text.
Thank you,
Eric Shields
Sent with Microsoft Outlook 2003
________________________________________
From: Eric Shields [mailto:skyvaleden0120@gmail.com]
Sent: Thursday, February 06, 2014 4:18 PM
To: linux-bluetooth@vger.kernel.org
Subject: How to install bluez in Linux mint
Hello, I am new to Linux but familiar with Android so I was wondering if any
help can be lent (so I can configure my Bluetooth adapter to be recognized
as a network adapter)? Please get back to me whenever possible.
Eric Shields
Sent via my Galaxy S Relay
via Gmail App
^ permalink raw reply
* [PATCH 6/6] android/a2dp: Fix audio deregistration
From: Andrzej Kaczmarek @ 2014-02-06 17:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391709250-8047-1-git-send-email-andrzej.kaczmarek@tieto.com>
Unregistering a SEP can trigger abort_cfm callback if some device is
connected thus we should free setups list before all endpoints are
unregistered to avoid error in abort_cfm due to non-existing setup.
---
android/a2dp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/android/a2dp.c b/android/a2dp.c
index f67a593..7a2f3cf 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -1483,12 +1483,12 @@ static void bt_audio_unregister(void)
if (audio_retry_id > 0)
g_source_remove(audio_retry_id);
- g_slist_free_full(setups, setup_free);
- setups = NULL;
-
g_slist_free_full(endpoints, unregister_endpoint);
endpoints = NULL;
+ g_slist_free_full(setups, setup_free);
+ setups = NULL;
+
audio_ipc_cleanup();
}
--
1.8.5.3
^ permalink raw reply related
* [PATCH 5/6] android/a2dp: Disconnect headset on IPC failure
From: Andrzej Kaczmarek @ 2014-02-06 17:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391709250-8047-1-git-send-email-andrzej.kaczmarek@tieto.com>
In case audio IPC is suddenly disconnected (most likely due to crash of
mediaserver process) we should disconnect headset since it is no longer
associated with valid setup and cannot be used properly.
---
android/a2dp.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/android/a2dp.c b/android/a2dp.c
index 8eabfeb..f67a593 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -1515,6 +1515,7 @@ static gboolean audio_retry_register(void *data)
static void audio_disconnected(void *data)
{
+ GSList *l;
bool restart;
DBG("");
@@ -1526,6 +1527,12 @@ static void audio_disconnected(void *data)
bt_audio_unregister();
+ for (l = devices; l; l = g_slist_next(l)) {
+ struct a2dp_device *dev = l->data;
+
+ avdtp_shutdown(dev->session);
+ }
+
if (!restart)
return;
--
1.8.5.3
^ permalink raw reply related
* [PATCH 4/6] android/hal-audio: Write SBC parameters to logcat
From: Andrzej Kaczmarek @ 2014-02-06 17:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391709250-8047-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
android/hal-audio.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index 766327b..9312659 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -289,6 +289,78 @@ static int sbc_get_presets(struct audio_preset *preset, size_t *len)
return i;
}
+static int sbc_freq2int(uint8_t freq)
+{
+ switch (freq) {
+ case SBC_SAMPLING_FREQ_16000:
+ return 16000;
+ case SBC_SAMPLING_FREQ_32000:
+ return 32000;
+ case SBC_SAMPLING_FREQ_44100:
+ return 44100;
+ case SBC_SAMPLING_FREQ_48000:
+ return 48000;
+ default:
+ return 0;
+ }
+}
+
+static const char *sbc_mode2str(uint8_t mode)
+{
+ switch (mode) {
+ case SBC_CHANNEL_MODE_MONO:
+ return "Mono";
+ case SBC_CHANNEL_MODE_DUAL_CHANNEL:
+ return "DualChannel";
+ case SBC_CHANNEL_MODE_STEREO:
+ return "Stereo";
+ case SBC_CHANNEL_MODE_JOINT_STEREO:
+ return "JointStereo";
+ default:
+ return "(unknown)";
+ }
+}
+
+static int sbc_blocks2int(uint8_t blocks)
+{
+ switch (blocks) {
+ case SBC_BLOCK_LENGTH_4:
+ return 4;
+ case SBC_BLOCK_LENGTH_8:
+ return 8;
+ case SBC_BLOCK_LENGTH_12:
+ return 12;
+ case SBC_BLOCK_LENGTH_16:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+static int sbc_subbands2int(uint8_t subbands)
+{
+ switch (subbands) {
+ case SBC_SUBBANDS_4:
+ return 4;
+ case SBC_SUBBANDS_8:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+static const char *sbc_allocation2str(uint8_t allocation)
+{
+ switch (allocation) {
+ case SBC_ALLOCATION_SNR:
+ return "SNR";
+ case SBC_ALLOCATION_LOUDNESS:
+ return "Loudness";
+ default:
+ return "(unknown)";
+ }
+}
+
static void sbc_init_encoder(struct sbc_data *sbc_data)
{
a2dp_sbc_t *in = &sbc_data->sbc;
@@ -298,6 +370,15 @@ static void sbc_init_encoder(struct sbc_data *sbc_data)
out->endian = SBC_LE;
out->bitpool = in->max_bitpool;
+
+ DBG("frequency=%d channel_mode=%s block_length=%d subbands=%d "
+ "allocation=%s bitpool=%d-%d",
+ sbc_freq2int(in->frequency),
+ sbc_mode2str(in->channel_mode),
+ sbc_blocks2int(in->block_length),
+ sbc_subbands2int(in->subbands),
+ sbc_allocation2str(in->allocation_method),
+ in->min_bitpool, in->max_bitpool);
}
static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
--
1.8.5.3
^ permalink raw reply related
* [PATCH 3/6] android/hal-audio: Ignore write call when closing
From: Andrzej Kaczmarek @ 2014-02-06 17:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391709250-8047-1-git-send-email-andrzej.kaczmarek@tieto.com>
We should not try to neither auto-resume nor write when state is set to
NONE as this is case when we're being closed and it's ok do ignore
write request.
---
android/hal-audio.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index efdf823..766327b 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -831,6 +831,10 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
{
struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+ /* just return in case we're closing */
+ if (out->audio_state == AUDIO_A2DP_STATE_NONE)
+ return -1;
+
/* We can auto-start only from standby */
if (out->audio_state == AUDIO_A2DP_STATE_STANDBY) {
DBG("stream in standby, auto-start");
--
1.8.5.3
^ permalink raw reply related
* [PATCH 2/6] android/a2dp: Notify audio state on SEP close
From: Andrzej Kaczmarek @ 2014-02-06 17:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391709250-8047-1-git-send-email-andrzej.kaczmarek@tieto.com>
---
android/a2dp.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/android/a2dp.c b/android/a2dp.c
index 8d6e7bf..8eabfeb 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -990,6 +990,8 @@ static gboolean sep_close_ind(struct avdtp *session,
return FALSE;
}
+ bt_audio_notify_state(setup, HAL_AUDIO_STOPPED);
+
setup_remove(setup);
return TRUE;
@@ -1163,6 +1165,7 @@ static void sep_close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
void *user_data)
{
struct a2dp_endpoint *endpoint = user_data;
+ struct a2dp_setup *setup;
DBG("");
@@ -1171,7 +1174,16 @@ static void sep_close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
return;
}
- setup_remove_by_id(endpoint->id);
+ setup = find_setup(endpoint->id);
+ if (!setup) {
+ error("Unable to find stream setup for %u endpoint",
+ endpoint->id);
+ return;
+ }
+
+ bt_audio_notify_state(setup, HAL_AUDIO_STOPPED);
+
+ setup_remove(setup);
}
static void sep_abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
--
1.8.5.3
^ permalink raw reply related
* [PATCH 1/6] android/a2dp: Close AVDTP gracefully
From: Andrzej Kaczmarek @ 2014-02-06 17:54 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andrzej Kaczmarek
When closing AVDTP we should wait for for CLOSE request to complete
(so stream go to idle state) before disconnecting signalling socket.
In case CLOSE is rejected, we simply abort stream.
---
android/a2dp.c | 4 +++-
android/avdtp.c | 21 +++++++++++++++++----
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/android/a2dp.c b/android/a2dp.c
index 8cff535..8d6e7bf 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -1166,8 +1166,10 @@ static void sep_close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
DBG("");
- if (err)
+ if (err) {
+ avdtp_abort(session, stream);
return;
+ }
setup_remove_by_id(endpoint->id);
}
diff --git a/android/avdtp.c b/android/avdtp.c
index e26d6ec..b9d1992 100644
--- a/android/avdtp.c
+++ b/android/avdtp.c
@@ -398,6 +398,8 @@ struct avdtp {
struct pending_req *req;
GSList *disconnect;
+
+ bool shutdown;
};
static GSList *lseps = NULL;
@@ -913,6 +915,11 @@ static void avdtp_sep_set_state(struct avdtp *session,
session->streams = g_slist_remove(session->streams, stream);
stream_free(stream);
}
+
+ if (session->io && session->shutdown && session->streams == NULL) {
+ int sock = g_io_channel_unix_get_fd(session->io);
+ shutdown(sock, SHUT_RDWR);
+ }
}
static void finalize_discovery(struct avdtp *session, int err)
@@ -2141,7 +2148,7 @@ gboolean avdtp_remove_disconnect_cb(struct avdtp *session, unsigned int id)
void avdtp_shutdown(struct avdtp *session)
{
GSList *l;
- int sock;
+ bool closing = false;
if (!session->io)
return;
@@ -2149,12 +2156,18 @@ void avdtp_shutdown(struct avdtp *session)
for (l = session->streams; l; l = g_slist_next(l)) {
struct avdtp_stream *stream = l->data;
- avdtp_close(session, stream, TRUE);
+ if (avdtp_close(session, stream, TRUE) == 0)
+ closing = true;
}
- sock = g_io_channel_unix_get_fd(session->io);
+ if (closing) {
+ /* defer shutdown until all streams closed */
+ session->shutdown = true;
+ } else {
+ int sock = g_io_channel_unix_get_fd(session->io);
- shutdown(sock, SHUT_RDWR);
+ shutdown(sock, SHUT_RDWR);
+ }
}
static void queue_request(struct avdtp *session, struct pending_req *req,
--
1.8.5.3
^ permalink raw reply related
* [RFC v8 06/10] Bluetooth: Introduce LE auto connection infrastructure
From: Andre Guedes @ 2014-02-06 17:35 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <20140206160209.GA26623@molly>
This patch introduces the LE auto connection infrastructure which
will be used to implement the LE auto connection options.
In summary, the auto connection mechanism works as follows: Once the
first pending LE connection is created, the background scanning is
started. When the target device is found in range, the kernel
autonomously starts the connection attempt. If connection is
established successfully, that pending LE connection is deleted and
the background is stopped.
To achieve that, this patch introduces the hci_update_background_scan()
which controls the background scanning state. This function starts or
stops the background scanning based on the hdev->pend_le_conns list. If
there is no pending LE connection, the background scanning is stopped.
Otherwise, we start the background scanning.
Then, every time a pending LE connection is added we call hci_update_
background_scan() so the background scanning is started (in case it is
not already running). Likewise, every time a pending LE connection is
deleted we call hci_update_background_scan() so the background scanning
is stopped (in case this was the last pending LE connection) or it is
started again (in case we have more pending LE connections). Finally,
we also call hci_update_background_scan() in hci_le_conn_failed() so
the background scan is restarted in case the connection establishment
fails. This way the background scanning keeps running until all pending
LE connection are established.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
include/net/bluetooth/hci_core.h | 2 +
net/bluetooth/hci_conn.c | 5 +++
net/bluetooth/hci_core.c | 83 +++++++++++++++++++++++++++++++++++++++-
net/bluetooth/hci_event.c | 44 +++++++++++++++++++++
4 files changed, 132 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 7b9c4ed..3c8dc0f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -778,6 +778,8 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
void hci_pend_le_conns_clear(struct hci_dev *hdev);
+void hci_update_background_scan(struct hci_dev *hdev);
+
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 70f4226..f3ca73f 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -527,6 +527,11 @@ void hci_le_conn_failed(struct hci_conn *conn, u8 status)
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
+
+ /* Since we may have temporarily stopped the background scanning in
+ * favor of connection establishment, we should restart it.
+ */
+ hci_update_background_scan(hdev);
}
static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0f670bc..ff85205 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3021,7 +3021,7 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
if (entry)
- return;
+ goto done;
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
@@ -3035,6 +3035,9 @@ void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
list_add(&entry->list, &hdev->pend_le_conns);
BT_DBG("addr %pMR (type %u)", addr, addr_type);
+
+done:
+ hci_update_background_scan(hdev);
}
/* This function requires the caller holds hdev->lock */
@@ -3044,12 +3047,15 @@ void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
if (!entry)
- return;
+ goto done;
list_del(&entry->list);
kfree(entry);
BT_DBG("addr %pMR (type %u)", addr, addr_type);
+
+done:
+ hci_update_background_scan(hdev);
}
/* This function requires the caller holds hdev->lock */
@@ -4597,3 +4603,76 @@ void hci_stop_le_scan_req(struct hci_request *req)
cp.enable = LE_SCAN_DISABLE;
hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
}
+
+static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+ if (status)
+ BT_DBG("HCI request failed to update background scanning: "
+ "status 0x%2.2x", status);
+}
+
+/* This function controls the background scanning based on hdev->pend_le_conns
+ * list. If there are pending LE connection we start the background scanning,
+ * otherwise we stop it.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+void hci_update_background_scan(struct hci_dev *hdev)
+{
+ struct hci_cp_le_set_scan_param param_cp;
+ struct hci_cp_le_set_scan_enable enable_cp;
+ struct hci_request req;
+ struct hci_conn *conn;
+ int err;
+
+ hci_req_init(&req, hdev);
+
+ if (list_empty(&hdev->pend_le_conns)) {
+ /* If there is no pending LE connections, we should stop
+ * the background scanning.
+ */
+
+ /* If controller is not scanning we are done. */
+ if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return;
+
+ hci_stop_le_scan_req(&req);
+
+ BT_DBG("%s stopping background scanning", hdev->name);
+ } else {
+ /* If there is at least one pending LE connection, we should
+ * keep the background scan running.
+ */
+
+ /* If controller is already scanning we are done. */
+ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+ return;
+
+ /* If controller is connecting, we should not start scanning
+ * since some controllers are not able to scan and connect at
+ * the same time.
+ */
+ conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+ if (conn)
+ return;
+
+ memset(¶m_cp, 0, sizeof(param_cp));
+ param_cp.type = LE_SCAN_PASSIVE;
+ param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
+ param_cp.window = cpu_to_le16(hdev->le_scan_window);
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+ ¶m_cp);
+
+ memset(&enable_cp, 0, sizeof(enable_cp));
+ enable_cp.enable = LE_SCAN_ENABLE;
+ enable_cp.filter_dup = LE_SCAN_FILTER_DUP_DISABLE;
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+ &enable_cp);
+
+ BT_DBG("%s starting background scanning", hdev->name);
+ }
+
+ err = hci_req_run(&req, update_background_scan_complete);
+ if (err)
+ BT_ERR("Failed to run HCI request: err %d", err);
+}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index df58cde..5796c06 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3620,25 +3620,69 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_proto_connect_cfm(conn, ev->status);
+ hci_pend_le_conn_del(hdev, &ev->bdaddr, ev->bdaddr_type);
+
unlock:
hci_dev_unlock(hdev);
}
+/* This function requires the caller holds hdev->lock */
+static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type)
+{
+ struct hci_conn *conn;
+ u8 bdaddr_type;
+
+ if (!hci_pend_le_conn_lookup(hdev, addr, addr_type))
+ return;
+
+ if (addr_type == ADDR_LE_DEV_PUBLIC)
+ bdaddr_type = BDADDR_LE_PUBLIC;
+ else
+ bdaddr_type = BDADDR_LE_RANDOM;
+
+ conn = hci_connect(hdev, LE_LINK, addr, bdaddr_type, BT_SECURITY_LOW,
+ HCI_AT_NO_BONDING);
+ if (!IS_ERR(conn))
+ return;
+
+ switch (PTR_ERR(conn)) {
+ case -EBUSY:
+ /* If hci_connect() returns -EBUSY it means there is already
+ * an LE connection attempt going on. Since controllers don't
+ * support more than one connection attempt at the time, we
+ * don't consider this an error case.
+ */
+ break;
+ default:
+ BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
+ }
+}
+
static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
u8 num_reports = skb->data[0];
void *ptr = &skb->data[1];
s8 rssi;
+ hci_dev_lock(hdev);
+
while (num_reports--) {
struct hci_ev_le_advertising_info *ev = ptr;
+ if (ev->evt_type == LE_ADV_IND ||
+ ev->evt_type == LE_ADV_DIRECT_IND)
+ check_pending_le_conn(hdev, &ev->bdaddr,
+ ev->bdaddr_type);
+
rssi = ev->data[ev->length];
mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
NULL, rssi, 0, 1, ev->data, ev->length);
ptr += sizeof(*ev) + ev->length + 1;
}
+
+ hci_dev_unlock(hdev);
}
static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
--
1.8.5.3
^ permalink raw reply related
* Re: [RFC v8 06/10] Bluetooth: Introduce LE auto connection infrastructure
From: Andre Guedes @ 2014-02-06 17:34 UTC (permalink / raw)
To: Vinicius Costa Gomes; +Cc: linux-bluetooth
In-Reply-To: <20140206160209.GA26623@molly>
Hi Vinicius,
On Thu, 2014-02-06 at 14:02 -0200, Vinicius Costa Gomes wrote:
> Hi Andre,
>
> On 19:23 Wed 05 Feb, Andre Guedes wrote:
> > This patch introduces the LE auto connection infrastructure which
> > will be used to implement the LE auto connection options.
> >
> > In summary, the auto connection mechanism works as follows: Once the
> > first pending LE connection is created, the background scanning is
> > started. When the target device is found in range, the kernel
> > autonomously starts the connection attempt. If connection is
> > established successfully, that pending LE connection is deleted and
> > the background is stopped.
> >
> > To achieve that, this patch introduces the hci_update_background_scan()
> > which controls the background scanning state. This function starts or
> > stops the background scanning based on the hdev->pend_le_conns list. If
> > there is no pending LE connection, the background scanning is stopped.
> > Otherwise, we start the background scanning.
> >
> > Then, every time a pending LE connection is added we call hci_update_
> > background_scan() so the background scanning is started (in case it is
> > not already running). Likewise, every time a pending LE connection is
> > deleted we call hci_update_background_scan() so the background scanning
> > is stopped (in case this was the last pending LE connection) or it is
> > started again (in case we have more pending LE connections). Finally,
> > we also call hci_update_background_scan() in hci_le_conn_failed() so
> > the background scan is restarted in case the connection establishment
> > fails. This way the background scanning keeps running until all pending
> > LE connection are established.
> >
> > Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> > ---
>
> [snip]
>
> > static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
> > {
> > u8 num_reports = skb->data[0];
> > void *ptr = &skb->data[1];
> > s8 rssi;
> >
> > + hci_dev_lock(hdev);
> > +
> > while (num_reports--) {
> > struct hci_ev_le_advertising_info *ev = ptr;
> >
> > + check_pending_le_conn(hdev, &ev->bdaddr, ev->bdaddr_type);
> > +
>
> Shouldn't the event type be checked to see if it is a connectable event?
Sure. I'm fixing it.
Thanks,
Andre
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox