Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC v6 12/14] Bluetooth: Auto connection and power on
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

When hdev is closed (e.g. Mgmt power off command, RFKILL or controller
is reset), the ongoing active connections are silently dropped by the
controller (no Disconnection Complete Event is sent to host). For that
reason, the devices that require HCI_AUTO_CONN_ALWAYS are not added to
hdev->pend_le_conns list and they won't auto connect.

So to fix this issue, during hdev closing, we remove all pending LE
connections. After adapter is powered on, we add a pending LE connection
for each HCI_AUTO_CONN_ALWAYS address.

This way, the auto connection mechanism works propely after a power
off and power on sequence as well as RFKILL block/unblock.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c |  1 +
 net/bluetooth/mgmt.c     | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cc9053d..9dba381 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2100,6 +2100,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 	hci_dev_lock(hdev);
 	hci_inquiry_cache_flush(hdev);
 	hci_conn_hash_flush(hdev);
+	hci_pend_le_conns_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_notify(hdev, HCI_DEV_DOWN);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8026e5f..31acc44 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4358,6 +4358,17 @@ void mgmt_index_removed(struct hci_dev *hdev)
 	mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
 }
 
+/* This function requires the caller holds hdev->lock */
+static void restart_le_auto_conns(struct hci_dev *hdev)
+{
+	struct hci_conn_params *p;
+
+	list_for_each_entry(p, &hdev->le_conn_params, list) {
+		if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
+			hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
+	}
+}
+
 static void powered_complete(struct hci_dev *hdev, u8 status)
 {
 	struct cmd_lookup match = { NULL, hdev };
@@ -4366,6 +4377,8 @@ static void powered_complete(struct hci_dev *hdev, u8 status)
 
 	hci_dev_lock(hdev);
 
+	restart_le_auto_conns(hdev);
+
 	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
 
 	new_settings(hdev, match.sk);
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 11/14] Bluetooth: Temporarily stop background scanning on discovery
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

If the user sends a mgmt start discovery command while the background
scanning is running, we should temporarily stop it. Once the discovery
finishes, we start the background scanning again.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_core.c |  2 ++
 net/bluetooth/mgmt.c     | 12 ++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c3ebd51..cc9053d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1629,6 +1629,8 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
 
 	switch (state) {
 	case DISCOVERY_STOPPED:
+		hci_update_background_scan(hdev);
+
 		if (hdev->discovery.state != DISCOVERY_STARTING)
 			mgmt_discovering(hdev, 0);
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index bde8e67..8026e5f 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3316,11 +3316,15 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 			goto failed;
 		}
 
+		/* If controller is scanning, it means the background scanning
+		 * is running. Thus, we should temporarily stop it in order to
+		 * set the discovery scanning parameters.
+		 */
 		if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
-			err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-					 MGMT_STATUS_BUSY);
-			mgmt_pending_remove(cmd);
-			goto failed;
+			memset(&enable_cp, 0, sizeof(enable_cp));
+			enable_cp.enable = LE_SCAN_DISABLE;
+			hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE,
+				    sizeof(enable_cp), &enable_cp);
 		}
 
 		memset(&param_cp, 0, sizeof(param_cp));
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 10/14] Bluetooth: Re-enable background scan in case of error
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

Since we temporarily stop the background scanning in favor of
connection, we should re-enable it in case something goes wrong
with connection establishment. So this patch adds a hci_update_
background_scan() call in fail_conn_attempt() and hci_le_conn_
complete_evt() error flow.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c  | 2 ++
 net/bluetooth/hci_event.c | 1 +
 2 files changed, 3 insertions(+)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 573b28d..6bdc349 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -527,6 +527,8 @@ static void le_conn_failed(struct hci_conn *conn, u8 status)
 	hci_proto_connect_cfm(conn, status);
 
 	hci_conn_del(conn);
+
+	hci_update_background_scan(hdev);
 }
 
 static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f9633ac..8f4686a 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3595,6 +3595,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_proto_connect_cfm(conn, ev->status);
 		conn->state = BT_CLOSED;
 		hci_conn_del(conn);
+		hci_update_background_scan(hdev);
 		goto unlock;
 	}
 
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 09/14] Bluetooth: Introduce LE auto connection infrastructure
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch introduces the LE auto connection infrastructure.
This infrastructure will be used to implement the auto_connect
options from hci_conn_params.

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). This way
the background scanning keeps running until all pending LE connection
are established.

When a device with pending connection is in range, we establish the
connection and delete the pending connection.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  2 +
 net/bluetooth/hci_core.c         | 86 +++++++++++++++++++++++++++++++++++++++-
 net/bluetooth/hci_event.c        | 41 +++++++++++++++++++
 3 files changed, 127 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5dc749d..f88bddf 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -782,6 +782,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_core.c b/net/bluetooth/hci_core.c
index ef9e105..c3ebd51 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3033,7 +3033,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) {
@@ -3047,6 +3047,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 */
@@ -3056,12 +3059,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 */
@@ -4603,3 +4609,79 @@ static void hci_cmd_work(struct work_struct *work)
 		}
 	}
 }
+
+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;
+
+		memset(&enable_cp, 0, sizeof(enable_cp));
+		enable_cp.enable = LE_SCAN_DISABLE;
+		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+			    &enable_cp);
+
+		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(&param_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),
+			    &param_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 8c44bbe..f9633ac 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3613,25 +3613,66 @@ 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_ERR("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;
 
+		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

* [RFC v6 08/14] Bluetooth: Introduce hdev->pend_le_conn list
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch introduces the hdev->pend_le_conn list which holds the
device addresses the kernel should autonomously connect. It also
introduces some helper functions to manipulate the list.

The list and helper functions will be used by the next patch which
implements the LE auto connection infrastructure.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h |  7 +++++
 net/bluetooth/hci_core.c         | 68 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f757b3f..5dc749d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -270,6 +270,7 @@ struct hci_dev {
 	struct list_head	long_term_keys;
 	struct list_head	remote_oob_data;
 	struct list_head	le_conn_params;
+	struct list_head	pend_le_conns;
 
 	struct hci_dev_stats	stat;
 
@@ -775,6 +776,12 @@ void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
 void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_clear(struct hci_dev *hdev);
 
+struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
+					    bdaddr_t *addr, u8 addr_type);
+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);
+
 int hci_uuids_clear(struct hci_dev *hdev);
 
 int hci_link_keys_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 672486f..ef9e105 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3011,6 +3011,72 @@ void hci_conn_params_clear(struct hci_dev *hdev)
 	BT_DBG("All LE connection parameters were removed");
 }
 
+/* This function requires the caller holds hdev->lock */
+struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev,
+					    bdaddr_t *addr, u8 addr_type)
+{
+	struct bdaddr_list *entry;
+
+	list_for_each_entry(entry, &hdev->pend_le_conns, list) {
+		if (bacmp(&entry->bdaddr, addr) == 0 &&
+		    entry->bdaddr_type == addr_type)
+			return entry;
+	}
+
+	return NULL;
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+	struct bdaddr_list *entry;
+
+	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
+	if (entry)
+		return;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		BT_ERR("Out of memory");
+		return;
+	}
+
+	bacpy(&entry->bdaddr, addr);
+	entry->bdaddr_type = addr_type;
+
+	list_add(&entry->list, &hdev->pend_le_conns);
+
+	BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+	struct bdaddr_list *entry;
+
+	entry = hci_pend_le_conn_lookup(hdev, addr, addr_type);
+	if (!entry)
+		return;
+
+	list_del(&entry->list);
+	kfree(entry);
+
+	BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_conns_clear(struct hci_dev *hdev)
+{
+	struct bdaddr_list *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &hdev->pend_le_conns, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+
+	BT_DBG("All LE pending connections cleared");
+}
+
 static void inquiry_complete(struct hci_dev *hdev, u8 status)
 {
 	if (status) {
@@ -3122,6 +3188,7 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_LIST_HEAD(&hdev->long_term_keys);
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
 	INIT_LIST_HEAD(&hdev->le_conn_params);
+	INIT_LIST_HEAD(&hdev->pend_le_conns);
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
 
 	INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -3308,6 +3375,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
 	hci_smp_ltks_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
 	hci_conn_params_clear(hdev);
+	hci_pend_le_conns_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_dev_put(hdev);
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 07/14] Bluetooth: Remove unused function
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch removes hci_create_le_conn() since it is not used anymore.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c | 32 --------------------------------
 1 file changed, 32 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 66f77a2..573b28d 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -551,38 +551,6 @@ done:
 	hci_dev_unlock(hdev);
 }
 
