Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC v8 06/10] Bluetooth: Introduce LE auto connection infrastructure
From: Andre Guedes @ 2014-02-05 22:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391639006-26311-1-git-send-email-andre.guedes@openbossa.org>

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        | 41 ++++++++++++++++++++
 4 files changed, 129 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(&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 df58cde..e2ca1b9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3620,25 +3620,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_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;
 
+		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 v8 05/10] Bluetooth: Introduce hdev->pend_le_conn list
From: Andre Guedes @ 2014-02-05 22:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391639006-26311-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 6e5062c..7b9c4ed 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;
 
@@ -771,6 +772,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 6529f4a..0f670bc 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2999,6 +2999,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) {
@@ -3107,6 +3173,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);
@@ -3293,6 +3360,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 v8 04/10] Bluetooth: Remove unused function
From: Andre Guedes @ 2014-02-05 22:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391639006-26311-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 166d7a5..70f4226 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 v8 03/10] Bluetooth: Stop scanning on LE connection
From: Andre Guedes @ 2014-02-05 22:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391639006-26311-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    | 78 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 352d3d7..a0d5262 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -352,6 +352,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 4f5029c..166d7a5 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);
+		hci_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);
+		hci_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,23 @@ 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)) {
+		hci_stop_le_scan_req(&req);
+		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 v8 02/10] Bluetooth: Declare le_conn_failed in hci_core.h
From: Andre Guedes @ 2014-02-05 22:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391639006-26311-1-git-send-email-andre.guedes@openbossa.org>

This patch adds the "hci_" prefix to le_conn_failed() helper and
declares it in hci_core.h so it can be reused in hci_event.c.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8aff7f9..6e5062c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -627,6 +627,8 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
 void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
 
+void hci_le_conn_failed(struct hci_conn *conn, u8 status);
+
 /*
  * hci_conn_get() and hci_conn_put() are used to control the life-time of an
  * "hci_conn" object. They do not guarantee that the hci_conn object is running,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6797292..4f5029c 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -515,7 +515,7 @@ 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)
+void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 {
 	struct hci_dev *hdev = conn->hdev;
 
@@ -545,7 +545,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
 	if (!conn)
 		goto done;
 
-	le_conn_failed(conn, status);
+	hci_le_conn_failed(conn, status);
 
 done:
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d2c6878..df58cde 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3601,11 +3601,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 
 	if (ev->status) {
-		mgmt_connect_failed(hdev, &conn->dst, conn->type,
-				    conn->dst_type, ev->status);
-		hci_proto_connect_cfm(conn, ev->status);
-		conn->state = BT_CLOSED;
-		hci_conn_del(conn);
+		hci_le_conn_failed(conn, ev->status);
 		goto unlock;
 	}
 
-- 
1.8.5.3


^ permalink raw reply related

* [RFC v8 01/10] Bluetooth: Create hci_stop_le_scan_req() helper
From: Andre Guedes @ 2014-02-05 22:23 UTC (permalink / raw)
  To: linux-bluetooth

This patch moves stop LE scanning duplicate code to one single
place and reuses it. This will avoid more duplicate code in
upcoming patches.

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

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 92fa75f..8aff7f9 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1212,4 +1212,6 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
 #define SCO_AIRMODE_CVSD       0x0000
 #define SCO_AIRMODE_TRANSP     0x0003
 
+void hci_stop_le_scan_req(struct hci_request *req);
+
 #endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e774669..6529f4a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3058,7 +3058,6 @@ static void le_scan_disable_work(struct work_struct *work)
 {
 	struct hci_dev *hdev = container_of(work, struct hci_dev,
 					    le_scan_disable.work);
-	struct hci_cp_le_set_scan_enable cp;
 	struct hci_request req;
 	int err;
 
@@ -3066,9 +3065,7 @@ static void le_scan_disable_work(struct work_struct *work)
 
 	hci_req_init(&req, hdev);
 
-	memset(&cp, 0, sizeof(cp));
-	cp.enable = LE_SCAN_DISABLE;
-	hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
+	hci_stop_le_scan_req(&req);
 
 	err = hci_req_run(&req, le_scan_disable_work_complete);
 	if (err)
@@ -4523,3 +4520,12 @@ static void hci_cmd_work(struct work_struct *work)
 		}
 	}
 }
+
+void hci_stop_le_scan_req(struct hci_request *req)
+{
+	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);
+}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ce7ef33..5c0d55d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3400,7 +3400,6 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
 	struct hci_cp_remote_name_req_cancel cp;
 	struct inquiry_entry *e;
 	struct hci_request req;
-	struct hci_cp_le_set_scan_enable enable_cp;
 	int err;
 
 	BT_DBG("%s", hdev->name);
@@ -3436,10 +3435,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
 		} else {
 			cancel_delayed_work(&hdev->le_scan_disable);
 
-			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);
+			hci_stop_le_scan_req(&req);
 		}
 
 		break;
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH] Bluetooth: Fix to auto accept pairing request for no MITM case
From: Bing Zhao @ 2014-02-05 19:01 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Bing Zhao,
	Hiren Tandel, Rahul Tank, Quinton Yuan

From: Hiren Tandel <hirent@marvell.com>

With existing implementation, during incoming SSP if no side
requires MITM protection, user confirm request event is
forwarded to user space for further user confirmation without
checking io capability of local host. But in case if there is no
agent registered with bluez user space daemon which means device
has NoInputNoOutput capability at that moment, it rejects the
request.

This patch will check for io capability of local host before
forwarding request to user space. If local host has
NoInputNoOutput capability, there is no point in forwarding
request to user space. Hence local host kernel goes ahead with
auto accept, by sending User Confirmation Request Reply command.

Signed-off-by: Hiren Tandel <hirent@marvell.com>
Signed-off-by: Rahul Tank <rahult@marvell.com>
Signed-off-by: Quinton Yuan <qyuan@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 net/bluetooth/hci_event.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d2c6878..b61f0c6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3239,8 +3239,13 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
 
 		/* If we're not the initiators request authorization to
 		 * proceed from user space (mgmt_user_confirm with
-		 * confirm_hint set to 1). */
-		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
+		 * confirm_hint set to 1).
+		 * But if local host has NoInputNoOutput capability,
+		 * then no use of passing request to user space,
+		 * so go ahead with auto accept.
+		 */
+		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
+		    conn->io_capability != HCI_IO_NO_INPUT_OUTPUT) {
 			BT_DBG("Confirming auto-accept as acceptor");
 			confirm_hint = 1;
 			goto confirm;
-- 
1.8.0

^ permalink raw reply related

* Re: [PATCH v2] android: Add support for Valgrind in debug variants
From: Marcel Holtmann @ 2014-02-05 18:44 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: BlueZ development
In-Reply-To: <1391591653-17254-2-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

> +
> +#include <cutils/properties.h>
> +
> +#define PROPERTY_NAME "persist.sys.bluetooth.valgrind"
> +
> +#define VALGRIND_BIN "/system/bin/valgrind"
> +
> +#define BLUETOOTHD_BIN "/system/bin/bluetoothd-main"
> +
> +int main(int argc, char *argv[])
> +{
> +	char value[PROPERTY_VALUE_MAX];
> +	char *prg_argv[4];
> +	char *prg_envp[3];
> +
> +	if (property_get(PROPERTY_NAME, value, "") <= 0)
> +		goto run_bluetoothd;
> +
> +	if (strcasecmp(value, "true") && atoi(value) == 0)
> +		goto run_bluetoothd;
> +
> +	prg_argv[0] = VALGRIND_BIN;
> +	prg_argv[1] = "--leak-check=full";
> +	prg_argv[2] = BLUETOOTHD_BIN;
> +	prg_argv[3] = NULL;
> +
> +	prg_envp[0] = "G_SLICE=always-malloc";
> +	prg_envp[1] = "G_DEBUG=gc-friendly";
> +	prg_envp[2] = NULL;
> +
> +	execve(prg_argv[0], prg_argv, prg_envp);
> +
> +run_bluetoothd:
> +	prg_argv[0] = BLUETOOTHD_BIN;
> +	prg_argv[1] = NULL;
> +
> +	prg_envp[0] = NULL;
> +
> +	execve(prg_argv[0], prg_argv, prg_envp);
> +
> +	return 0;
> +}

the usage of a goto label here is completely wrong. Create two functions. One to execve bluetoothd without valgrind and one to execve bluetoothd with valgrind.

Regards

Marcel


^ permalink raw reply

* [PATCH v2 5/5] android/pan: Fix bnep interface name
From: Szymon Janc @ 2014-02-05 16:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1391616034-23312-1-git-send-email-szymon.janc@tieto.com>

From: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>

Android uses bt-pan static interface in PAN profile. In server role
it uses it as bridge name. But current implementaion passes interface
names like bnep0, bnep1... Android Framework is unaware of this name
and unable to allocate IP address after profile connection setup.
---
 android/pan.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index b5f8d56..eeeadeb 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -51,8 +51,9 @@
 
 #define SVC_HINT_NETWORKING 0x02
 
-#define BNEP_BRIDGE "bnep"
+#define BNEP_BRIDGE "bt-pan"
 #define BNEP_PANU_INTERFACE "bt-pan"
+#define BNEP_NAP_INTERFACE "bt-pan%d"
 #define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
@@ -221,8 +222,13 @@ static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
 	ev.state = state;
 	ev.local_role = local_role;
 	ev.status = HAL_STATUS_SUCCESS;
+
 	memset(ev.name, 0, sizeof(ev.name));
-	memcpy(ev.name, dev->iface, sizeof(dev->iface));
+
+	if (local_role == HAL_PAN_ROLE_NAP)
+		memcpy(ev.name, BNEP_BRIDGE, sizeof(BNEP_BRIDGE));
+	else
+		memcpy(ev.name, dev->iface, sizeof(dev->iface));
 
 	ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
 									&ev);
@@ -534,6 +540,9 @@ static void nap_confirm_cb(GIOChannel *chan, gpointer data)
 	local_role = HAL_PAN_ROLE_NAP;
 	dev->role = HAL_PAN_ROLE_PANU;
 
+	strncpy(dev->iface, BNEP_NAP_INTERFACE, 16);
+	dev->iface[15] = '\0';
+
 	dev->io = g_io_channel_ref(chan);
 	g_io_channel_set_close_on_unref(dev->io, TRUE);
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v2 4/5] android/pan: Fix unregistering NAP bridge
From: Szymon Janc @ 2014-02-05 16:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391616034-23312-1-git-send-email-szymon.janc@tieto.com>

This fix not removing NAP bridge in case of error or last device
disconnect.
---
 android/pan.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 7e44e58..b5f8d56 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -72,11 +72,14 @@ struct pan_device {
 static struct {
 	uint32_t	record_id;
 	GIOChannel	*io;
+	bool		bridge;
 } nap_dev = {
 	.record_id = 0,
 	.io = NULL,
+	.bridge = false,
 };
 
+
 static int set_forward_delay(void)
 {
 	int fd, ret;
@@ -103,6 +106,9 @@ static int nap_create_bridge(void)
 
 	DBG("%s", BNEP_BRIDGE);
 
+	if (nap_dev.bridge)
+		return 0;
+
 	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
 	if (sk < 0)
 		return -EOPNOTSUPP;
@@ -121,6 +127,8 @@ static int nap_create_bridge(void)
 
 	close(sk);
 
+	nap_dev.bridge = err == 0;
+
 	return err;
 }
 
@@ -130,6 +138,11 @@ static int nap_remove_bridge(void)
 
 	DBG("%s", BNEP_BRIDGE);
 
+	if (!nap_dev.bridge)
+		return 0;
+
+	nap_dev.bridge = false;
+
 	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
 	if (sk < 0)
 		return -EOPNOTSUPP;
@@ -169,8 +182,10 @@ static void pan_device_free(struct pan_device *dev)
 	devices = g_slist_remove(devices, dev);
 	g_free(dev);
 
-	if (g_slist_length(devices) == 0)
+	if (g_slist_length(devices) == 0) {
 		local_role = HAL_PAN_ROLE_NONE;
+		nap_remove_bridge();
+	}
 }
 
 static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
@@ -447,8 +462,12 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
 		goto failed;
 	}
 