-static int hci_create_le_conn(struct hci_conn *conn)
-{
-	struct hci_dev *hdev = conn->hdev;
-	struct hci_cp_le_create_conn cp;
-	struct hci_request req;
-	int err;
-
-	hci_req_init(&req, hdev);
-
-	memset(&cp, 0, sizeof(cp));
-	cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
-	cp.scan_window = cpu_to_le16(hdev->le_scan_window);
-	bacpy(&cp.peer_addr, &conn->dst);
-	cp.peer_addr_type = conn->dst_type;
-	cp.own_address_type = conn->src_type;
-	cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
-	cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
-	cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
-	cp.min_ce_len = __constant_cpu_to_le16(0x0000);
-	cp.max_ce_len = __constant_cpu_to_le16(0x0000);
-
-	hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
-
-	err = hci_req_run(&req, create_le_conn_complete);
-	if (err) {
-		hci_conn_del(conn);
-		return err;
-	}
-
-	return 0;
-}
-
 static void create_le_conn_req(struct hci_request *req, struct hci_conn *conn)
 {
 	struct hci_cp_le_create_conn cp;
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 06/14] Bluetooth: Stop scanning on LE connection
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

Some LE controllers don't support scanning and creating a connection
at the same time. So we should always stop scanning in order to
establish the connection.

Since we may prematurely stop the discovery procedure in favor of
the connection establishment, we should also cancel hdev->le_scan_
disable delayed work and set the discovery state to DISCOVERY_STOPPED.

This change does a small improvement since it is not mandatory the
user stops scanning before connecting anymore. Moreover, this change
is required by upcoming LE auto connection mechanism in order to work
properly with controllers that don't support background scanning and
connection establishment at the same time.

In future, we might want to do a small optimization by checking if
controller is able to scan and connect at the same time. For now,
we want the simplest approach so we always stop scanning (even if
the controller is able to carry out both operations).

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/hci_conn.c    | 84 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 232c078..1e486a9 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -348,6 +348,7 @@ enum {
 
 /* ---- HCI Error Codes ---- */
 #define HCI_ERROR_AUTH_FAILURE		0x05
+#define HCI_ERROR_MEMORY_EXCEEDED	0x07
 #define HCI_ERROR_CONNECTION_TIMEOUT	0x08
 #define HCI_ERROR_REJ_BAD_ADDR		0x0f
 #define HCI_ERROR_REMOTE_USER_TERM	0x13
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 914d7f5..66f77a2 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -583,11 +583,71 @@ static int hci_create_le_conn(struct hci_conn *conn)
 	return 0;
 }
 
+static void create_le_conn_req(struct hci_request *req, struct hci_conn *conn)
+{
+	struct hci_cp_le_create_conn cp;
+	struct hci_dev *hdev = conn->hdev;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
+	cp.scan_window = cpu_to_le16(hdev->le_scan_window);
+	bacpy(&cp.peer_addr, &conn->dst);
+	cp.peer_addr_type = conn->dst_type;
+	cp.own_address_type = conn->src_type;
+	cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
+	cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
+	cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
+	cp.min_ce_len = __constant_cpu_to_le16(0x0000);
+	cp.max_ce_len = __constant_cpu_to_le16(0x0000);
+
+	hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+}
+
+static void stop_scan_complete(struct hci_dev *hdev, u8 status)
+{
+	struct hci_request req;
+	struct hci_conn *conn;
+	int err;
+
+	conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+	if (!conn)
+		return;
+
+	if (status) {
+		BT_DBG("HCI request failed to stop scanning: status 0x%2.2x",
+		       status);
+
+		hci_dev_lock(hdev);
+		le_conn_failed(conn, status);
+		hci_dev_unlock(hdev);
+		return;
+	}
+
+	/* Since we may have prematurely stopped discovery procedure, we should
+	 * update discovery state.
+	 */
+	cancel_delayed_work(&hdev->le_scan_disable);
+	hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+
+	hci_req_init(&req, hdev);
+
+	create_le_conn_req(&req, conn);
+
+	err = hci_req_run(&req, create_le_conn_complete);
+	if (err) {
+		hci_dev_lock(hdev);
+		le_conn_failed(conn, HCI_ERROR_MEMORY_EXCEEDED);
+		hci_dev_unlock(hdev);
+		return;
+	}
+}
+
 static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 				    u8 dst_type, u8 sec_level, u8 auth_type)
 {
 	struct hci_conn_params *params;
 	struct hci_conn *conn;
+	struct hci_request req;
 	int err;
 
 	if (test_bit(HCI_ADVERTISING, &hdev->flags))
@@ -643,9 +703,29 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 		conn->le_conn_max_interval = hdev->le_conn_max_interval;
 	}
 
-	err = hci_create_le_conn(conn);
-	if (err)
+	hci_req_init(&req, hdev);
+
+	/* If controller is scanning, we stop it since some controllers are
+	 * not able to scan and connect at the same time.
+	 */
+	if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
+		struct hci_cp_le_set_scan_enable cp;
+
+		memset(&cp, 0, sizeof(cp));
+		cp.enable = LE_SCAN_DISABLE;
+		hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+
+		err = hci_req_run(&req, stop_scan_complete);
+	} else {
+		create_le_conn_req(&req, conn);
+
+		err = hci_req_run(&req, create_le_conn_complete);
+	}
+
+	if (err) {
+		hci_conn_del(conn);
 		return ERR_PTR(err);
+	}
 
 done:
 	hci_conn_hold(conn);
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 05/14] Bluetooth: Introduce le_conn_failed() helper
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch moves connection attempt failure code to its own function
so it can be reused in the next patch.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 4d1ce74..914d7f5 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -514,6 +514,21 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
 }
 EXPORT_SYMBOL(hci_get_route);
 
+/* This function requires the caller holds hdev->lock */
+static void le_conn_failed(struct hci_conn *conn, u8 status)
+{
+	struct hci_dev *hdev = conn->hdev;
+
+	conn->state = BT_CLOSED;
+
+	mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type,
+			    status);
+
+	hci_proto_connect_cfm(conn, status);
+
+	hci_conn_del(conn);
+}
+
 static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
 {
 	struct hci_conn *conn;
@@ -530,14 +545,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
 	if (!conn)
 		goto done;
 
-	conn->state = BT_CLOSED;
-
-	mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type,
-			    status);
-
-	hci_proto_connect_cfm(conn, status);
-
-	hci_conn_del(conn);
+	le_conn_failed(conn, status);
 
 done:
 	hci_dev_unlock(hdev);
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 04/14] Bluetooth: Use connection parameters if any
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch changes hci_connect_le() so it uses the connection
parameters specified for the certain device. If no parameters
were configured, we use the default values.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 net/bluetooth/hci_conn.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7f148c9..4d1ce74 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -578,6 +578,7 @@ static int hci_create_le_conn(struct hci_conn *conn)
 static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 				    u8 dst_type, u8 sec_level, u8 auth_type)
 {
+	struct hci_conn_params *params;
 	struct hci_conn *conn;
 	int err;
 
@@ -624,8 +625,15 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 	conn->sec_level = BT_SECURITY_LOW;
 	conn->pending_sec_level = sec_level;
 	conn->auth_type = auth_type;
-	conn->le_conn_min_interval = hdev->le_conn_min_interval;
-	conn->le_conn_max_interval = hdev->le_conn_max_interval;
+
+	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+	if (params) {
+		conn->le_conn_min_interval = params->conn_min_interval;
+		conn->le_conn_max_interval = params->conn_max_interval;
+	} else {
+		conn->le_conn_min_interval = hdev->le_conn_min_interval;
+		conn->le_conn_max_interval = hdev->le_conn_max_interval;
+	}
 
 	err = hci_create_le_conn(conn);
 	if (err)
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 03/14] Bluetooth: Introduce connection parameters list
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch adds to hdev the connection parameters list (hdev->le_
conn_params). The elements from this list (struct hci_conn_params)
contains the connection parameters (for now, minimum and maximum
connection interval) that should be used during the connection
establishment.