+	if (nap_create_bridge() < 0)
+		goto failed;
+
 	if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
 							&dev->dst) < 0) {
+		nap_remove_bridge();
 		error("server_connadd failed");
 		rsp = BNEP_CONN_NOT_ALLOWED;
 		goto failed;
@@ -549,14 +568,9 @@ static void destroy_nap_device(void)
 static int register_nap_server(void)
 {
 	GError *gerr = NULL;
-	int err;
 
 	DBG("");
 
-	err = nap_create_bridge();
-	if (err < 0)
-		return err;
-
 	nap_dev.io = bt_io_listen(NULL, nap_confirm_cb, NULL, NULL, &gerr,
 					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
 					BT_IO_OPT_PSM, BNEP_PSM,
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v2 3/5] android/pan: Move functions up to avoid forward declarations
From: Szymon Janc @ 2014-02-05 16:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391616034-23312-1-git-send-email-szymon.janc@tieto.com>

---
 android/pan.c | 132 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 66 insertions(+), 66 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 07cddc9..7e44e58 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -77,6 +77,72 @@ static struct {
 	.io = NULL,
 };
 
+static int set_forward_delay(void)
+{
+	int fd, ret;
+
+	fd = open(FORWARD_DELAY_PATH, O_RDWR);
+	if (fd < 0) {
+		int err = -errno;
+
+		error("pan: open forward delay file failed: %d (%s)",
+							-err, strerror(-err));
+
+		return err;
+	}
+
+	ret = write(fd, "0", sizeof("0"));
+	close(fd);
+
+	return ret;
+}
+
+static int nap_create_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
+		err = -errno;
+		if (err != -EEXIST) {
+			close(sk);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	err = set_forward_delay();
+	if (err < 0)
+		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+
+	close(sk);
+
+	return err;
+}
+
+static int nap_remove_bridge(void)
+{
+	int sk, err;
+
+	DBG("%s", BNEP_BRIDGE);
+
+	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+	if (sk < 0)
+		return -EOPNOTSUPP;
+
+	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
+	close(sk);
+
+	if (err < 0)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
 static int device_cmp(gconstpointer s, gconstpointer user_data)
 {
 	const struct pan_device *dev = s;
@@ -467,72 +533,6 @@ failed:
 	bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
 }
 
-static int set_forward_delay(void)
-{
-	int fd, ret;
-
-	fd = open(FORWARD_DELAY_PATH, O_RDWR);
-	if (fd < 0) {
-		int err = -errno;
-
-		error("pan: open forward delay file failed: %d (%s)",
-							-err, strerror(-err));
-
-		return err;
-	}
-
-	ret = write(fd, "0", sizeof("0"));
-	close(fd);
-
-	return ret;
-}
-
-static int nap_create_bridge(void)
-{
-	int sk, err;
-
-	DBG("%s", BNEP_BRIDGE);
-
-	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
-	if (sk < 0)
-		return -EOPNOTSUPP;
-
-	if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
-		err = -errno;
-		if (err != -EEXIST) {
-			close(sk);
-			return -EOPNOTSUPP;
-		}
-	}
-
-	err = set_forward_delay();
-	if (err < 0)
-		ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
-
-	close(sk);
-
-	return err;
-}
-
-static int nap_remove_bridge(void)
-{
-	int sk, err;
-
-	DBG("%s", BNEP_BRIDGE);
-
-	sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
-	if (sk < 0)
-		return -EOPNOTSUPP;
-
-	err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
-	close(sk);
-
-	if (err < 0)
-		return -EOPNOTSUPP;
-
-	return 0;
-}
-
 static void destroy_nap_device(void)
 {
 	DBG("");
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v2 2/5] profiles/network: Allow to pass interface name to bnep_new
From: Szymon Janc @ 2014-02-05 16:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391616034-23312-1-git-send-email-szymon.janc@tieto.com>

---
 android/pan.c                 | 3 ++-
 profiles/network/bnep.c       | 5 ++++-
 profiles/network/bnep.h       | 3 ++-
 profiles/network/connection.c | 6 ++++--
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 2bc54bd..07cddc9 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -52,6 +52,7 @@
 #define SVC_HINT_NETWORKING 0x02
 
 #define BNEP_BRIDGE "bnep"
+#define BNEP_PANU_INTERFACE "bt-pan"
 #define FORWARD_DELAY_PATH "/sys/class/net/"BNEP_BRIDGE"/bridge/forward_delay"
 
 static bdaddr_t adapter_addr;
@@ -194,7 +195,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 
 	sk = g_io_channel_unix_get_fd(dev->io);
 
-	dev->session = bnep_new(sk, l_role, r_role);
+	dev->session = bnep_new(sk, l_role, r_role, BNEP_PANU_INTERFACE);
 	if (!dev->session)
 		goto fail;
 
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 82d0d99..1aa0783 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -386,7 +386,8 @@ static gboolean bnep_conn_req_to(gpointer user_data)
 	return FALSE;
 }
 
-struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role)
+struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
+								char *iface)
 {
 	struct bnep *session;
 	int dup_fd;
@@ -399,6 +400,8 @@ struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role)
 	session->io = g_io_channel_unix_new(dup_fd);
 	session->src = local_role;
 	session->dst = remote_role;
+	strncpy(session->iface, iface, 16);
+	session->iface[15] = '\0';
 
 	g_io_channel_set_close_on_unref(session->io, TRUE);
 	session->watch = g_io_add_watch(session->io,
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 87cdacf..bc43d4f 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -30,7 +30,8 @@ uint16_t bnep_service_id(const char *svc);
 const char *bnep_uuid(uint16_t id);
 const char *bnep_name(uint16_t id);
 
-struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role);
+struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
+								char *iface);
 void bnep_free(struct bnep *session);
 
 typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 5f45fdb..cc73989 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -51,6 +51,7 @@
 #include "connection.h"
 
 #define NETWORK_PEER_INTERFACE "org.bluez.Network1"
+#define BNEP_INTERFACE "bnep%d"
 
 typedef enum {
 	CONNECTED,
@@ -128,7 +129,8 @@ static void bnep_disconn_cb(gpointer data)
 
 	nc->state = DISCONNECTED;
 	memset(nc->dev, 0, sizeof(nc->dev));
-	strcpy(nc->dev, "bnep%d");
+	strncpy(nc->dev, BNEP_INTERFACE, 16);
+	nc->dev[15] = '\0';
 
 	bnep_free(nc->session);
 	nc->session = NULL;
@@ -243,7 +245,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
 	}
 
 	sk = g_io_channel_unix_get_fd(nc->io);
-	nc->session = bnep_new(sk, BNEP_SVC_PANU, nc->id);
+	nc->session = bnep_new(sk, BNEP_SVC_PANU, nc->id, BNEP_INTERFACE);
 	if (!nc->session)
 		goto failed;
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v2 1/5] profiles/network: Use interface name passed to bnep_connadd
From: Szymon Janc @ 2014-02-05 16:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391616034-23312-1-git-send-email-szymon.janc@tieto.com>

---
 profiles/network/bnep.c   | 5 +++--
 profiles/network/server.c | 4 ++++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 0d57056..82d0d99 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -174,9 +174,10 @@ static int bnep_connadd(int sk, uint16_t role, char *dev)
 {
 	struct bnep_connadd_req req;
 
-	memset(dev, 0, 16);
 	memset(&req, 0, sizeof(req));
-	strcpy(req.device, "bnep%d");
+	strncpy(req.device, dev, 16);
+	req.device[15] = '\0';
+
 	req.sock = sk;
 	req.role = role;
 	if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
diff --git a/profiles/network/server.c b/profiles/network/server.c
index f14d688..3fb031f 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -51,6 +51,7 @@
 #include "server.h"
 
 #define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
+#define BNEP_INTERFACE "bnep%d"
 #define SETUP_TIMEOUT		1
 
 /* Pending Authorization */
@@ -347,6 +348,9 @@ static gboolean bnep_setup(GIOChannel *chan,
 		goto reply;
 	}
 
+	strncpy(na->setup->dev, BNEP_INTERFACE, 16);
+	na->setup->dev[15] = '\0';
+
 	if (bnep_server_add(sk, dst_role, ns->bridge, na->setup->dev,
 							&na->setup->dst) < 0)
 		goto reply;
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v2 0/5] Android PAN fixes
From: Szymon Janc @ 2014-02-05 16:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Hi,

This is based on patch from Ravi (sent 23.01.2013). Changes include
patch split and some bugfixes.

BR
Szymon Janc

Ravi kumar Veeramally (1):
  android/pan: Fix bnep interface name

Szymon Janc (4):
  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.c                 | 174 ++++++++++++++++++++++++------------------
 profiles/network/bnep.c       |  10 ++-
 profiles/network/bnep.h       |   3 +-
 profiles/network/connection.c |   6 +-
 profiles/network/server.c     |   4 +
 5 files changed, 116 insertions(+), 81 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* Re: [PATCH] Bluetooth: hidp: make sure input buffers are big enough
From: Jiri Kosina @ 2014-02-05 15:49 UTC (permalink / raw)
  To: Marcel Holtmann, Gustavo F. Padovan
  Cc: David Herrmann, open list:HID CORE LAYER,
	linux-bluetooth@vger.kernel.org development
In-Reply-To: <20573666-E2A0-4D6B-986A-09DAFC0FB64B@holtmann.org>

On Tue, 4 Feb 2014, Marcel Holtmann wrote:

> >>>>> just got back to this, finally ... did you have time to work on this at
> >>>>> all, or should I just start from scratch?
> >>>> 
> >>>> Sorry, no. Fosdem is this weekend and I needed to get my code ready
> >>>> for that. But I'll finally have time again next week.
> >>> 
> >>> Okay, thanks. I then guess we should proceed with this bandaid (double
> >>> allocation) for 3.14
> >> 
> >> It would be really nice if we could get the HIDP patch into 3.14-rc2
> >> and backported to stable. There have been quite a bunch of reports now
> >> and I dislike adding a GFP_ATOMIC allocation in HID core. 
> > 
> > I agree with David; Gustavo, what is your take on this, please?
> 
> I leave this up to Gustavo to get this into wireless tree for 3.14-rc2.
> 
> Acked-by: Marcel Holtmann <marcel@holtmann.org>

Thanks a lot.

Gustavo, what is your take on this please? I can take it through hid.git 
in case you don't have anything else queued for -rc2.

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* [PATCH] android/haltest: Remove unneeded assignment
From: Andrei Emeltchenko @ 2014-02-05 15:45 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 android/client/if-audio.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index bb8f51b..72fea98 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -227,7 +227,6 @@ static void *playback_thread(void *data)
 
 	if (in) {
 		fclose(in);
-		in = NULL;
 	}
 
 	pthread_cleanup_pop(1);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH] android/haltest: Close file in case of error
From: Andrei Emeltchenko @ 2014-02-05 15:44 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 android/client/if-audio.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 66f8364..bb8f51b 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -258,6 +258,7 @@ static void play_p(int argc, const char **argv)
 
 	if (buffer_size == 0) {
 		haltest_error("Invalid buffer size. Was stream_out opened?\n");
+		fclose(in);
 		return;
 	}
 
@@ -265,12 +266,15 @@ static void play_p(int argc, const char **argv)
 	if (current_state != STATE_STOPPED) {
 		haltest_error("Already playing or stream suspended!\n");
 		pthread_mutex_unlock(&state_mutex);
+		fclose(in);
 		return;
 	}
 	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");
+		fclose(in);
+	}
 }
 
 static void stop_p(int argc, const char **argv)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/2] unit/avctp: Cleanup code, remove fragmentation support
From: Andrei Emeltchenko @ 2014-02-05 15:28 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391614102-21639-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 unit/test-avctp.c | 15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/unit/test-avctp.c b/unit/test-avctp.c
index 9d94ae0..be1dfd7 100644
--- a/unit/test-avctp.c
+++ b/unit/test-avctp.c
@@ -42,7 +42,6 @@
 
 struct test_pdu {
 	bool valid;
-	bool fragmented;
 	const uint8_t *data;
 	size_t size;
 };
@@ -71,14 +70,6 @@ struct context {
 		.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[] = {			\
@@ -133,9 +124,6 @@ static gboolean send_pdu(gpointer user_data)
 
 	g_assert_cmpint(len, ==, pdu->size);
 
-	if (pdu->fragmented)
-		return send_pdu(user_data);
-
 	context->process = 0;
 	return FALSE;
 }
@@ -180,8 +168,7 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 
 	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
 
-	if (!pdu->fragmented)
-		context_process(context);
+	context_process(context);
 
 	return TRUE;
 }
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 1/2] unit/avctp: Use pre-defined values instead of magic numbers
From: Andrei Emeltchenko @ 2014-02-05 15:28 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 unit/test-avctp.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/unit/test-avctp.c b/unit/test-avctp.c
index 581f88c..9d94ae0 100644
--- a/unit/test-avctp.c
+++ b/unit/test-avctp.c
@@ -277,8 +277,8 @@ static void test_client(gconstpointer data)
 {
 	struct context *context = create_context(0x0100, data);
 
-	avctp_send_vendordep_req(context->session, 0, 0, NULL, 0,
-						handler_response, context);
+	avctp_send_vendordep_req(context->session, AVC_CTYPE_CONTROL, 0, NULL,
+						0, handler_response, context);
 
 	execute_context(context);
 }
@@ -290,8 +290,8 @@ static void test_server(gconstpointer data)
 	if (g_str_equal(context->data->test_name, "/TP/NFR/BV-03-C")) {
 		int ret;
 
-		ret = avctp_register_pdu_handler(context->session, 0x00,
-								handler, NULL);
+		ret = avctp_register_pdu_handler(context->session,
+					AVC_OP_VENDORDEP, handler, NULL);
 		DBG("ret %d", ret);
 		g_assert_cmpint(ret, !=, 0);
 	}
-- 
1.8.3.2


^ permalink raw reply related

* Re: LE Connection Update Disallowed
From: Anderson Lizardo @ 2014-02-05 15:23 UTC (permalink / raw)
  To: Sandy Chapman; +Cc: BlueZ development
In-Reply-To: <CAPm3yA2LJMPOSGGzscQe8XV+gu8+kf5WZurk8DsSWEBBCOJcew@mail.gmail.com>

HI Sandy,

On Wed, Feb 5, 2014 at 10:51 AM, Sandy Chapman <schapman@lixar.com> wrote:
>>> How do I initiate a Connection Update from the peripheral?
>>
>> I never tried this procedure myself, but my guess it that you are
>> using the incorrect mechanism on the slave role. Take a look at the
>> "Connection Parameters Update Request" on Vol 3, Part A, Section 4.20.
>> I believe this is the correct way to request from the slave (from what
>> I understand while reading the Linux kernel implementation of the
>> master side).
>>
>> Note that when Linux is the master, this command is issued
>> automatically by the kernel when requested by the slave.
>
> I've taken a look at that section and it appears that this is what is
> used to trigger the Connection Update. It states that the command
> shall only be issued from the slave to the master. I can confirm that
> my device is in the slave role using 'hcitool con'.