The struct hci_conn_params also defines the 'auto_connect' field
which will be used to implement the auto connection mechanism.

Moreover, this patch adds helper functions to manipulate hdev->le_
conn_params list. Some of these functions are also declared in
hci_core.h since they will be used outside hci_core.c in upcoming
patches.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h | 25 +++++++++++++
 net/bluetooth/hci_core.c         | 80 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 197413b..f757b3f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -269,6 +269,7 @@ struct hci_dev {
 	struct list_head	link_keys;
 	struct list_head	long_term_keys;
 	struct list_head	remote_oob_data;
+	struct list_head	le_conn_params;
 
 	struct hci_dev_stats	stat;
 
@@ -373,6 +374,22 @@ struct hci_chan {
 	__u8		state;
 };
 
+struct hci_conn_params {
+	struct list_head list;
+
+	bdaddr_t addr;
+	u8 addr_type;
+
+	enum {
+		HCI_AUTO_CONN_DISABLED,
+		HCI_AUTO_CONN_ALWAYS,
+		HCI_AUTO_CONN_LINK_LOSS,
+	} auto_connect;
+
+	u16 conn_min_interval;
+	u16 conn_max_interval;
+};
+
 extern struct list_head hci_dev_list;
 extern struct list_head hci_cb_list;
 extern rwlock_t hci_dev_list_lock;
@@ -750,6 +767,14 @@ int hci_blacklist_clear(struct hci_dev *hdev);
 int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
 
+struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
+					       bdaddr_t *addr, u8 addr_type);
+void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+			 u8 auto_connect, u16 conn_min_interval,
+			 u16 conn_max_interval);
+void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
+void hci_conn_params_clear(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_core.c b/net/bluetooth/hci_core.c
index 369d307..672486f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2933,6 +2933,84 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 	return mgmt_device_unblocked(hdev, bdaddr, type);
 }
 
+/* This function requires the caller holds hdev->lock */
+struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
+					       bdaddr_t *addr, u8 addr_type)
+{
+	struct hci_conn_params *params;
+
+	list_for_each_entry(params, &hdev->le_conn_params, list) {
+		if (bacmp(&params->addr, addr) == 0 &&
+		    params->addr_type == addr_type) {
+			return params;
+		}
+	}
+
+	return NULL;
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
+			 u8 auto_connect, u16 conn_min_interval,
+			 u16 conn_max_interval)
+{
+	struct hci_conn_params *params;
+
+	params = hci_conn_params_lookup(hdev, addr, addr_type);
+	if (params) {
+		params->auto_connect = auto_connect;
+		params->conn_min_interval = conn_min_interval;
+		params->conn_max_interval = conn_max_interval;
+		return;
+	}
+
+	params = kzalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		BT_ERR("Out of memory");
+		return;
+	}
+
+	bacpy(&params->addr, addr);
+	params->addr_type = addr_type;
+	params->auto_connect = auto_connect;
+	params->conn_min_interval = conn_min_interval;
+	params->conn_max_interval = conn_max_interval;
+
+	list_add(&params->list, &hdev->le_conn_params);
+
+	BT_DBG("addr %pMR (type %u) auto_connect %u conn_min_interval 0x%.4x "
+	       "conn_max_interval 0x%.4x", addr, addr_type, auto_connect,
+	       conn_min_interval, conn_max_interval);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
+{
+	struct hci_conn_params *params;
+
+	params = hci_conn_params_lookup(hdev, addr, addr_type);
+	if (!params)
+		return;
+
+	list_del(&params->list);
+	kfree(params);
+
+	BT_DBG("addr %pMR (type %u)", addr, addr_type);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_conn_params_clear(struct hci_dev *hdev)
+{
+	struct hci_conn_params *params, *tmp;
+
+	list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
+		list_del(&params->list);
+		kfree(params);
+	}
+
+	BT_DBG("All LE connection parameters were removed");
+}
+
 static void inquiry_complete(struct hci_dev *hdev, u8 status)
 {
 	if (status) {
@@ -3043,6 +3121,7 @@ struct hci_dev *hci_alloc_dev(void)
 	INIT_LIST_HEAD(&hdev->link_keys);
 	INIT_LIST_HEAD(&hdev->long_term_keys);
 	INIT_LIST_HEAD(&hdev->remote_oob_data);
+	INIT_LIST_HEAD(&hdev->le_conn_params);
 	INIT_LIST_HEAD(&hdev->conn_hash.list);
 
 	INIT_WORK(&hdev->rx_work, hci_rx_work);
@@ -3228,6 +3307,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
 	hci_link_keys_clear(hdev);
 	hci_smp_ltks_clear(hdev);
 	hci_remote_oob_data_clear(hdev);
+	hci_conn_params_clear(hdev);
 	hci_dev_unlock(hdev);
 
 	hci_dev_put(hdev);
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 02/14] Bluetooth: Group list_head fields from strcut hci_dev together
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch groups the list_head fields from struct hci_dev together
and removes empty lines between them.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 77a4cb5..197413b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -259,18 +259,15 @@ struct hci_dev {
 	__u32			req_status;
 	__u32			req_result;
 
-	struct list_head	mgmt_pending;
 
 	struct discovery_state	discovery;
 	struct hci_conn_hash	conn_hash;
-	struct list_head	blacklist;
 
+	struct list_head	mgmt_pending;
+	struct list_head	blacklist;
 	struct list_head	uuids;
-
 	struct list_head	link_keys;
-
 	struct list_head	long_term_keys;
-
 	struct list_head	remote_oob_data;
 
 	struct hci_dev_stats	stat;
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 01/14] Bluetooth: Save connection interval parameters in hci_conn
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391116937-28217-1-git-send-email-andre.guedes@openbossa.org>

This patch creates two new fields in struct hci_conn to save the
minimum and maximum connection interval values used to establish
the connection this object represents.

This change is required in order to know what parameters the
connection is currently using.

Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
---
 include/net/bluetooth/hci_core.h | 2 ++
 net/bluetooth/hci_conn.c         | 6 ++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8d225e4..77a4cb5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -334,6 +334,8 @@ struct hci_conn {
 	__u8		passkey_entered;
 	__u16		disc_timeout;
 	__u16		setting;
+	__u16		le_conn_min_interval;
+	__u16		le_conn_max_interval;
 	unsigned long	flags;
 
 	__u8		remote_cap;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 0266bd8..7f148c9 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -558,8 +558,8 @@ static int hci_create_le_conn(struct hci_conn *conn)
 	bacpy(&cp.peer_addr, &conn->dst);
 	cp.peer_addr_type = conn->dst_type;
 	cp.own_address_type = conn->src_type;
-	cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval);
-	cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval);
+	cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
+	cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
 	cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
 	cp.min_ce_len = __constant_cpu_to_le16(0x0000);
 	cp.max_ce_len = __constant_cpu_to_le16(0x0000);