I think you didn't notice that the section I mentioned is about a
L2CAP signalling packet, not an HCI command (which in this case is to
be used on the master side). I suggest you read a bit more on the
L2CAP section to understand how these signalling packets work. Then
you can try building such packet with "hcitool cmd" (unless there is
some support for it on the current kernel, which I didn't check)

>> You may want to take a look at the "GAP Peripheral Preferred
>> Connection Parameters" characteristic (see Vol 3, Part C, Section
>> 12.3). If iPhones reads this characteristic and honours the
>> parameters, it may help.
>
> Unfortunately, it appears Apple explicitly ignores this parameter
> (section 3.6 in this document
> https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf).

This is unfortunate. It would be the easiest way to pass custom
connection parameters IMHO.

> I believe that 'hcitool lecup' is exactly supposed to initiate this
> process. I've also tried to use 'hcitool cmd' to issue direct commands
> to the controller (using Vol 3, Part A, Section 4.20 as a guide), but
> I am having no luck. It's stating that the command is disallowed (not
> that the parameters are invalid), so I'm guessing there's something
> else wrong. Since this is directly communicating with the controller,
> where would the problem be? In the kernel, itself? Could it be a
> problem with the Broadcom chipset in my MacBook?

"hcitool lecup" is just a helper, it uses the same mechanism that
"hcitool cmd" uses (and both are just "raw" interfaces to the
Bluetooth controller). If you are getting an "Invalid Parameters" on
any of them, is either because you built the packet incorrectly on
"hcitool cmd" or given invalid values as per the spec.

By the way, I suggest using "btmon" instead of "hcidump", as the
former has nicer output and is more up-to-date (although I'm not sure
it supports parsing "LE Connection Update" parameters).

Best Regards,
-- 
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil

^ permalink raw reply

* Re: LE Connection Update Disallowed
From: Sandy Chapman @ 2014-02-05 14:51 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <CAJdJm_OK5TW3ECqQgF_JnUzO3McPCW=inG3HOxm1c_K4ODkWEQ@mail.gmail.com>

Hi Anderson,

On Wed, Feb 5, 2014 at 9:12 AM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Hi Sandy,
>
> On Wed, Feb 5, 2014 at 8:26 AM, Sandy Chapman <schapman@lixar.com> wrote:
>> I establish an LE connection between the devices. The central
>> successfully discovers the services and characteristics and can read
>> them. Once the connection is established, I run this command on the
>> Linux peripheral:
>>
>> $ sudo ./bin/hcitool lecup --handle 64 --min 24 --max 50 --latency 4
>> --timeout 550
>>>>> Could not change connection params: Input/output error(5)
>>
>> In my hcidump -X, I get this:
>>
>> < HCI Command: LE Connection Update (0x08|0x0013) plen 14
>>   0000: 40 00 18 00 32 00 04 00  26 02 01 00 01 00        @...2...&.....
>>> HCI Event: Command Status (0x0f) plen 4
>>     LE Connection Update (0x08|0x0013) status 0x0c ncmd 1
>>     Error: Command Disallowed
>
> This errors comes directly from the controller. The host is not at
> fault here, as hcitool issues HCI commands directly to the controller.
>
>> How do I initiate a Connection Update from the peripheral?
>
> I never tried this procedure myself, but my guess it that you are
> using the incorrect mechanism on the slave role. Take a look at the
> "Connection Parameters Update Request" on Vol 3, Part A, Section 4.20.
> I believe this is the correct way to request from the slave (from what
> I understand while reading the Linux kernel implementation of the
> master side).
>
> Note that when Linux is the master, this command is issued
> automatically by the kernel when requested by the slave.

I've taken a look at that section and it appears that this is what is
used to trigger the Connection Update. It states that the command
shall only be issued from the slave to the master. I can confirm that
my device is in the slave role using 'hcitool con'.

$ hcitool con
<<< Connections:
<<< Unknown 53:DC:05:A5:FA:7B handle 64 state 1 lm SLAVE

>
>> If this
>> isn't possible, how to I dictate the connection parameters (the
>> current connection is much too slow)?
>
> You may want to take a look at the "GAP Peripheral Preferred
> Connection Parameters" characteristic (see Vol 3, Part C, Section
> 12.3). If iPhones reads this characteristic and honours the
> parameters, it may help.

Unfortunately, it appears Apple explicitly ignores this parameter
(section 3.6 in this document
https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf).

>
> Best Regards,
> --
> Anderson Lizardo
> http://www.indt.org/?lang=en
> INdT - Manaus - Brazil

Now what I want to do is to issue a command to the controller to begin
the Connection Update. This would result in the linux slave issuing a
Connection Update packet to the iPhone master. This doesn't seem to be
happening and is being blocked.

I believe that 'hcitool lecup' is exactly supposed to initiate this
process. I've also tried to use 'hcitool cmd' to issue direct commands
to the controller (using Vol 3, Part A, Section 4.20 as a guide), but
I am having no luck. It's stating that the command is disallowed (not
that the parameters are invalid), so I'm guessing there's something
else wrong. Since this is directly communicating with the controller,
where would the problem be? In the kernel, itself? Could it be a
problem with the Broadcom chipset in my MacBook?

Thanks again,
Sandy

-- 


^ permalink raw reply

* [PATCH BlueZ 2/2] audio/AVCTP: Lookup key name from key_map table
From: Luiz Augusto von Dentz @ 2014-02-05 14:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391610272-12991-1-git-send-email-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

The key_map table already contain the key name.
---
 android/avctp.c        | 36 ++++++++----------------------------
 profiles/audio/avctp.c | 38 +++++++++-----------------------------
 2 files changed, 17 insertions(+), 57 deletions(-)

diff --git a/android/avctp.c b/android/avctp.c
index f7544a2..1e414d1 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -1136,36 +1136,16 @@ int avctp_send_browsing_req(struct avctp *session,
 	return 0;
 }
 
-static char *op2str(uint8_t op)
+static const char *op2str(uint8_t op)
 {
-	switch (op & 0x7f) {
-	case AVC_VOLUME_UP:
-		return "VOLUME UP";
-	case AVC_VOLUME_DOWN:
-		return "VOLUME DOWN";
-	case AVC_MUTE:
-		return "MUTE";
-	case AVC_PLAY:
-		return "PLAY";
-	case AVC_STOP:
-		return "STOP";
-	case AVC_PAUSE:
-		return "PAUSE";
-	case AVC_RECORD:
-		return "RECORD";
-	case AVC_REWIND:
-		return "REWIND";
-	case AVC_FAST_FORWARD:
-		return "FAST FORWARD";
-	case AVC_EJECT:
-		return "EJECT";
-	case AVC_FORWARD:
-		return "FORWARD";
-	case AVC_BACKWARD:
-		return "BACKWARD";
-	default:
-		return "UNKNOWN";
+	int i;
+
+	for (i = 0; key_map[i].name != NULL; i++) {
+		if ((op & 0x7F) == key_map[i].avc)
+			return key_map[i].name;
 	}
+
+	return "UNKNOWN";
 }
 
 static int avctp_passthrough_press(struct avctp *session, uint8_t op)
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index ae142bd..28c7685 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -1610,36 +1610,16 @@ int avctp_send_browsing_req(struct avctp *session,
 	return 0;
 }
 
-static char *op2str(uint8_t op)
-{
-	switch (op & 0x7f) {
-	case AVC_VOLUME_UP:
-		return "VOLUME UP";
-	case AVC_VOLUME_DOWN:
-		return "VOLUME DOWN";
-	case AVC_MUTE:
-		return "MUTE";
-	case AVC_PLAY:
-		return "PLAY";
-	case AVC_STOP:
-		return "STOP";
-	case AVC_PAUSE:
-		return "PAUSE";
-	case AVC_RECORD:
-		return "RECORD";
-	case AVC_REWIND:
-		return "REWIND";
-	case AVC_FAST_FORWARD:
-		return "FAST FORWARD";
-	case AVC_EJECT:
-		return "EJECT";
-	case AVC_FORWARD:
-		return "FORWARD";
-	case AVC_BACKWARD:
-		return "BACKWARD";
-	default:
-		return "UNKNOWN";
+static const char *op2str(uint8_t op)
+{
+	int i;
+
+	for (i = 0; key_map[i].name != NULL; i++) {
+		if ((op & 0x7F) == key_map[i].avc)
+			return key_map[i].name;
 	}
+
+	return "UNKNOWN";
 }
 
 static int avctp_passthrough_press(struct avctp *session, uint8_t op)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH BlueZ 1/2] audio/AVCTP: Add keys that can be mapped to uinput
From: Luiz Augusto von Dentz @ 2014-02-05 14:24 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds the remaining AV/C keys that can be mapped to uinput.
---
 android/avctp.c        | 28 ++++++++++++++++++++++++++++
 android/avctp.h        | 29 +++++++++++++++++++++++++++++
 profiles/audio/avctp.c | 28 ++++++++++++++++++++++++++++
 profiles/audio/avctp.h | 29 +++++++++++++++++++++++++++++
 4 files changed, 114 insertions(+)

diff --git a/android/avctp.c b/android/avctp.c
index 8f35403..f7544a2 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -215,25 +215,53 @@ static struct {
 	{ "ROOT MENU",		AVC_ROOT_MENU,		KEY_MENU },
 	{ "CONTENTS MENU",	AVC_CONTENTS_MENU,	KEY_PROGRAM },
 	{ "FAVORITE MENU",	AVC_FAVORITE_MENU,	KEY_FAVORITES },
+	{ "EXIT",		AVC_EXIT,		KEY_EXIT },
+	{ "ON DEMAND MENU",	AVC_ON_DEMAND_MENU,	KEY_MENU },
+	{ "APPS MENU",		AVC_APPS_MENU,		KEY_MENU },
+	{ "0",			AVC_0,			KEY_0 },
+	{ "1",			AVC_1,			KEY_1 },
+	{ "2",			AVC_2,			KEY_2 },
+	{ "3",			AVC_3,			KEY_3 },
+	{ "4",			AVC_4,			KEY_4 },
+	{ "5",			AVC_5,			KEY_5 },
+	{ "6",			AVC_6,			KEY_6 },
+	{ "7",			AVC_7,			KEY_7 },
+	{ "8",			AVC_8,			KEY_8 },
+	{ "9",			AVC_9,			KEY_9 },
+	{ "DOT",		AVC_DOT,		KEY_DOT },
 	{ "ENTER",		AVC_ENTER,		KEY_ENTER },
 	{ "CHANNEL UP",		AVC_CHANNEL_UP,		KEY_CHANNELUP },
 	{ "CHANNEL DOWN",	AVC_CHANNEL_DOWN,	KEY_CHANNELDOWN },
+	{ "CHANNEL PREVIOUS",	AVC_CHANNEL_PREVIOUS,	KEY_LAST },
 	{ "INPUT SELECT",	AVC_INPUT_SELECT,	KEY_CONFIG },
+	{ "INFO",		AVC_INFO,		KEY_INFO },
 	{ "HELP",		AVC_HELP,		KEY_HELP },
 	{ "POWER",		AVC_POWER,		KEY_POWER2 },
 	{ "VOLUME UP",		AVC_VOLUME_UP,		KEY_VOLUMEUP },
 	{ "VOLUME DOWN",	AVC_VOLUME_DOWN,	KEY_VOLUMEDOWN },
+	{ "MUTE",		AVC_MUTE,		KEY_MUTE },
 	{ "PLAY",		AVC_PLAY,		KEY_PLAYCD },
 	{ "STOP",		AVC_STOP,		KEY_STOPCD },
 	{ "PAUSE",		AVC_PAUSE,		KEY_PAUSECD },
 	{ "FORWARD",		AVC_FORWARD,		KEY_NEXTSONG },
 	{ "BACKWARD",		AVC_BACKWARD,		KEY_PREVIOUSSONG },
+	{ "RECORD",		AVC_RECORD,		KEY_RECORD },
 	{ "REWIND",		AVC_REWIND,		KEY_REWIND },
 	{ "FAST FORWARD",	AVC_FAST_FORWARD,	KEY_FASTFORWARD },
+	{ "LIST",		AVC_LIST,		KEY_LIST },
 	{ "F1",			AVC_F1,			KEY_F1 },
 	{ "F2",			AVC_F2,			KEY_F2 },
 	{ "F3",			AVC_F3,			KEY_F3 },
 	{ "F4",			AVC_F4,			KEY_F4 },
+	{ "F5",			AVC_F5,			KEY_F5 },
+	{ "F6",			AVC_F6,			KEY_F6 },
+	{ "F7",			AVC_F7,			KEY_F7 },
+	{ "F8",			AVC_F8,			KEY_F8 },
+	{ "F9",			AVC_F9,			KEY_F9 },
+	{ "RED",		AVC_RED,		KEY_RED },
+	{ "GREEN",		AVC_GREEN,		KEY_GREEN },
+	{ "BLUE",		AVC_BLUE,		KEY_BLUE },
+	{ "YELLOW",		AVC_YELLOW,		KEY_YELLOW },
 	{ NULL }
 };
 
diff --git a/android/avctp.h b/android/avctp.h
index e7e0277..dfa0ca6 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -56,11 +56,30 @@
 #define AVC_ROOT_MENU			0x09
 #define AVC_CONTENTS_MENU		0x0b
 #define AVC_FAVORITE_MENU		0x0c
+#define AVC_EXIT			0x0d
+#define AVC_ON_DEMAND_MENU		0x0e
+#define AVC_APPS_MENU			0x0f
+#define AVC_0				0x20
+#define AVC_1				0x21
+#define AVC_2				0x22
+#define AVC_3				0x23
+#define AVC_4				0x24
+#define AVC_5				0x25
+#define AVC_6				0x26
+#define AVC_7				0x27
+#define AVC_8				0x28
+#define AVC_9				0x29
+#define AVC_DOT				0x2a
 #define AVC_ENTER			0x2b
 #define AVC_CHANNEL_UP			0x30
 #define AVC_CHANNEL_DOWN		0x31
+#define AVC_CHANNEL_PREVIOUS		0x32
 #define AVC_INPUT_SELECT		0x34
+#define AVC_INFO			0x35
 #define AVC_HELP			0x36
+#define AVC_PAGE_UP			0x37
+#define AVC_PAGE_DOWN			0x38
+#define AVC_LOCK			0x3a
 #define AVC_POWER			0x40
 #define AVC_VOLUME_UP			0x41
 #define AVC_VOLUME_DOWN			0x42
@@ -74,10 +93,20 @@
 #define AVC_EJECT			0x4a
 #define AVC_FORWARD			0x4b
 #define AVC_BACKWARD			0x4c
+#define AVC_LIST			0x4d
 #define AVC_F1				0x71
 #define AVC_F2				0x72
 #define AVC_F3				0x73
 #define AVC_F4				0x74
+#define AVC_F5				0x75
+#define AVC_F6				0x76
+#define AVC_F7				0x77
+#define AVC_F8				0x78
+#define AVC_F9				0x79
+#define AVC_RED				0x7a
+#define AVC_GREEN			0x7b
+#define AVC_BLUE			0x7c
+#define AVC_YELLOW			0x7c
 
 struct avctp;
 
diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
index 9f87859..ae142bd 100644
--- a/profiles/audio/avctp.c
+++ b/profiles/audio/avctp.c
@@ -238,25 +238,53 @@ static struct {
 	{ "ROOT MENU",		AVC_ROOT_MENU,		KEY_MENU },
 	{ "CONTENTS MENU",	AVC_CONTENTS_MENU,	KEY_PROGRAM },
 	{ "FAVORITE MENU",	AVC_FAVORITE_MENU,	KEY_FAVORITES },
+	{ "EXIT",		AVC_EXIT,		KEY_EXIT },
+	{ "ON DEMAND MENU",	AVC_ON_DEMAND_MENU,	KEY_MENU },
+	{ "APPS MENU",		AVC_APPS_MENU,		KEY_MENU },
+	{ "0",			AVC_0,			KEY_0 },
+	{ "1",			AVC_1,			KEY_1 },
+	{ "2",			AVC_2,			KEY_2 },
+	{ "3",			AVC_3,			KEY_3 },
+	{ "4",			AVC_4,			KEY_4 },
+	{ "5",			AVC_5,			KEY_5 },
+	{ "6",			AVC_6,			KEY_6 },
+	{ "7",			AVC_7,			KEY_7 },
+	{ "8",			AVC_8,			KEY_8 },
+	{ "9",			AVC_9,			KEY_9 },
+	{ "DOT",		AVC_DOT,		KEY_DOT },
 	{ "ENTER",		AVC_ENTER,		KEY_ENTER },
 	{ "CHANNEL UP",		AVC_CHANNEL_UP,		KEY_CHANNELUP },
 	{ "CHANNEL DOWN",	AVC_CHANNEL_DOWN,	KEY_CHANNELDOWN },
+	{ "CHANNEL PREVIOUS",	AVC_CHANNEL_PREVIOUS,	KEY_LAST },
 	{ "INPUT SELECT",	AVC_INPUT_SELECT,	KEY_CONFIG },
+	{ "INFO",		AVC_INFO,		KEY_INFO },
 	{ "HELP",		AVC_HELP,		KEY_HELP },
 	{ "POWER",		AVC_POWER,		KEY_POWER2 },
 	{ "VOLUME UP",		AVC_VOLUME_UP,		KEY_VOLUMEUP },
 	{ "VOLUME DOWN",	AVC_VOLUME_DOWN,	KEY_VOLUMEDOWN },
+	{ "MUTE",		AVC_MUTE,		KEY_MUTE },
 	{ "PLAY",		AVC_PLAY,		KEY_PLAYCD },
 	{ "STOP",		AVC_STOP,		KEY_STOPCD },
 	{ "PAUSE",		AVC_PAUSE,		KEY_PAUSECD },
 	{ "FORWARD",		AVC_FORWARD,		KEY_NEXTSONG },
 	{ "BACKWARD",		AVC_BACKWARD,		KEY_PREVIOUSSONG },
+	{ "RECORD",		AVC_RECORD,		KEY_RECORD },
 	{ "REWIND",		AVC_REWIND,		KEY_REWIND },
 	{ "FAST FORWARD",	AVC_FAST_FORWARD,	KEY_FASTFORWARD },
+	{ "LIST",		AVC_LIST,		KEY_LIST },
 	{ "F1",			AVC_F1,			KEY_F1 },
 	{ "F2",			AVC_F2,			KEY_F2 },
 	{ "F3",			AVC_F3,			KEY_F3 },
 	{ "F4",			AVC_F4,			KEY_F4 },
+	{ "F5",			AVC_F5,			KEY_F5 },
+	{ "F6",			AVC_F6,			KEY_F6 },
+	{ "F7",			AVC_F7,			KEY_F7 },
+	{ "F8",			AVC_F8,			KEY_F8 },
+	{ "F9",			AVC_F9,			KEY_F9 },
+	{ "RED",		AVC_RED,		KEY_RED },
+	{ "GREEN",		AVC_GREEN,		KEY_GREEN },
+	{ "BLUE",		AVC_BLUE,		KEY_BLUE },
+	{ "YELLOW",		AVC_YELLOW,		KEY_YELLOW },
 	{ NULL }
 };
 
diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h
index f9c665e..05fceb4 100644
--- a/profiles/audio/avctp.h
+++ b/profiles/audio/avctp.h
@@ -57,11 +57,30 @@
 #define AVC_ROOT_MENU			0x09
 #define AVC_CONTENTS_MENU		0x0b
 #define AVC_FAVORITE_MENU		0x0c
+#define AVC_EXIT			0x0d
+#define AVC_ON_DEMAND_MENU		0x0e
+#define AVC_APPS_MENU			0x0f
+#define AVC_0				0x20
+#define AVC_1				0x21
+#define AVC_2				0x22
+#define AVC_3				0x23
+#define AVC_4				0x24
+#define AVC_5				0x25
+#define AVC_6				0x26
+#define AVC_7				0x27
+#define AVC_8				0x28
+#define AVC_9				0x29
+#define AVC_DOT				0x2a
 #define AVC_ENTER			0x2b
 #define AVC_CHANNEL_UP			0x30
 #define AVC_CHANNEL_DOWN		0x31
+#define AVC_CHANNEL_PREVIOUS		0x32
 #define AVC_INPUT_SELECT		0x34
+#define AVC_INFO			0x35
 #define AVC_HELP			0x36
+#define AVC_PAGE_UP			0x37
+#define AVC_PAGE_DOWN			0x38
+#define AVC_LOCK			0x3a
 #define AVC_POWER			0x40
 #define AVC_VOLUME_UP			0x41
 #define AVC_VOLUME_DOWN			0x42
@@ -75,10 +94,20 @@
 #define AVC_EJECT			0x4a
 #define AVC_FORWARD			0x4b
 #define AVC_BACKWARD			0x4c
+#define AVC_LIST			0x4d
 #define AVC_F1				0x71
 #define AVC_F2				0x72
 #define AVC_F3				0x73
 #define AVC_F4				0x74
+#define AVC_F5				0x75
+#define AVC_F6				0x76
+#define AVC_F7				0x77
+#define AVC_F8				0x78
+#define AVC_F9				0x79
+#define AVC_RED				0x7a
+#define AVC_GREEN			0x7b
+#define AVC_BLUE			0x7c
+#define AVC_YELLOW			0x7c
 
 struct avctp;
 
-- 
1.8.5.3


^ permalink raw reply related

* Re: [RFC 00/15] android/client: Add audio support
From: Szymon Janc @ 2014-02-05 14:13 UTC (permalink / raw)
  To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Hi Jakub,

On Thursday 30 of January 2014 12:23:06 Jakub Tyszkowski wrote:
> This patch set adds audio support for haltest tool. It provides basic audio HAL
> functionality and adds ability to play PCM audio files.
> 
> I've also added sound generator when no file path is provided for "play"
> command. We can leave that be or push sample audio file to the tree, and/or
> hardcode the path. I think that leaving audio file selection to the user and
> providing fallback to sound generator is the right solution. Please let me know
> what is yours preference.
> 
> Regards.
> 
> Jakub Tyszkowski (15):
>   android/client-av: Fix checking for a2dp interface
>   android/client-audio: Add open/close output stream
>   android/client-audio: Add audio file playback
>   android/client-audio: Add playback suspend/resume
>   android/client-audio: Add get_latency for output
>   android/client-audio: Add get_buffer_size for output
>   android/client-audio: Add get_channels
>   android/client-audio: Add getting audio format
>   android/client-audio: Add getting sample rate
>   android/client-audio: Add get_parameters for output
>   android/client-audio: Add set_parameters
>   android/client-audio: Add setting sample rate
>   android/client-audio: Add init_check
>   android/client-audio: Add sine generator as fallback
>   android/client-audio: Fix getting audio module on Android
> 
>  android/Makefile.am       |   2 +-
>  android/client/if-audio.c | 477 +++++++++++++++++++++++++++++++++++++++++++++-
>  android/client/if-av.c    |   4 +-
>  3 files changed, 479 insertions(+), 4 deletions(-)

Despite it being RFC it looks good for me so I've applied patches 1-14.

For 15 I think haltest should not try to stop media server as this might
have unexpected side effects on Android. If one wants to use haltest for
audio testing on Android he can disable media server by hand.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* Re: [PATCH BlueZ 1/4] android/AVRCP: Add bt_avrcp_connect
From: Szymon Janc @ 2014-02-05 13:45 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1391596020-27679-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Wednesday 05 of February 2014 12:26:57 Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> 
> This adds bt_avrcp_connect function which can be used to request AVRCP
> connections.
> ---
>  android/avrcp.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  android/avrcp.h |  2 ++
>  2 files changed, 57 insertions(+), 5 deletions(-)
> 
> diff --git a/android/avrcp.c b/android/avrcp.c
> index ef833df..8600d98 100644
> --- a/android/avrcp.c
> +++ b/android/avrcp.c
> @@ -54,6 +54,7 @@ static GIOChannel *server = NULL;
>  struct avrcp_device {
>  	bdaddr_t	dst;
>  	struct avctp	*session;
> +	GIOChannel	*io;
>  };
>  
>  static const struct ipc_handler cmd_handlers[] = {
> @@ -197,17 +198,20 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>  	}
>  
>  	ba2str(&dst, address);
> -	DBG("Incoming connection from %s", address);
>  
>  	l = g_slist_find_custom(devices, &dst, device_cmp);
>  	if (l) {
> -		error("Unexpected connection");
> -		return;
> +		dev = l->data;
> +		if (dev->session) {
> +			error("Unexpected connection");
> +			return;
> +		}
> +	} else {
> +		DBG("Incoming connection from %s", address);
> +		dev = avrcp_device_new(&dst);
>  	}
>  
>  	fd = g_io_channel_unix_get_fd(chan);
> -
> -	dev = avrcp_device_new(&dst);
>  	dev->session = avctp_new(fd, imtu, omtu, 0x0100);
>  
>  	if (!dev->session) {
> @@ -222,6 +226,11 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>  
>  	g_io_channel_set_close_on_unref(chan, FALSE);
>  
> +	if (dev->io) {
> +		g_io_channel_unref(dev->io);
> +		dev->io = NULL;
> +	}
> +
>  	DBG("%s connected", address);
>  }
>  
> @@ -288,3 +297,44 @@ void bt_avrcp_unregister(void)
>  		server = NULL;
>  	}
>  }
> +
> +static bool avrcp_device_connect(struct avrcp_device *dev, BtIOConnect cb)
> +{
> +	GError *err = NULL;
> +
> +	dev->io = bt_io_connect(cb, dev, NULL, &err,
> +					BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
> +					BT_IO_OPT_DEST_BDADDR, &dev->dst,
> +					BT_IO_OPT_PSM, L2CAP_PSM_AVCTP,
> +					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
> +					BT_IO_OPT_INVALID);
> +	if (err) {
> +		error("%s", err->message);
> +		g_error_free(err);
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +void bt_avrcp_connect(const bdaddr_t *dst)
> +{
> +	struct avrcp_device *dev;
> +	char addr[18];
> +	GSList *l;
> +
> +	DBG("");
> +
> +	l = g_slist_find_custom(devices, dst, device_cmp);
> +	if (l)
> +		return;
> +
> +	dev = avrcp_device_new(dst);
> +	if (!avrcp_device_connect(dev, connect_cb)) {
> +		avrcp_device_free(dev);
> +		return;
> +	}
> +
> +	ba2str(&dev->dst, addr);
> +	DBG("connecting to %s", addr);
> +}
> diff --git a/android/avrcp.h b/android/avrcp.h
> index 6fe7fbf..7b0a5ed 100644
> --- a/android/avrcp.h
> +++ b/android/avrcp.h
> @@ -23,3 +23,5 @@
>  
>  bool bt_avrcp_register(const bdaddr_t *addr);
>  void bt_avrcp_unregister(void);
> +
> +void bt_avrcp_connect(const bdaddr_t *dst);
> 

All four patches applied, thanks.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply


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