@@ -624,6 +624,8 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
 	conn->sec_level = BT_SECURITY_LOW;
 	conn->pending_sec_level = sec_level;
 	conn->auth_type = auth_type;
+	conn->le_conn_min_interval = hdev->le_conn_min_interval;
+	conn->le_conn_max_interval = hdev->le_conn_max_interval;
 
 	err = hci_create_le_conn(conn);
 	if (err)
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v6 00/14] LE auto connection and connection parameters
From: Andre Guedes @ 2014-01-30 21:22 UTC (permalink / raw)
  To: linux-bluetooth

Hi all,

This patch set implements the minor changes suggested by Johan on the
previous version.

The changes are:
    - Rename fail_conn_attempt() to le_conn_failed()
    - Create create_le_conn_req() helper to avoid duplicated code

Regards,

Andre


Andre Guedes (14):
  Bluetooth: Save connection interval parameters in hci_conn
  Bluetooth: Group list_head fields from strcut hci_dev together
  Bluetooth: Introduce connection parameters list
  Bluetooth: Use connection parameters if any
  Bluetooth: Introduce le_conn_failed() helper
  Bluetooth: Stop scanning on LE connection
  Bluetooth: Remove unused function
  Bluetooth: Introduce hdev->pend_le_conn list
  Bluetooth: Introduce LE auto connection infrastructure
  Bluetooth: Re-enable background scan in case of error
  Bluetooth: Temporarily stop background scanning on discovery
  Bluetooth: Auto connection and power on
  Bleutooth: Add support for auto connect options
  Bluetooth: Add le_auto_conn file on debugfs

 include/net/bluetooth/hci.h      |   1 +
 include/net/bluetooth/hci_core.h |  43 +++++-
 net/bluetooth/hci_conn.c         | 114 +++++++++++---
 net/bluetooth/hci_core.c         | 318 +++++++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_event.c        |  60 ++++++++
 net/bluetooth/mgmt.c             |  25 ++-
 6 files changed, 529 insertions(+), 32 deletions(-)

-- 
1.8.5.3


^ permalink raw reply

* [PATCH] Bluetooth: Remove Simultaneous LE & BR/EDR flags from AD
From: johan.hedberg @ 2014-01-30 19:16 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

Starting with the 4.1 Core Specification these flags are no longer used
and should always be cleared. From volume 3, part C, section 13.1.1:

"The 'Simultaneous LE and BR/EDR to Same Device Capable (Controller)'
and ‘Simultaneous LE and BR/EDR to Same Device Capable (Host)’ bits in
the Flags AD type shall be set to ‘0’."

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/mgmt.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index bde8e675c5ea..111b1296a2b8 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -637,14 +637,8 @@ static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
 
 	flags |= get_adv_discov_flags(hdev);
 
-	if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
-		if (lmp_le_br_capable(hdev))
-			flags |= LE_AD_SIM_LE_BREDR_CTRL;
-		if (lmp_host_le_br_capable(hdev))
-			flags |= LE_AD_SIM_LE_BREDR_HOST;
-	} else {
+	if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
 		flags |= LE_AD_NO_BREDR;
-	}
 
 	if (flags) {
 		BT_DBG("adv flags 0x%02x", flags);
-- 
1.8.5.3


^ permalink raw reply related

* "retail" config question OT???
From: ken @ 2014-01-30 17:36 UTC (permalink / raw)
  To: bluetooth list

I signed up for this list, not because I'm a bluetooth developer, but 
for help configuring my system.  Reading all the messages on development 
passing here the past week or so, I'm thinking I might have the wrong 
list.  If so, please ignore my query below (or respond if you care to) 
and direct me to the appropriate list.

For several weeks I've been trying to use bluetooth to connect my 
Android phone (running BlueTerm) to a terminal on a Raspberry Pi.  I've 
somehow gotten them paired and connected and have transferred a file 
from the Pi to the phone.  But when attempting to connect from BlueTerm, 
it says "Connected" just for a second, then a second message appears 
saying, "Device connection was lost".

"grep -i blue /var/log/*" yields a lot, among which is:

messages:Jan 27 02:17:18 rpi kernel: [   18.926436] Bluetooth: Core ver 2.16
messages:Jan 27 02:17:18 rpi kernel: [   20.888582] Bluetooth: HCI 
device and connection manager initialized
messages:Jan 27 02:17:18 rpi kernel: [   21.307016] Bluetooth: HCI 
socket layer initialized
messages:Jan 27 02:17:18 rpi kernel: [   21.371930] Bluetooth: L2CAP 
socket layer initialized
messages:Jan 27 02:17:18 rpi kernel: [   21.438767] Bluetooth: SCO 
socket layer initialized
messages:Jan 27 02:17:20 rpi kernel: [   40.992246] Bluetooth: BNEP 
(Ethernet Emulation) ver 1.3
messages:Jan 27 02:17:20 rpi kernel: [   40.992284] Bluetooth: BNEP 
filters: protocol multicast
messages:Jan 27 02:17:20 rpi kernel: [   40.992345] Bluetooth: BNEP 
socket layer initialized
messages:Jan 27 02:17:20 rpi kernel: [   41.042231] Bluetooth: RFCOMM 
TTY layer initialized
messages:Jan 27 02:17:20 rpi kernel: [   41.042346] Bluetooth: RFCOMM 
socket layer initialized
messages:Jan 27 02:17:20 rpi kernel: [   41.042368] Bluetooth: RFCOMM 
ver 1.11
syslog:Jan 30 12:00:38 rpi bluetoothd[2042]: Unable to spawn pnatd: 
Failed to execute child process "/usr/bin/phonet-at" (No such file or 
directory)
...

I haven't been able to get blueTerm to output any logs.

Perhaps helpful:

# hciconfig hci0 -a
hci0:   Type: BR/EDR  Bus: USB
         BD Address: 00:1F:81:00:08:30  ACL MTU: 1021:4  SCO MTU: 180:1
         UP RUNNING PSCAN
         RX bytes:6034 acl:90 sco:0 events:242 errors:0
         TX bytes:3253 acl:102 sco:0 commands:77 errors:0
         Features: 0xff 0x3e 0x09 0x76 0x80 0x01 0x00 0x80
         Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
         Link policy: RSWITCH HOLD SNIFF
         Link mode: SLAVE ACCEPT
         Name: 'rpi-0'
         Class: 0x520100
         Service Classes: Networking, Object Transfer, Telephony
         Device Class: Computer, Uncategorized
         HCI Version: 2.0 (0x3)  Revision: 0x44
         LMP Version: 2.0 (0x3)  Subversion: 0x3
         Manufacturer: Cambridge Silicon Radio (10)

Running "rfcomm -a" returns nothing at all.  Not knowing or finding 
anywhere what to put in any of the /etc/bluetooth/* files, that may not 
be surprising.

TIA for any help you can provide.

^ permalink raw reply

* Re: [PATCH] android/pts: PTS test results for PBAP
From: Szymon Janc @ 2014-01-30 16:28 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1390929931-10447-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Tuesday 28 of January 2014 19:25:31 Sebastian Chlad wrote:
> ---
>  android/pts-pbap.txt | 103
> +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 88
> insertions(+), 15 deletions(-)
> 
> diff --git a/android/pts-pbap.txt b/android/pts-pbap.txt
> index 843b7cf..4312921 100644
> --- a/android/pts-pbap.txt
> +++ b/android/pts-pbap.txt
> @@ -1,7 +1,7 @@
>  PTS test results for PBAP
> 
>  PTS version: 5.0
> -Tested: 14.11.2013
> +Tested: 28.01.2014
> 
>  Results:
>  PASS	test passed
> @@ -17,32 +17,82 @@ TC_PCE_SSM_BV_02_C	N/A
>  TC_PCE_SSM_BV_06_C	N/A
>  TC_PCE_SSM_BV_08_C	N/A
>  TC_PCE_SSM_BI_01_C	N/A
> +TC_PCE_SSM_BV_09_C	N/A
> +TC_PCE_SSM_BV_10_C	N/A
>  TC_PCE_PBD_BV_01_C	N/A
>  TC_PCE_PBD_BV_04_C	N/A
> +TC_PCE_PBD_BV_38_C	N/A
> +TC_PCE_PBD_BV_29_C	N/A
> +TC_PCE_PBD_BV_40_C	N/A
> +TC_PCE_PBD_BV_41_C	N/A
> +TC_PCE_PBD_BV_42_C	N/A
> +TC_PCE_PBD_BV_43_C	N/A
> +TC_PCE_PBD_BV_44_C	N/A
> +TC_PCE_PBD_BV_45_C	N/A
> +TC_PCE_PBD_BV_46_C	N/A
> +TC_PCE_PBD_BV_47_C	N/A
> +TC_PCE_PBD_BV_48_C	N/A
>  TC_PCE_PBB_BV_01_C	N/A
>  TC_PCE_PBB_BV_02_C	N/A
>  TC_PCE_PBB_BV_03_C	N/A
>  TC_PCE_PBB_BV_05_C	N/A
> +TC_PCE_PBB_BV_39_C	N/A
> +TC_PCE_PBB_BV_40_C	N/A
> +TC_PCE_PBB_BV_41_C	N/A
> +TC_PCE_PBB_BV_42_C	N/A
> +TC_PCE_PBB_BV_33_C	N/A
> +TC_PCE_PBB_BV_34_C	N/A
> +TC_PCE_PBB_BV_35_C	N/A
> +TC_PCE_PBB_BV_36_C	N/A
> +TC_PCE_PBB_BV_43_C	N/A
> +TC_PCE_PBB_BV_37_C	N/A
> +TC_PCE_PBB_BV_38_C	N/A
>  TC_PCE_PBF_BV_01_I	N/A
>  TC_PCE_PBF_BV_02_I	N/A
> +TC_PCE_PBF_BV_03_I	N/A
>  TC_PCE_PDF_BV_01_I	N/A
> -TC_PCE_PDF_BV_04_I	N/A
> +TC_PCE_PDF_BV_06_I	N/A
>  TC_PSE_SSM_BV_03_C	PASS
>  TC_PSE_SSM_BV_05_C	PASS
> -TC_PSE_SSM_BV_07_C	PASS
> +TC_PSE_SSM_BV_07_C	PASS	Tester must accept obex request with
> +					TSPX_auth_password set in PIXITs
>  TC_PSE_SSM_BI_02_C	PASS
>  TC_PSE_SSM_BI_03_C	N/A
> -TC_PSE_SSM_BV_08_I	PASS
> -TC_PSE_PBD_BV_02_C	PASS
> -TC_PSE_PBD_BV_03_C	PASS
> +TC_PSE_SSM_BV_08_I	PASS	Tester must compare passkey on IUT and PTS
> +TC_PSE_SSM_BV_11_C	N/A
> +
> +TC_PSE_PBD_BV_02_C	PASS	Tester must compare phone book size with the 
value
> +					given by PTS
> +TC_PSE_PBD_BV_03_C	PASS	Tester must compare phone book size with the 
value
> +					given by PTS
>  TC_PSE_PBD_BV_05_C	N/A
>  TC_PSE_PBD_BI_01_C	FAIL
> -TC_PSE_PBD_BV_11_C	N/A
> -TC_PSE_PBD_BV_12_C	N/A
> -TC_PSE_PBD_BV_13_C	N/A
> -TC_PSE_PBD_BV_14_C	N/A
> -TC_PSE_PBD_BV_15_C	N/A
> -TC_PSE_PBD_BV_16_C	N/A
> +TC_PSE_PBD_BV_06_C	N/A
> +TC_PSE_PBD_BV_07_C	N/A
> +TC_PSE_PBD_BV_08_C	N/A
> +TC_PSE_PBD_BV_09_C	N/A
> +TC_PSE_PBD_BV_10_C	N/A
> +TC_PSE_PBD_BV_17_C	FAIL
> +TC_PSE_PBD_BV_18_C	N/A
> +TC_PSE_PBD_BV_19_C	N/A
> +TC_PSE_PBD_BV_20_C	N/A
> +TC_PSE_PBD_BV_21_C	N/A
> +TC_PSE_PBD_BV_22_C	N/A
> +TC_PSE_PBD_BV_23_C	N/A
> +TC_PSE_PBD_BV_24_C	N/A
> +TC_PSE_PBD_BV_25_C	N/A
> +TC_PSE_PBD_BV_26_C	N/A
> +TC_PSE_PBD_BV_27_C	N/A
> +TC_PSE_PBD_BV_28_C	N/A
> +TC_PSE_PBD_BV_29_C	N/A
> +TC_PSE_PBD_BV_30_C	N/A
> +TC_PSE_PBD_BV_31_C	N/A
> +TC_PSE_PBD_BV_32_C	N/A
> +TC_PSE_PBD_BV_33_C	N/A
> +TC_PSE_PBD_BV_34_C	N/A
> +TC_PSE_PBD_BV_35_C	N/A
> +TC_PSE_PBD_BV_36_C	PASS
> +TC_PSE_PBD_BV_37_C	N/A
>  TC_PSE_PBB_BV_06_C	PASS
>  TC_PSE_PBB_BV_07_C	PASS
>  TC_PSE_PBB_BV_08_C	PASS
> @@ -51,9 +101,32 @@ TC_PSE_PBB_BV_10_C	PASS
>  TC_PSE_PBB_BV_11_C	PASS
>  TC_PSE_PBB_BI_01_C	PASS
>  TC_PSE_PBB_BI_07_C	PASS
> +TC_PSE_PBB_BV_12_C	PASS
> +TC_PSE_PBB_BV_13_C	N/A
> +TC_PSE_PBB_BV_14_C	N/A
> +TC_PSE_PBB_BV_15_C	N/A
> +TC_PSE_PBB_BV_16_C	N/A
> +TC_PSE_PBB_BV_17_C	N/A
> +TC_PSE_PBB_BV_18_C	N/A
> +TC_PSE_PBB_BV_19_C	N/A
> +TC_PSE_PBB_BV_20_C	N/A
> +TC_PSE_PBB_BV_21_C	N/A
> +TC_PSE_PBB_BV_22_C	N/A
> +TC_PSE_PBB_BV_23_C	N/A
> +TC_PSE_PBB_BV_24_C	N/A
> +TC_PSE_PBB_BV_25_C	N/A
> +TC_PSE_PBB_BV_26_C	N/A
> +TC_PSE_PBB_BV_27_C	N/A
> +TC_PSE_PBB_BV_44_C	N/A
> +TC_PSE_PBB_BV_45_C	N/A
> +TC_PSE_PBB_BV_46_C	N/A
> +TC_PSE_PBB_BV_28_C	N/A
> +TC_PSE_PBB_BV_29_C	N/A
> +TC_PSE_PBB_BV_30_C	N/A
> +TC_PSE_PBB_BV_31_C	PASS
> +TC_PSE_PBB_BV_32_C	N/A
>  TC_PSE_PBF_BV_01_I	PASS
>  TC_PSE_PBF_BV_02_I	PASS
> -TC_PSE_PDF_BV_01_I	PASS
> -TC_PSE_PDF_BV_03_I	N/A
> -TC_PSE_PDF_BV_05_I	N/A
> +TC_PSE_PDF_BV_01_I	PASS	Tester must compare phone book size with the 
value
> +					given by PTS
>  ---------------------------------------------------------------------------
> ----

Applied, thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH] android/pts: PTS test results for OPP
From: Szymon Janc @ 2014-01-30 16:28 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1390931987-10904-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Tuesday 28 of January 2014 19:59:47 Sebastian Chlad wrote:
> ---
>  android/pts-opp.txt | 37 ++++++++++++++++++++-----------------
>  1 file changed, 20 insertions(+), 17 deletions(-)
> 
> diff --git a/android/pts-opp.txt b/android/pts-opp.txt
> index b9329b9..3c4ab47 100644
> --- a/android/pts-opp.txt
> +++ b/android/pts-opp.txt
> @@ -1,7 +1,7 @@
>  PTS test results for OPP
> 
> -PTS version: 4.9
> -Tested: 14.11.2013
> +PTS version: 5.0
> +Tested: 28.01.2014
> 
>  Results:
>  PASS	test passed
> @@ -14,9 +14,9 @@ Test Name		Result	Notes
>  ---------------------------------------------------------------------------
> ---- TC_CLIENT_OPH_BV_01_I	PASS
>  TC_CLIENT_OPH_BV_02_I	N/A
> -TC_CLIENT_OPH_BV_03_I	PASS
> +TC_CLIENT_OPH_BV_03_I	PASS	Tester must send a contact to PTS
>  TC_CLIENT_OPH_BV_04_I	N/A
> -TC_CLIENT_OPH_BV_05_I	PASS
> +TC_CLIENT_OPH_BV_05_I	PASS	Tester must send a contact to PTS
>  TC_CLIENT_OPH_BV_07_I	N/A
>  TC_CLIENT_OPH_BV_08_I	N/A
>  TC_CLIENT_OPH_BV_09_I	N/A
> @@ -49,33 +49,36 @@ TC_CLIENT_BCE_BV_04_I	N/A
>  TC_CLIENT_BCE_BV_05_I	N/A
>  TC_CLIENT_BCE_BV_06_I	N/A
>  TC_CLIENT_BCE_BV_07_I	N/A
> -TC_SERVER_OPH_BV_01_I	PASS
> -TC_SERVER_OPH_BV_02_I	PASS
> -TC_SERVER_OPH_BV_03_I	PASS
> -TC_SERVER_OPH_BV_04_I	PASS
> -TC_SERVER_OPH_BV_05_I	PASS
> +TC_SERVER_OPH_BV_01_I	PASS	IUT must be in the connectable mode
> +TC_SERVER_OPH_BV_02_I	PASS	IUT must be in the connectable mode
> +TC_SERVER_OPH_BV_03_I	PASS	IUT must be in the connectable mode. Tester 
must
> +					accept incoming file
> +TC_SERVER_OPH_BV_04_I	PASS	IUT must be in the connectable mode. Tester 
must
> +					accept incoming file
> +TC_SERVER_OPH_BV_05_I	PASS	IUT must be in the connectable mode. Tester 
must
> +					reject incoming file
>  TC_SERVER_OPH_BV_07_I	N/A
>  TC_SERVER_OPH_BV_08_I	N/A
>  TC_SERVER_OPH_BV_09_I	N/A
> -TC_SERVER_OPH_BV_10_I	PASS
> +TC_SERVER_OPH_BV_10_I	PASS	IUT must be in the connectable mode
>  TC_SERVER_OPH_BV_11_I	N/A
>  TC_SERVER_OPH_BV_12_I	N/A
>  TC_SERVER_OPH_BV_13_I	N/A
> -TC_SERVER_OPH_BV_14_I	PASS
> +TC_SERVER_OPH_BV_14_I	PASS	IUT must be in the connectable mode
>  TC_SERVER_OPH_BV_15_I	N/A
>  TC_SERVER_OPH_BV_16_I	N/A
>  TC_SERVER_OPH_BV_17_I	N/A
> -TC_SERVER_OPH_BV_18_I	PASS
> -TC_SERVER_OPH_BV_19_I	PASS
> +TC_SERVER_OPH_BV_18_I	PASS	IUT must be in the connectable mode
> +TC_SERVER_OPH_BV_19_I	PASS	IUT must be in the connectable mode
>  TC_SERVER_OPH_BV_21_I	N/A
> -TC_SERVER_OPH_BV_22_I	PASS
> -TC_SERVER_OPH_BV_23_I	PASS
> +TC_SERVER_OPH_BV_22_I	PASS	IUT must be in the connectable mode
> +TC_SERVER_OPH_BV_23_I	PASS	IUT must be in the connectable mode
>  TC_SERVER_OPH_BV_24_I	N/A
>  TC_SERVER_OPH_BV_25_I	N/A
>  TC_SERVER_OPH_BV_26_I	N/A
> -TC_SERVER_OPH_BV_34_I	PASS
> +TC_SERVER_OPH_BV_34_I	PASS	IUT must be in the connectable mode
>  TC_SERVER_BCP_BV_01_I	N/A
> -TC_SERVER_BCP_BV_02_I	PASS
> +TC_SERVER_BCP_BV_02_I	PASS	IUT must be in the connectable mode
>  TC_SERVER_BCP_BV_03_I	N/A
>  TC_SERVER_BCP_BV_04_I	N/A
>  TC_SERVER_BCP_BV_05_I	N/A

Applied, thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH 1/2] android/pts: PTS test results for AVCTP
From: Szymon Janc @ 2014-01-30 16:28 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1391002025-15997-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Wednesday 29 of January 2014 15:27:04 Sebastian Chlad wrote:
> ---
>  android/pts-avctp.txt | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/android/pts-avctp.txt b/android/pts-avctp.txt
> index c057a10..a57ecee 100644
> --- a/android/pts-avctp.txt
> +++ b/android/pts-avctp.txt
> @@ -1,7 +1,7 @@
>  PTS test results for AVCTP
> 
>  PTS version: 5.0
> -Tested: --not yet tested--
> +Tested: 29.01.2014
> 
>  Results:
>  PASS	test passed
> @@ -29,13 +29,13 @@ TC_CT_FRA_BV_04_C	N/A
>  ---------------------------------------------------------------------------
> ---- Test Name		Result	Notes
>  ---------------------------------------------------------------------------
> ---- -TC_TG_CCM_BV_01_C	INC
> -TC_TG_CCM_BV_02_C	INC
> -TC_TG_CCM_BV_03_C	INC
> -TC_TG_CCM_BV_04_C	INC
> -TC_TG_NFR_BV_02_C	INC
> -TC_TG_NFR_BV_03_C	INC
> -TC_TG_NFR_BI_01_C	INC
> -TC_TG_FRA_BV_02_C	INC
> +TC_TG_CCM_BV_01_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_CCM_BV_02_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_CCM_BV_03_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_CCM_BV_04_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_NFR_BV_02_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_NFR_BV_03_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_NFR_BI_01_C	PASS
> +TC_TG_FRA_BV_02_C	FAIL
>  TC_TG_FRA_BV_03_C	INC
>  ---------------------------------------------------------------------------
> ----

Patch 1/2 pushed, for 2/2 please mark version as 4.4.2 as discussed. Thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH] android: Add avtest to debug builds
From: Szymon Janc @ 2014-01-30 16:25 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1390999219-15012-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Wednesday 29 of January 2014 14:40:19 Sebastian Chlad wrote:
> ---
>  android/Android.mk | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/android/Android.mk b/android/Android.mk
> index 1d12da5..238bb7c 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -354,6 +354,34 @@ LOCAL_MODULE := l2ping
>  include $(BUILD_EXECUTABLE)
> 
>  #
> +# avtest
> +#
> +
> +include $(CLEAR_VARS)
> +
> +LOCAL_SRC_FILES := \
> +	bluez/tools/avtest.c \
> +	bluez/lib/bluetooth.c \
> +	bluez/lib/hci.c \
> +
> +LOCAL_C_INCLUDES := \
> +	$(LOCAL_PATH)/bluez/lib \
> +
> +lib_headers := \
> +	bluetooth.h \
> +	hci.h \
> +
> +$(foreach file,$(lib_headers), $(shell ln -sf ../$(file)
> $(LOCAL_PATH)/bluez/lib/bluetooth/$(file))) +

Why is this need? Please compare on how other tools were added to Android.mk 

> +LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)
> +
> +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
> +LOCAL_MODULE_TAGS := debug
> +LOCAL_MODULE := avtest
> +
> +include $(BUILD_EXECUTABLE)
> +
> +#
>  # libsbc
>  #

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH] Bluetooth: Enable LTK distribution to slave devices
From: Vinicius Costa Gomes @ 2014-01-30 16:14 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1391032559-25183-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

On 13:55 Wed 29 Jan, johan.hedberg@gmail.com wrote:
> From: Johan Hedberg <johan.hedberg@intel.com>
>
> So far we've only been requesting the LTK to be distributed to the
> master (initiator) of pairing, which is usually enough since it's the
> master that will establish future connections and initiate encryption.
> However, in the case that both devices support switching to the opposing
> role (which seems to be increasingly common) pairing will have to
> performed again since the "new" master will not have all information.
>
> As there is no real harm in it, this patch updates the code to always
> try distributing the LTK also to the slave device, thereby enabling role
> switches for future connections.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---

Looks good. Ack.


Cheers,
--
Vinicius

^ permalink raw reply

* [PATCH 3/3] avrcp: Fix possible buffer overflow and correct length
From: Andrei Emeltchenko @ 2014-01-30 16:12 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391098376-26834-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Wrong length was given and it was also possible to crash.
---
 profiles/audio/avrcp.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 128f7d3..f9fce5c 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1899,8 +1899,12 @@ static void avrcp_get_current_player_value(struct avrcp *session,
 {
 	uint8_t buf[AVRCP_HEADER_LENGTH + 5];
 	struct avrcp_header *pdu = (void *) buf;
+	uint16_t length = AVRCP_HEADER_LENGTH + count + 1;
 	int i;
 
+	if (count + 1 > 5)
+		return;
+
 	memset(buf, 0, sizeof(buf));
 
 	set_company_id(pdu->company_id, IEEEID_BTSIG);
@@ -1913,7 +1917,7 @@ static void avrcp_get_current_player_value(struct avrcp *session,
 		pdu->params[i + 1] = attrs[i];
 
 	avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
-					AVC_SUBUNIT_PANEL, buf, sizeof(buf),
+					AVC_SUBUNIT_PANEL, buf, length,
 					avrcp_player_value_rsp, session);
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/3] avrcp: Fix using incorrect buffer for SetVolume
From: Andrei Emeltchenko @ 2014-01-30 16:12 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391098376-26834-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

The command requires one parameter.
---
 profiles/audio/avrcp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 2e1a940..128f7d3 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -3706,7 +3706,7 @@ int avrcp_set_volume(struct btd_device *dev, uint8_t volume)
 {
 	struct avrcp_server *server;
 	struct avrcp *session;
-	uint8_t buf[AVRCP_HEADER_LENGTH + 2];
+	uint8_t buf[AVRCP_HEADER_LENGTH + 1];
 	struct avrcp_header *pdu = (void *) buf;
 
 	server = find_server(servers, device_get_adapter(dev));
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 1/3] avrcp: Avoid unneeded calculation
From: Andrei Emeltchenko @ 2014-01-30 16:12 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

There no need to calculate those values
---
 profiles/audio/avrcp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index fa5adab..2e1a940 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -3177,7 +3177,7 @@ static void avrcp_register_notification(struct avrcp *session, uint8_t event)
 	pdu->params[0] = event;
 	pdu->params_len = htons(AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH);
 
-	length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
+	length = AVRCP_HEADER_LENGTH + AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH;
 
 	avctp_send_vendordep_req(session->conn, AVC_CTYPE_NOTIFY,
 					AVC_SUBUNIT_PANEL, buf, length,
@@ -3250,7 +3250,7 @@ static void avrcp_get_capabilities(struct avrcp *session)
 	pdu->params[0] = CAP_EVENTS_SUPPORTED;
 	pdu->params_len = htons(AVRCP_GET_CAPABILITIES_PARAM_LENGTH);
 
-	length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
+	length = AVRCP_HEADER_LENGTH + AVRCP_GET_CAPABILITIES_PARAM_LENGTH;
 
 	avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
 					AVC_SUBUNIT_PANEL, buf, length,
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH] android/pts: PTS test results for L2CAP
From: Szymon Janc @ 2014-01-30 15:43 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1390991606-13576-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Wednesday 29 of January 2014 12:33:26 Sebastian Chlad wrote:
> ---
>  android/pts-l2cap.txt | 20 +++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/android/pts-l2cap.txt b/android/pts-l2cap.txt
> index 51eedf5..3e46309 100644
> --- a/android/pts-l2cap.txt
> +++ b/android/pts-l2cap.txt
> @@ -1,7 +1,7 @@
>  PTS test results for L2CAP
> 
>  PTS version: 5.0
> -Tested: 10.01.2014
> +Tested: 29.01.2014
> 
>  Results:
>  PASS   test passed
> @@ -87,16 +87,18 @@ TC_ERM_BV_06_C         PASS
>  TC_ERM_BV_07_C         PASS    l2test -X ertm -P 33 &
>  TC_ERM_BV_08_C         PASS
>  TC_ERM_BV_09_C         PASS    l2test -X ertm -P 33 &
> -TC_ERM_BV_10_C         INC
> -TC_ERM_BV_11_C         INC
> -TC_ERM_BV_12_C         INC
> +TC_ERM_BV_10_C         PASS    l2test -x -X ertm -P 33 -D 35000 -Q 1 -R -N
> 1 & +				btmgmt disconnect
> +TC_ERM_BV_11_C         PASS    l2test -x -X ertm -P 33 -D 35000 -Q 1 -R -N
> 1 & +				btmgmt disconnect
> +TC_ERM_BV_12_C         PASS    l2test -x -X ertm -P 33 -R -N 1
>  TC_ERM_BV_13_C         PASS
>  TC_ERM_BV_14_C         PASS
>  TC_ERM_BV_15_C         PASS
>  TC_ERM_BV_16_C         PASS
>  TC_ERM_BV_17_C         PASS
> -TC_ERM_BV_18_C         INC
> -TC_ERM_BV_19_C         INC
> +TC_ERM_BV_18_C         PASS    l2test -x -X ertm -P 33 -R -N 1
> +TC_ERM_BV_19_C         PASS    l2test -x -X ertm -P 33 -R -N 1
>  TC_ERM_BV_20_C         PASS
>  TC_ERM_BV_21_C         PASS
>  TC_ERM_BV_22_C         PASS
> @@ -106,9 +108,9 @@ TC_ERM_BI_02_C         PASS
>  TC_ERM_BI_03_C         PASS
>  TC_ERM_BI_04_C         PASS
>  TC_ERM_BI_05_C         PASS
> -TC_STM_BV_01_C         INC
> -TC_STM_BV_02_C         INC
> -TC_STM_BV_03_C         INC
> +TC_STM_BV_01_C         PASS    l2test -x -X ertm -P 33 -R -N 1 -Y 3 &
> +TC_STM_BV_02_C         PASS    l2test -x -X ertm -P 33 -R -N 1 -Y 3 &
> +TC_STM_BV_03_C         PASS    l2test -x -X ertm -P 33 -R -N 1 -Y 3 &
>  TC_STM_BV_11_C         N/A
>  TC_STM_BV_12_C         N/A
>  TC_STM_BV_13_C         N/A

Applied, thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* [RFC] unit/avrcp: First unit test for AVRCP profile
From: Andrei Emeltchenko @ 2014-01-30 15:38 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test TP/MPS/BV-01-C [SetAddressedPlayer – CT] verifies
SetAddressedPlayer command.
---
 Makefile.am       |   9 ++
 unit/test-avrcp.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 334 insertions(+)
 create mode 100644 unit/test-avrcp.c

diff --git a/Makefile.am b/Makefile.am
index 1a44a9f..67b7167 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -281,6 +281,15 @@ unit_test_avctp_SOURCES = unit/test-avctp.c \
 				android/avctp.c android/avctp.h
 unit_test_avctp_LDADD = @GLIB_LIBS@
 
+unit_tests += unit/test-avrcp
+
+unit_test_avrcp_SOURCES = unit/test-avrcp.c \
+				src/shared/util.h src/shared/util.c \
+				src/log.h src/log.c \
+				android/avctp.c android/avctp.h \
+				android/avrcp-lib.c android/avrcp-lib.h
+unit_test_avrcp_LDADD = @GLIB_LIBS@ lib/libbluetooth-internal.la
+
 unit_tests += unit/test-gdbus-client
 
 unit_test_gdbus_client_SOURCES = unit/test-gdbus-client.c
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
new file mode 100644
index 0000000..2030b22
--- /dev/null
+++ b/unit/test-avrcp.c
@@ -0,0 +1,325 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  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 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+
+#include "src/shared/util.h"
+#include "src/log.h"
+#include "lib/bluetooth.h"
+
+#include "android/avctp.h"
+#include "android/avrcp-lib.h"
+
+#define IEEEID_BTSIG		0x001958
+
+struct test_pdu {
+	bool valid;
+	bool fragmented;
+	const uint8_t *data;
+	size_t size;
+};
+
+struct test_data {
+	char *test_name;
+	struct test_pdu *pdu_list;
+};
+
+struct context {
+	GMainLoop *main_loop;
+	struct avrcp_device *dev;
+	guint source;
+	guint process;
+	int fd;
+	unsigned int pdu_offset;
+	const struct test_data *data;
+};
+
+#define data(args...) ((const unsigned char[]) { args })
+
+#define raw_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
+#define frg_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.fragmented = true,				\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
+#define define_test(name, function, args...)				\
+	do {								\
+		const struct test_pdu pdus[] = {			\
+			args, { }					\
+		};							\
+		static struct test_data data;				\
+		data.test_name = g_strdup(name);			\
+		data.pdu_list = g_malloc(sizeof(pdus));			\
+		memcpy(data.pdu_list, pdus, sizeof(pdus));		\
+		g_test_add_data_func(name, &data, function);		\
+	} while (0)
+
+static void test_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	g_print("%s%s\n", prefix, str);
+}
+
+static void test_free(gconstpointer user_data)
+{
+	const struct test_data *data = user_data;
+
+	g_free(data->test_name);
+	g_free(data->pdu_list);
+}
+
+static gboolean context_quit(gpointer user_data)
+{
+	struct context *context = user_data;
+
+	if (context->process > 0)
+		g_source_remove(context->process);
+
+	g_main_loop_quit(context->main_loop);
+
+	return FALSE;
+}
+
+static gboolean send_pdu(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	ssize_t len;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	len = write(context->fd, pdu->data, pdu->size);
+
+	if (g_test_verbose())
+		util_hexdump('<', pdu->data, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	if (pdu->fragmented)
+		return send_pdu(user_data);
+
+	context->process = 0;
+	return FALSE;
+}
+
+static void context_process(struct context *context)
+{
+	if (!context->data->pdu_list[context->pdu_offset].valid) {
+		context_quit(context);
+		return;
+	}
+
+	context->process = g_idle_add(send_pdu, context);
+}
+
+static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	unsigned char buf[512];
+	ssize_t len;
+	int fd;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		context->source = 0;
+		g_print("%s: cond %x\n", __func__, cond);
+		return FALSE;
+	}
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	len = read(fd, buf, sizeof(buf));
+
+	g_assert(len > 0);
+
+	if (g_test_verbose())
+		util_hexdump('>', buf, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+	if (!pdu->fragmented)
+		context_process(context);
+
+	return TRUE;
+}
+
+static struct context *create_context(uint16_t version, gconstpointer data)
+{
+	struct context *context = g_new0(struct context, 1);
+	GIOChannel *channel;
+	int err, sv[2];
+	bdaddr_t dst;
+
+	context->main_loop = g_main_loop_new(NULL, FALSE);
+	g_assert(context->main_loop);
+
+	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+	g_assert(err == 0);
+
+	context->dev = avrcp_device_new(&dst);
+	context->dev->session = avctp_new(sv[0], 672, 672, version);
+	g_assert(context->dev->session != NULL);
+
+	channel = g_io_channel_unix_new(sv[1]);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	context->source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				test_handler, context);
+	g_assert(context->source > 0);
+
+	g_io_channel_unref(channel);
+
+	context->fd = sv[1];
+	context->data = data;
+
+	return context;
+}
+
+static void execute_context(struct context *context)
+{
+	g_main_loop_run(context->main_loop);
+
+	if (context->source > 0)
+		g_source_remove(context->source);
+
+	avrcp_device_free(context->dev);
+
+	g_main_loop_unref(context->main_loop);
+
+	test_free(context->data);
+	g_free(context);
+}
+
+#define AVRCP_SET_ADDRESSED_PLAYER	0x60
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct avrcp_header {
+	uint8_t company_id[3];
+	uint8_t pdu_id;
+	uint8_t packet_type:2;
+	uint8_t rsvd:6;
+	uint16_t params_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_HEADER_LENGTH 7
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct avrcp_header {
+	uint8_t company_id[3];
+	uint8_t pdu_id;
+	uint8_t rsvd:6;
+	uint8_t packet_type:2;
+	uint16_t params_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_HEADER_LENGTH 7
+
+#else
+#error "Unknown byte order"
+#endif
+
+static void set_company_id(uint8_t cid[3], const uint32_t cid_in)
+{
+	cid[0] = cid_in >> 16;
+	cid[1] = cid_in >> 8;
+	cid[2] = cid_in;
+}
+
+static int avrcp_sent_set_addr_player(struct context *context)
+{
+	uint8_t buf[AVRCP_HEADER_LENGTH + 2];
+	struct avrcp_header *pdu = (void *) buf;
+
+	memset(buf, 0, sizeof(buf));
+
+	set_company_id(pdu->company_id, IEEEID_BTSIG);
+
+	pdu->pdu_id = AVRCP_SET_ADDRESSED_PLAYER;
+	pdu->params[0] = 0xab;
+	pdu->params[1] = 0xcd;
+	pdu->params_len = htons(2);
+
+	return avctp_send_vendordep_req(context->dev->session,
+					AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
+					buf, sizeof(buf),
+					NULL, NULL);
+}
+
+static void test_client(gconstpointer data)
+{
+	struct context *context = create_context(0x0100, data);
+
+	avrcp_sent_set_addr_player(context);
+
+	execute_context(context);
+}
+
+int main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	if (g_test_verbose())
+		__btd_log_init("*", 0);
+
+	/* Media Player Selection Commands and Notifications tests */
+
+	define_test("/TP/MPS/BV-01-C", test_client,
+			raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x00,
+				0x00, 0x19, 0x58, 0x60, 0x00, 0x00,
+				0x02, 0xab, 0xcd));
+
+	return g_test_run();
+}
-- 
1.8.3.2


^ permalink raw reply related


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