All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/26] Bluetooth: Management interface fixes
@ 2013-03-15 22:06 Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 01/26] Bluetooth: Move power on HCI command updates to their own function Johan Hedberg
                   ` (25 more replies)
  0 siblings, 26 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

Here's hopefully the last send of this set. v5 includes the flags mask
fix suggested by Marcel as well as updates to all those patches that
the mask inversion affects.

Johan

----------------------------------------------------------------
Johan Hedberg (26):
      Bluetooth: Move power on HCI command updates to their own function
      Bluetooth: Update mgmt powered HCI commands to use async requests
      Bluetooth: Wait for HCI command completion with mgmt_set_powered
      Bluetooth: Fix busy condition testing for EIR and class updates
      Bluetooth: Fix UUID/class mgmt command response synchronization
      Bluetooth: Remove useless HCI_PENDING_CLASS flag
      Bluetooth: Add a define for the HCI persistent flags mask
      Bluetooth: Clear non-persistent flags when closing HCI device
      Bluetooth: Fix clearing flags on power off before notifying mgmt
      Bluetooth: Fix waiting for EIR update when setting local name
      Bluetooth: Handle AD updating through an async request
      Bluetooth: Fix local name setting for LE-only controllers
      Bluetooth: Fix setting local name to the existing value
      Bluetooth: Use an async request for mgmt_set_connectable
      Bluetooth: Fix fast connectable response sending
      Bluetooth: Limit fast connectable support to >= 1.2 controllers
      Bluetooth: Fix error response for simultaneous fast connectable commands
      Bluetooth: Add proper flag for fast connectable mode
      Bluetooth: Refactor fast connectable HCI commands
      Bluetooth: Disable fast connectable when disabling connectable
      Bluetooth: Add reading of page scan parameters
      Bluetooth: Update page scan parameters after successful write commands
      Bluetooth: Fix updating page scan parameters when not necessary
      Bluetooth: Fix fast connectable state when enabling page scan
      Bluetooth: Simplify address parameters of user_pairing_resp()
      Bluetooth: Fix PIN/Confirm/Passkey response parameters

 include/net/bluetooth/hci.h      |   21 +-
 include/net/bluetooth/hci_core.h |    8 +-
 net/bluetooth/hci_core.c         |   42 ++-
 net/bluetooth/hci_event.c        |   97 +++++-
 net/bluetooth/mgmt.c             |  680 ++++++++++++++++++++++++++------------
 5 files changed, 599 insertions(+), 249 deletions(-)


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

* [PATCH v5 01/26] Bluetooth: Move power on HCI command updates to their own function
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 02/26] Bluetooth: Update mgmt powered HCI commands to use async requests Johan Hedberg
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

These commands will in a subsequent patch be performed in their own
asynchronous request, so it's more readable (not just from a resulting
code perspective but also the way the patches look like) to have them
performed in their own function.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   78 +++++++++++++++++++++++++++-----------------------
 1 file changed, 42 insertions(+), 36 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 39395c7..7d58b44 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3058,53 +3058,59 @@ static int set_bredr_scan(struct hci_dev *hdev)
 	return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 }
 
-int mgmt_powered(struct hci_dev *hdev, u8 powered)
+static int powered_update_hci(struct hci_dev *hdev)
 {
-	struct cmd_lookup match = { NULL, hdev };
-	int err;
+	u8 link_sec;
 
-	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
-		return 0;
+	if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
+	    !lmp_host_ssp_capable(hdev)) {
+		u8 ssp = 1;
 
-	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
+		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
+	}
 
-	if (powered) {
-		u8 link_sec;
+	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+		struct hci_cp_write_le_host_supported cp;
 
-		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
-		    !lmp_host_ssp_capable(hdev)) {
-			u8 ssp = 1;
+		cp.le = 1;
+		cp.simul = lmp_le_br_capable(hdev);
 
-			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
-		}
+		/* Check first if we already have the right
+		 * host state (host features set)
+		 */
+		if (cp.le != lmp_host_le_capable(hdev) ||
+		    cp.simul != lmp_host_le_br_capable(hdev))
+			hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
+				     sizeof(cp), &cp);
+	}
 
-		if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
-			struct hci_cp_write_le_host_supported cp;
+	link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
+	if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
+		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
+			     sizeof(link_sec), &link_sec);
 
-			cp.le = 1;
-			cp.simul = lmp_le_br_capable(hdev);
+	if (lmp_bredr_capable(hdev)) {
+		set_bredr_scan(hdev);
+		update_class(hdev);
+		update_name(hdev, hdev->dev_name);
+		update_eir(hdev);
+	}
 
-			/* Check first if we already have the right
-			 * host state (host features set)
-			 */
-			if (cp.le != lmp_host_le_capable(hdev) ||
-			    cp.simul != lmp_host_le_br_capable(hdev))
-				hci_send_cmd(hdev,
-					     HCI_OP_WRITE_LE_HOST_SUPPORTED,
-					     sizeof(cp), &cp);
-		}
+	return 0;
+}
 
-		link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
-		if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
-			hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
-				     sizeof(link_sec), &link_sec);
+int mgmt_powered(struct hci_dev *hdev, u8 powered)
+{
+	struct cmd_lookup match = { NULL, hdev };
+	int err;
 
-		if (lmp_bredr_capable(hdev)) {
-			set_bredr_scan(hdev);
-			update_class(hdev);
-			update_name(hdev, hdev->dev_name);
-			update_eir(hdev);
-		}
+	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
+		return 0;
+
+	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
+
+	if (powered) {
+		powered_update_hci(hdev);
 	} else {
 		u8 status = MGMT_STATUS_NOT_POWERED;
 		u8 zero_cod[] = { 0, 0, 0 };
-- 
1.7.10.4


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

* [PATCH v5 02/26] Bluetooth: Update mgmt powered HCI commands to use async requests
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 01/26] Bluetooth: Move power on HCI command updates to their own function Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 03/26] Bluetooth: Wait for HCI command completion with mgmt_set_powered Johan Hedberg
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch updates sending of HCI commands related to mgmt_set_powered
(e.g. class, name and EIR data) to be sent using asynchronous requests.
This is necessary since it's the only (well, at least the cleanest) way
to keep the power on procedure synchronized and let user space know it
has completed only when all HCI commands are completed (this actual fix
is coming in a subsequent patch).

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |  163 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 100 insertions(+), 63 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7d58b44..4726876 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -591,32 +591,33 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
 	ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
 }
 
-static int update_eir(struct hci_dev *hdev)
+static void update_eir(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_write_eir cp;
 
 	if (!hdev_is_powered(hdev))
-		return 0;
+		return;
 
 	if (!lmp_ext_inq_capable(hdev))
-		return 0;
+		return;
 
 	if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
-		return 0;
+		return;
 
 	if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
-		return 0;
+		return;
 
 	memset(&cp, 0, sizeof(cp));
 
 	create_eir(hdev, cp.data);
 
 	if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
-		return 0;
+		return;
 
 	memcpy(hdev->eir, cp.data, sizeof(cp.data));
 
-	return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
 }
 
 static u8 get_service_classes(struct hci_dev *hdev)
@@ -630,47 +631,50 @@ static u8 get_service_classes(struct hci_dev *hdev)
 	return val;
 }
 
-static int update_class(struct hci_dev *hdev)
+static void update_class(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	u8 cod[3];
-	int err;
 
 	BT_DBG("%s", hdev->name);
 
 	if (!hdev_is_powered(hdev))
-		return 0;
+		return;
 
 	if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
-		return 0;
+		return;
 
 	cod[0] = hdev->minor_class;
 	cod[1] = hdev->major_class;
 	cod[2] = get_service_classes(hdev);
 
 	if (memcmp(cod, hdev->dev_class, 3) == 0)
-		return 0;
+		return;
 
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
-	if (err == 0)
-		set_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
+	hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
 
-	return err;
+	set_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
 }
 
 static void service_cache_off(struct work_struct *work)
 {
 	struct hci_dev *hdev = container_of(work, struct hci_dev,
 					    service_cache.work);
+	struct hci_request req;
 
 	if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
 		return;
 
+	hci_req_init(&req, hdev);
+
 	hci_dev_lock(hdev);
 
-	update_eir(hdev);
-	update_class(hdev);
+	update_eir(&req);
+	update_class(&req);
 
 	hci_dev_unlock(hdev);
+
+	hci_req_run(&req, NULL);
 }
 
 static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
@@ -1355,6 +1359,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 {
 	struct mgmt_cp_add_uuid *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	struct bt_uuid *uuid;
 	int err;
 
@@ -1380,13 +1385,12 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	list_add_tail(&uuid->list, &hdev->uuids);
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto failed;
+	hci_req_init(&req, hdev);
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto failed;
+	update_class(&req);
+	update_eir(&req);
+
+	hci_req_run(&req, NULL);
 
 	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
@@ -1395,8 +1399,12 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
-	if (!cmd)
+	if (!cmd) {
 		err = -ENOMEM;
+		goto failed;
+	}
+
+	err = 0;
 
 failed:
 	hci_dev_unlock(hdev);
@@ -1424,6 +1432,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 	struct pending_cmd *cmd;
 	struct bt_uuid *match, *tmp;
 	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	struct hci_request req;
 	int err, found;
 
 	BT_DBG("request for %s", hdev->name);
@@ -1466,13 +1475,12 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 	}
 
 update_class:
-	err = update_class(hdev);
-	if (err < 0)
-		goto unlock;
+	hci_req_init(&req, hdev);
 
-	err = update_eir(hdev);
-	if (err < 0)
-		goto unlock;
+	update_class(&req);
+	update_eir(&req);
+
+	hci_req_run(&req, NULL);
 
 	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
@@ -1481,8 +1489,12 @@ update_class:
 	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
-	if (!cmd)
+	if (!cmd) {
 		err = -ENOMEM;
+		goto unlock;
+	}
+
+	err = 0;
 
 unlock:
 	hci_dev_unlock(hdev);
@@ -1494,6 +1506,7 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 {
 	struct mgmt_cp_set_dev_class *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	int err;
 
 	BT_DBG("request for %s", hdev->name);
@@ -1521,16 +1534,18 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 		goto unlock;
 	}
 
+	hci_req_init(&req, hdev);
+
 	if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
 		hci_dev_unlock(hdev);
 		cancel_delayed_work_sync(&hdev->service_cache);
 		hci_dev_lock(hdev);
-		update_eir(hdev);
+		update_eir(&req);
 	}
 
-	err = update_class(hdev);
-	if (err < 0)
-		goto unlock;
+	update_class(&req);
+
+	hci_req_run(&req, NULL);
 
 	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
@@ -1539,8 +1554,12 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 	}
 
 	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
-	if (!cmd)
+	if (!cmd) {
 		err = -ENOMEM;
+		goto unlock;
+	}
+
+	err = 0;
 
 unlock:
 	hci_dev_unlock(hdev);
@@ -2268,13 +2287,13 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
 				 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
 }
 
-static int update_name(struct hci_dev *hdev, const char *name)
+static void update_name(struct hci_request *req, const char *name)
 {
 	struct hci_cp_write_local_name cp;
 
 	memcpy(cp.name, name, sizeof(cp.name));
 
-	return hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
 }
 
 static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -2282,6 +2301,7 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 {
 	struct mgmt_cp_set_local_name *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	int err;
 
 	BT_DBG("");
@@ -2310,7 +2330,9 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 		goto failed;
 	}
 
-	err = update_name(hdev, cp->name);
+	hci_req_init(&req, hdev);
+	update_name(&req, cp->name);
+	err = hci_req_run(&req, NULL);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
 
@@ -2698,6 +2720,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
 			 u16 len)
 {
 	struct mgmt_cp_set_device_id *cp = data;
+	struct hci_request req;
 	int err;
 	__u16 source;
 
@@ -2718,7 +2741,9 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
 
-	update_eir(hdev);
+	hci_req_init(&req, hdev);
+	update_eir(&req);
+	hci_req_run(&req, NULL);
 
 	hci_dev_unlock(hdev);
 
@@ -3043,8 +3068,9 @@ static void settings_rsp(struct pending_cmd *cmd, void *data)
 	mgmt_pending_free(cmd);
 }
 
-static int set_bredr_scan(struct hci_dev *hdev)
+static void set_bredr_scan(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	u8 scan = 0;
 
 	if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
@@ -3052,21 +3078,22 @@ static int set_bredr_scan(struct hci_dev *hdev)
 	if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
 		scan |= SCAN_INQUIRY;
 
-	if (!scan)
-		return 0;
-
-	return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+	if (scan)
+		hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 }
 
 static int powered_update_hci(struct hci_dev *hdev)
 {
+	struct hci_request req;
 	u8 link_sec;
 
+	hci_req_init(&req, hdev);
+
 	if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
 	    !lmp_host_ssp_capable(hdev)) {
 		u8 ssp = 1;
 
-		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
+		hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
 	}
 
 	if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
@@ -3080,23 +3107,23 @@ static int powered_update_hci(struct hci_dev *hdev)
 		 */
 		if (cp.le != lmp_host_le_capable(hdev) ||
 		    cp.simul != lmp_host_le_br_capable(hdev))
-			hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
-				     sizeof(cp), &cp);
+			hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
+				    sizeof(cp), &cp);
 	}
 
 	link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
 	if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
-		hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
-			     sizeof(link_sec), &link_sec);
+		hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
+			    sizeof(link_sec), &link_sec);
 
 	if (lmp_bredr_capable(hdev)) {
-		set_bredr_scan(hdev);
-		update_class(hdev);
-		update_name(hdev, hdev->dev_name);
-		update_eir(hdev);
+		set_bredr_scan(&req);
+		update_class(&req);
+		update_name(&req, hdev->dev_name);
+		update_eir(&req);
 	}
 
-	return 0;
+	return hci_req_run(&req, NULL);
 }
 
 int mgmt_powered(struct hci_dev *hdev, u8 powered)
@@ -3561,23 +3588,25 @@ int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
 	return err;
 }
 
-static int clear_eir(struct hci_dev *hdev)
+static void clear_eir(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_write_eir cp;
 
 	if (!lmp_ext_inq_capable(hdev))
-		return 0;
+		return;
 
 	memset(hdev->eir, 0, sizeof(hdev->eir));
 
 	memset(&cp, 0, sizeof(cp));
 
-	return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+	hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
 }
 
 int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
 {
 	struct cmd_lookup match = { NULL, hdev };
+	struct hci_request req;
 	bool changed = false;
 	int err = 0;
 
@@ -3610,10 +3639,14 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
 	if (match.sk)
 		sock_put(match.sk);
 
+	hci_req_init(&req, hdev);
+
 	if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
-		update_eir(hdev);
+		update_eir(&req);
 	else
-		clear_eir(hdev);
+		clear_eir(&req);
+
+	hci_req_run(&req, NULL);
 
 	return err;
 }
@@ -3701,8 +3734,12 @@ send_event:
 	 * adapter so only update them here if this is a name change
 	 * unrelated to power on.
 	 */
-	if (!test_bit(HCI_INIT, &hdev->flags))
-		update_eir(hdev);
+	if (!test_bit(HCI_INIT, &hdev->flags)) {
+		struct hci_request req;
+		hci_req_init(&req, hdev);
+		update_eir(&req);
+		hci_req_run(&req, NULL);
+	}
 
 failed:
 	if (cmd)
-- 
1.7.10.4


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

* [PATCH v5 03/26] Bluetooth: Wait for HCI command completion with mgmt_set_powered
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 01/26] Bluetooth: Move power on HCI command updates to their own function Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 02/26] Bluetooth: Update mgmt powered HCI commands to use async requests Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 04/26] Bluetooth: Fix busy condition testing for EIR and class updates Johan Hedberg
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

We should only notify user space that the adapter has been powered on
after all HCI commands related to the action have completed. This patch
fixes the issue by instating an async request complete callback for
these HCI commands and only notifies user space in the callback.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   46 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4726876..bf17a62 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3082,6 +3082,24 @@ static void set_bredr_scan(struct hci_request *req)
 		hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 }
 
+static void powered_complete(struct hci_dev *hdev, u8 status)
+{
+	struct cmd_lookup match = { NULL, hdev };
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
+
+	new_settings(hdev, match.sk);
+
+	hci_dev_unlock(hdev);
+
+	if (match.sk)
+		sock_put(match.sk);
+}
+
 static int powered_update_hci(struct hci_dev *hdev)
 {
 	struct hci_request req;
@@ -3123,32 +3141,36 @@ static int powered_update_hci(struct hci_dev *hdev)
 		update_eir(&req);
 	}
 
-	return hci_req_run(&req, NULL);
+	return hci_req_run(&req, powered_complete);
 }
 
 int mgmt_powered(struct hci_dev *hdev, u8 powered)
 {
 	struct cmd_lookup match = { NULL, hdev };
+	u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
+	u8 zero_cod[] = { 0, 0, 0 };
 	int err;
 
 	if (!test_bit(HCI_MGMT, &hdev->dev_flags))
 		return 0;
 
-	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
-
 	if (powered) {
-		powered_update_hci(hdev);
-	} else {
-		u8 status = MGMT_STATUS_NOT_POWERED;
-		u8 zero_cod[] = { 0, 0, 0 };
-
-		mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
+		if (powered_update_hci(hdev) == 0)
+			return 0;
 
-		if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
-			mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
-				   zero_cod, sizeof(zero_cod), NULL);
+		mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
+				     &match);
+		goto new_settings;
 	}
 
+	mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
+	mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
+
+	if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
+		mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
+			   zero_cod, sizeof(zero_cod), NULL);
+
+new_settings:
 	err = new_settings(hdev, match.sk);
 
 	if (match.sk)
-- 
1.7.10.4


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

* [PATCH v5 04/26] Bluetooth: Fix busy condition testing for EIR and class updates
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (2 preceding siblings ...)
  2013-03-15 22:06 ` [PATCH v5 03/26] Bluetooth: Wait for HCI command completion with mgmt_set_powered Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 05/26] Bluetooth: Fix UUID/class mgmt command response synchronization Johan Hedberg
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

The add/remove_uuid and set_dev_class mgmt commands can trigger both EIR
and class HCI commands, so testing just for a pending class command is
enough. The simplest way to monitor conflicts that should trigger "busy"
error returns is to check for any pending mgmt command that can trigger
these HCI commands. This patch adds a helper function for this
(pending_eir_or_class) and uses it instead of the old HCI_PENDING_CLASS
flag to test for busy conditions.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   45 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 9 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index bf17a62..367837d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1336,6 +1336,29 @@ unlock:
 	return err;
 }
 
+/* This is a helper function to test for pending mgmt commands that can
+ * cause CoD or EIR HCI commands. We can only allow one such pending
+ * mgmt command at a time since otherwise we cannot easily track what
+ * the current values are, will be, and based on that calculate if a new
+ * HCI command needs to be sent and if yes with what value.
+ */
+static bool pending_eir_or_class(struct hci_dev *hdev)
+{
+	struct pending_cmd *cmd;
+
+	list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
+		switch (cmd->opcode) {
+		case MGMT_OP_ADD_UUID:
+		case MGMT_OP_REMOVE_UUID:
+		case MGMT_OP_SET_DEV_CLASS:
+		case MGMT_OP_SET_POWERED:
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static const u8 bluetooth_base_uuid[] = {
 			0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
 			0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1367,7 +1390,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	hci_dev_lock(hdev);
 
-	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
+	if (pending_eir_or_class(hdev)) {
 		err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
 				 MGMT_STATUS_BUSY);
 		goto failed;
@@ -1439,7 +1462,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	hci_dev_lock(hdev);
 
-	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
+	if (pending_eir_or_class(hdev)) {
 		err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
 				 MGMT_STATUS_BUSY);
 		goto unlock;
@@ -1515,15 +1538,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
 				  MGMT_STATUS_NOT_SUPPORTED);
 
-	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
-				  MGMT_STATUS_BUSY);
+	hci_dev_lock(hdev);
 
-	if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0)
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
-				  MGMT_STATUS_INVALID_PARAMS);
+	if (pending_eir_or_class(hdev)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
+				 MGMT_STATUS_BUSY);
+		goto unlock;
+	}
 
-	hci_dev_lock(hdev);
+	if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
+				 MGMT_STATUS_INVALID_PARAMS);
+		goto unlock;
+	}
 
 	hdev->major_class = cp->major;
 	hdev->minor_class = cp->minor;
-- 
1.7.10.4


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

* [PATCH v5 05/26] Bluetooth: Fix UUID/class mgmt command response synchronization
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (3 preceding siblings ...)
  2013-03-15 22:06 ` [PATCH v5 04/26] Bluetooth: Fix busy condition testing for EIR and class updates Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 06/26] Bluetooth: Remove useless HCI_PENDING_CLASS flag Johan Hedberg
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

We should only return a mgmt command complete once all HCI commands to a
mgmt_set_dev_class or mgmt_add/remove_uuid command have completed. This
patch fixes the issue by having a proper async request complete callback
for these actions and responding to user space in the callback.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   73 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 56 insertions(+), 17 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 367837d..8a0bbb9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1378,6 +1378,32 @@ static u8 get_uuid_size(const u8 *uuid)
 	return 16;
 }
 
+static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
+{
+	struct pending_cmd *cmd;
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(mgmt_op, hdev);
+	if (!cmd)
+		goto unlock;
+
+	cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
+		     hdev->dev_class, 3);
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
+static void add_uuid_complete(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("status 0x%02x", status);
+
+	mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
+}
+
 static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 {
 	struct mgmt_cp_add_uuid *cp = data;
@@ -1413,9 +1439,11 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 	update_class(&req);
 	update_eir(&req);
 
-	hci_req_run(&req, NULL);
+	err = hci_req_run(&req, add_uuid_complete);
+	if (err < 0) {
+		if (err != -ENODATA)
+			goto failed;
 
-	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
 				   hdev->dev_class, 3);
 		goto failed;
@@ -1448,6 +1476,13 @@ static bool enable_service_cache(struct hci_dev *hdev)
 	return false;
 }
 
+static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("status 0x%02x", status);
+
+	mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
+}
+
 static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 		       u16 len)
 {
@@ -1503,9 +1538,11 @@ update_class:
 	update_class(&req);
 	update_eir(&req);
 
-	hci_req_run(&req, NULL);
+	err = hci_req_run(&req, remove_uuid_complete);
+	if (err < 0) {
+		if (err != -ENODATA)
+			goto unlock;
 
-	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
 				   hdev->dev_class, 3);
 		goto unlock;
@@ -1524,6 +1561,13 @@ unlock:
 	return err;
 }
 
+static void set_class_complete(struct hci_dev *hdev, u8 status)
+{
+	BT_DBG("status 0x%02x", status);
+
+	mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
+}
+
 static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 			 u16 len)
 {
@@ -1572,9 +1616,11 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	update_class(&req);
 
-	hci_req_run(&req, NULL);
+	err = hci_req_run(&req, set_class_complete);
+	if (err < 0) {
+		if (err != -ENODATA)
+			goto unlock;
 
-	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
 		err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
 				   hdev->dev_class, 3);
 		goto unlock;
@@ -3700,21 +3746,14 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
 	return err;
 }
 
-static void class_rsp(struct pending_cmd *cmd, void *data)
+static void sk_lookup(struct pending_cmd *cmd, void *data)
 {
 	struct cmd_lookup *match = data;
 
-	cmd_complete(cmd->sk, cmd->index, cmd->opcode, match->mgmt_status,
-		     match->hdev->dev_class, 3);
-
-	list_del(&cmd->list);
-
 	if (match->sk == NULL) {
 		match->sk = cmd->sk;
 		sock_hold(match->sk);
 	}
-
-	mgmt_pending_free(cmd);
 }
 
 int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
@@ -3725,9 +3764,9 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
 
 	clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
 
-	mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, class_rsp, &match);
-	mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, class_rsp, &match);
-	mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, class_rsp, &match);
+	mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
+	mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
+	mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
 
 	if (!status)
 		err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class,
-- 
1.7.10.4


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

* [PATCH v5 06/26] Bluetooth: Remove useless HCI_PENDING_CLASS flag
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (4 preceding siblings ...)
  2013-03-15 22:06 ` [PATCH v5 05/26] Bluetooth: Fix UUID/class mgmt command response synchronization Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 07/26] Bluetooth: Add a define for the HCI persistent flags mask Johan Hedberg
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

Now that class related operations are tracked through asynchronous HCI
requests this flag is no longer needed.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci.h |    1 -
 net/bluetooth/hci_event.c   |    3 +--
 net/bluetooth/mgmt.c        |    4 ----
 3 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 7f12c25f..1e723c7 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -119,7 +119,6 @@ enum {
 	HCI_CONNECTABLE,
 	HCI_DISCOVERABLE,
 	HCI_LINK_SECURITY,
-	HCI_PENDING_CLASS,
 	HCI_PERIODIC_INQ,
 };
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d11b87b..5f2d008 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -194,8 +194,7 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 	clear_bit(HCI_RESET, &hdev->flags);
 
 	/* Reset all non-persistent flags */
-	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
-			     BIT(HCI_PERIODIC_INQ));
+	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ));
 
 	hdev->discovery.state = DISCOVERY_STOPPED;
 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8a0bbb9..3e3cb01 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -652,8 +652,6 @@ static void update_class(struct hci_request *req)
 		return;
 
 	hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
-
-	set_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
 }
 
 static void service_cache_off(struct work_struct *work)
@@ -3762,8 +3760,6 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
 	struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
 	int err = 0;
 
-	clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
-
 	mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
 	mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
 	mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
-- 
1.7.10.4


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

* [PATCH v5 07/26] Bluetooth: Add a define for the HCI persistent flags mask
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (5 preceding siblings ...)
  2013-03-15 22:06 ` [PATCH v5 06/26] Bluetooth: Remove useless HCI_PENDING_CLASS flag Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 08/26] Bluetooth: Clear non-persistent flags when closing HCI device Johan Hedberg
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

We'll need to use this mask also when powering off the HCI device
so it's better to have this in a single and visible place.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci.h |    5 +++++
 net/bluetooth/hci_event.c   |    2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 1e723c7..1e40222 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -122,6 +122,11 @@ enum {
 	HCI_PERIODIC_INQ,
 };
 
+/* A mask for the flags that are supposed to remain when a reset happens
+ * or the HCI device is closed.
+ */
+#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ))
+
 /* HCI ioctl defines */
 #define HCIDEVUP	_IOW('H', 201, int)
 #define HCIDEVDOWN	_IOW('H', 202, int)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 5f2d008..ed4ecd9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -194,7 +194,7 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 	clear_bit(HCI_RESET, &hdev->flags);
 
 	/* Reset all non-persistent flags */
-	hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ));
+	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
 	hdev->discovery.state = DISCOVERY_STOPPED;
 	hdev->inq_tx_power = HCI_TX_POWER_INVALID;
-- 
1.7.10.4


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

* [PATCH v5 08/26] Bluetooth: Clear non-persistent flags when closing HCI device
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (6 preceding siblings ...)
  2013-03-15 22:06 ` [PATCH v5 07/26] Bluetooth: Add a define for the HCI persistent flags mask Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:06 ` [PATCH v5 09/26] Bluetooth: Fix clearing flags on power off before notifying mgmt Johan Hedberg
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

When hci_dev_do_close() is called we should make sure to clear all
non-persistent flags in hci->dev_flags.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_core.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 02070dc..059bbae 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1139,6 +1139,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
 	/* Clear flags */
 	hdev->flags = 0;
+	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
 	/* Controller radio is available but is currently powered down */
 	hdev->amp_status = 0;
-- 
1.7.10.4


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

* [PATCH v5 09/26] Bluetooth: Fix clearing flags on power off before notifying mgmt
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (7 preceding siblings ...)
  2013-03-15 22:06 ` [PATCH v5 08/26] Bluetooth: Clear non-persistent flags when closing HCI device Johan Hedberg
@ 2013-03-15 22:06 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 10/26] Bluetooth: Fix waiting for EIR update when setting local name Johan Hedberg
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:06 UTC (permalink / raw)
  To: linux-bluetooth

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

When powering off the device the hdev->flags and hdev->dev_flags need to
be cleared before calling mgmt_powered(). If this is not done the
resulting events sent to user space may contain incorrect values.

Note that the HCI_AUTO_OFF flag accessed right after this is part of the
persistent flags, so it's unchanged by the hdev->dev_flags reset.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_core.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 059bbae..9e87a91 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1130,6 +1130,10 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 	 * and no tasks are scheduled. */
 	hdev->close(hdev);
 
+	/* Clear flags */
+	hdev->flags = 0;
+	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
+
 	if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
 	    mgmt_valid_hdev(hdev)) {
 		hci_dev_lock(hdev);
@@ -1137,10 +1141,6 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 		hci_dev_unlock(hdev);
 	}
 
-	/* Clear flags */
-	hdev->flags = 0;
-	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
-
 	/* Controller radio is available but is currently powered down */
 	hdev->amp_status = 0;
 
-- 
1.7.10.4


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

* [PATCH v5 10/26] Bluetooth: Fix waiting for EIR update when setting local name
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (8 preceding siblings ...)
  2013-03-15 22:06 ` [PATCH v5 09/26] Bluetooth: Fix clearing flags on power off before notifying mgmt Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 11/26] Bluetooth: Handle AD updating through an async request Johan Hedberg
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

We shouldn't respond to the mgmt_set_local_name command until all
related HCI commands have completed. This patch fixes the issue by
running the local name HCI command and the EIR update in the same
asynchronous request, and returning the mgmt command complete through
the complete callback of the request.

The downside of this is that we must set hdev->dev_name before the local
name HCI command has completed since otherwise the generated EIR
command doesn't contain the new name. This means that we can no-longer
reliably detect when the name has really changed and when not. Luckily
this only affects scenarios where the mgmt interface is *not* used (e.g.
hciconfig) so redundant mgmt_ev_local_name_changed events in these cases
are an acceptable drawback.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   96 ++++++++++++++++++++++++++------------------------
 1 file changed, 49 insertions(+), 47 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3e3cb01..1d50841 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2358,15 +2358,44 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
 				 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
 }
 
-static void update_name(struct hci_request *req, const char *name)
+static void update_name(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_write_local_name cp;
 
-	memcpy(cp.name, name, sizeof(cp.name));
+	memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
 
 	hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
 }
 
+static void set_name_complete(struct hci_dev *hdev, u8 status)
+{
+	struct mgmt_cp_set_local_name *cp;
+	struct pending_cmd *cmd;
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
+	if (!cmd)
+		goto unlock;
+
+	cp = cmd->param;
+
+	if (status)
+		cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
+			   mgmt_status(status));
+	else
+		cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
+			     cp, sizeof(*cp));
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
 static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 			  u16 len)
 {
@@ -2401,9 +2430,12 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 		goto failed;
 	}
 
+	memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
+
 	hci_req_init(&req, hdev);
-	update_name(&req, cp->name);
-	err = hci_req_run(&req, NULL);
+	update_name(&req);
+	update_eir(&req);
+	err = hci_req_run(&req, set_name_complete);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
 
@@ -3208,7 +3240,7 @@ static int powered_update_hci(struct hci_dev *hdev)
 	if (lmp_bredr_capable(hdev)) {
 		set_bredr_scan(&req);
 		update_class(&req);
-		update_name(&req, hdev->dev_name);
+		update_name(&req);
 		update_eir(&req);
 	}
 
@@ -3776,59 +3808,29 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
 
 int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
 {
-	struct pending_cmd *cmd;
 	struct mgmt_cp_set_local_name ev;
-	bool changed = false;
-	int err = 0;
+	struct pending_cmd *cmd;
 
-	if (memcmp(name, hdev->dev_name, sizeof(hdev->dev_name)) != 0) {
-		memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
-		changed = true;
-	}
+	if (status)
+		return 0;
 
 	memset(&ev, 0, sizeof(ev));
 	memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
 	memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
 
 	cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
-	if (!cmd)
-		goto send_event;
-
-	/* Always assume that either the short or the complete name has
-	 * changed if there was a pending mgmt command */
-	changed = true;
-
-	if (status) {
-		err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
-				 mgmt_status(status));
-		goto failed;
-	}
-
-	err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, &ev,
-			   sizeof(ev));
-	if (err < 0)
-		goto failed;
-
-send_event:
-	if (changed)
-		err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev,
-				 sizeof(ev), cmd ? cmd->sk : NULL);
+	if (!cmd) {
+		memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
 
-	/* EIR is taken care of separately when powering on the
-	 * adapter so only update them here if this is a name change
-	 * unrelated to power on.
-	 */
-	if (!test_bit(HCI_INIT, &hdev->flags)) {
-		struct hci_request req;
-		hci_req_init(&req, hdev);
-		update_eir(&req);
-		hci_req_run(&req, NULL);
+		/* If this is a HCI command related to powering on the
+		 * HCI dev don't send any mgmt signals.
+		 */
+		if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
+			return 0;
 	}
 
-failed:
-	if (cmd)
-		mgmt_pending_remove(cmd);
-	return err;
+	return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
+			  cmd ? cmd->sk : NULL);
 }
 
 int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
-- 
1.7.10.4


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

* [PATCH v5 11/26] Bluetooth: Handle AD updating through an async request
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (9 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 10/26] Bluetooth: Fix waiting for EIR update when setting local name Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 12/26] Bluetooth: Fix local name setting for LE-only controllers Johan Hedberg
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

For proper control of the AD update and the related HCI commands it's
best to run the AD update through an async request instead of a
standalone HCI command. This patch changes the hci_update_ad() function
to take a request pointer and updates its users appropriately. E.g. the
function is no longer called after the init sequence but during stage 3
of the init sequence.

The TX power is read during the init sequence, so we don't need an
explicit update whenever it is read and the AD update based on the local
name should be done through the local name mgmt handler. The only other
user is the update based on enabling advertising. This part is still
kept as there is no mgmt API to enable it.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci_core.h |    4 ++--
 net/bluetooth/hci_core.c         |   29 ++++++++++-------------------
 net/bluetooth/hci_event.c        |   19 +++++++++----------
 3 files changed, 21 insertions(+), 31 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d6c3256..cb99193 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -740,8 +740,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
 								u8 *randomizer);
 int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
-int hci_update_ad(struct hci_dev *hdev);
-
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
 int hci_recv_frame(struct sk_buff *skb);
@@ -1167,6 +1165,8 @@ struct hci_sec_filter {
 #define hci_req_lock(d)		mutex_lock(&d->req_lock)
 #define hci_req_unlock(d)	mutex_unlock(&d->req_lock)
 
+void hci_update_ad(struct hci_request *req);
+
 void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 					u16 latency, u16 to_multiplier);
 void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9e87a91..0ffd358 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -492,8 +492,10 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
 	if (hdev->commands[5] & 0x10)
 		hci_setup_link_policy(req);
 
-	if (lmp_le_capable(hdev))
+	if (lmp_le_capable(hdev)) {
 		hci_set_le_support(req);
+		hci_update_ad(req);
+	}
 }
 
 static int __hci_init(struct hci_dev *hdev)
@@ -936,39 +938,29 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
 	return ad_len;
 }
 
-int hci_update_ad(struct hci_dev *hdev)
+void hci_update_ad(struct hci_request *req)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_le_set_adv_data cp;
 	u8 len;
-	int err;
-
-	hci_dev_lock(hdev);
 
-	if (!lmp_le_capable(hdev)) {
-		err = -EINVAL;
-		goto unlock;
-	}
+	if (!lmp_le_capable(hdev))
+		return;
 
 	memset(&cp, 0, sizeof(cp));
 
 	len = create_ad(hdev, cp.data);
 
 	if (hdev->adv_data_len == len &&
-	    memcmp(cp.data, hdev->adv_data, len) == 0) {
-		err = 0;
-		goto unlock;
-	}
+	    memcmp(cp.data, hdev->adv_data, len) == 0)
+		return;
 
 	memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
 	hdev->adv_data_len = len;
 
 	cp.length = len;
-	err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
 
-unlock:
-	hci_dev_unlock(hdev);
-
-	return err;
+	hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
 }
 
 /* ---- HCI ioctl helpers ---- */
@@ -1025,7 +1017,6 @@ int hci_dev_open(__u16 dev)
 		hci_dev_hold(hdev);
 		set_bit(HCI_UP, &hdev->flags);
 		hci_notify(hdev, HCI_DEV_UP);
-		hci_update_ad(hdev);
 		if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
 		    mgmt_valid_hdev(hdev)) {
 			hci_dev_lock(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ed4ecd9..84edacb 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -223,9 +223,6 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 		memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
 
 	hci_dev_unlock(hdev);
-
-	if (!status && !test_bit(HCI_INIT, &hdev->flags))
-		hci_update_ad(hdev);
 }
 
 static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -776,11 +773,8 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
 
 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
-	if (!rp->status) {
+	if (!rp->status)
 		hdev->adv_tx_power = rp->tx_power;
-		if (!test_bit(HCI_INIT, &hdev->flags))
-			hci_update_ad(hdev);
-	}
 }
 
 static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
@@ -877,10 +871,15 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 			clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
 	}
 
-	hci_dev_unlock(hdev);
+	if (!test_bit(HCI_INIT, &hdev->flags)) {
+		struct hci_request req;
 
-	if (!test_bit(HCI_INIT, &hdev->flags))
-		hci_update_ad(hdev);
+		hci_req_init(&req, hdev);
+		hci_update_ad(&req);
+		hci_req_run(&req, NULL);
+	}
+
+	hci_dev_unlock(hdev);
 }
 
 static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
-- 
1.7.10.4


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

* [PATCH v5 12/26] Bluetooth: Fix local name setting for LE-only controllers
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (10 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 11/26] Bluetooth: Handle AD updating through an async request Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 13/26] Bluetooth: Fix setting local name to the existing value Johan Hedberg
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch fixes the mgmt_set_local_name command to send the appropriate
HCI commands based on BR/EDR support and LE support. Local name and EIR
data should only be sent for BR/EDR capable controllers whereas an
update to the AD should only happen for LE capable controllers.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1d50841..28e5975 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2433,8 +2433,15 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 	memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
 
 	hci_req_init(&req, hdev);
-	update_name(&req);
-	update_eir(&req);
+
+	if (lmp_bredr_capable(hdev)) {
+		update_name(&req);
+		update_eir(&req);
+	}
+
+	if (lmp_le_capable(hdev))
+		hci_update_ad(&req);
+
 	err = hci_req_run(&req, set_name_complete);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
-- 
1.7.10.4


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

* [PATCH v5 13/26] Bluetooth: Fix setting local name to the existing value
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (11 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 12/26] Bluetooth: Fix local name setting for LE-only controllers Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 14/26] Bluetooth: Use an async request for mgmt_set_connectable Johan Hedberg
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

If user space attempts to set the local name to the same value that's
already set we should simply return a direct command complete for this
mgmt command.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 28e5975..15305fa 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2408,6 +2408,17 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	hci_dev_lock(hdev);
 
+	/* If the old values are the same as the new ones just return a
+	 * direct command complete event.
+	 */
+	if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
+	    !memcmp(hdev->short_name, cp->short_name,
+		    sizeof(hdev->short_name))) {
+		err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
+				   data, len);
+		goto failed;
+	}
+
 	memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
 
 	if (!hdev_is_powered(hdev)) {
-- 
1.7.10.4


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

* [PATCH v5 14/26] Bluetooth: Use an async request for mgmt_set_connectable
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (12 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 13/26] Bluetooth: Fix setting local name to the existing value Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 15/26] Bluetooth: Fix fast connectable response sending Johan Hedberg
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch changes the mgmt_set_connectable handler to use an async
request for sending the required HCI command. This is necessary
preparation for handling the fast connectable change that needs to be
associated with disabling the connectable setting.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 15305fa..a4f928d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -996,11 +996,32 @@ failed:
 	return err;
 }
 
+static void set_connectable_complete(struct hci_dev *hdev, u8 status)
+{
+	struct pending_cmd *cmd;
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
+	if (!cmd)
+		goto unlock;
+
+	send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
 static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 			   u16 len)
 {
 	struct mgmt_mode *cp = data;
 	struct pending_cmd *cmd;
+	struct hci_request req;
 	u8 scan;
 	int err;
 
@@ -1067,7 +1088,11 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 			cancel_delayed_work(&hdev->discov_off);
 	}
 
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+	hci_req_init(&req, hdev);
+
+	hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+
+	err = hci_req_run(&req, set_connectable_complete);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
 
@@ -3328,7 +3353,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
 
 int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
 {
-	struct cmd_lookup match = { NULL, hdev };
+	struct pending_cmd *cmd;
 	bool changed = false;
 	int err = 0;
 
@@ -3340,14 +3365,10 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
 			changed = true;
 	}
 
-	mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp,
-			     &match);
+	cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
 
 	if (changed)
-		err = new_settings(hdev, match.sk);
-
-	if (match.sk)
-		sock_put(match.sk);
+		err = new_settings(hdev, cmd ? cmd->sk : NULL);
 
 	return err;
 }
-- 
1.7.10.4


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

* [PATCH v5 15/26] Bluetooth: Fix fast connectable response sending
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (13 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 14/26] Bluetooth: Use an async request for mgmt_set_connectable Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 16/26] Bluetooth: Limit fast connectable support to >= 1.2 controllers Johan Hedberg
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

The mgmt_set_fast_connectable response should be sent only when all
related HCI commands have completed. This patch fixes the issue by using
an async request and sending the response to user space throught the
complete callback of the request. The patch also fixes in the same go
the return parameters of the command which should be the current
settings.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   53 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 11 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a4f928d..bd61318 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2896,11 +2896,39 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
 	return err;
 }
 
+static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
+{
+	struct pending_cmd *cmd;
+
+	BT_DBG("status 0x%02x", status);
+
+	hci_dev_lock(hdev);
+
+	cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
+	if (!cmd)
+		goto unlock;
+
+	if (status) {
+		cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+			   mgmt_status(status));
+	} else {
+		send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
+		new_settings(hdev, cmd->sk);
+	}
+
+	mgmt_pending_remove(cmd);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
 static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 				void *data, u16 len)
 {
 	struct mgmt_mode *cp = data;
 	struct hci_cp_write_page_scan_activity acp;
+	struct pending_cmd *cmd;
+	struct hci_request req;
 	u8 type;
 	int err;
 
@@ -2939,25 +2967,28 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 	/* default 11.25 msec page scan window */
 	acp.window = __constant_cpu_to_le16(0x0012);
 
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp),
-			   &acp);
-	if (err < 0) {
-		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
-				 MGMT_STATUS_FAILED);
-		goto done;
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
+			       data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto unlock;
 	}
 
-	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+	hci_req_init(&req, hdev);
+
+	hci_req_add(&req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), &acp);
+	hci_req_add(&req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+
+	err = hci_req_run(&req, fast_connectable_complete);
 	if (err < 0) {
 		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 				 MGMT_STATUS_FAILED);
-		goto done;
+		mgmt_pending_remove(cmd);
 	}
 
-	err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0,
-			   NULL, 0);
-done:
+unlock:
 	hci_dev_unlock(hdev);
+
 	return err;
 }
 
-- 
1.7.10.4


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

* [PATCH v5 16/26] Bluetooth: Limit fast connectable support to >= 1.2 controllers
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (14 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 15/26] Bluetooth: Fix fast connectable response sending Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 17/26] Bluetooth: Fix error response for simultaneous fast connectable commands Johan Hedberg
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

The HCI commands that are necessary for fast connectable mode are only
available from HCI specification version 1.2 onwards. This should be
reflected in the supported settings as well as error response for the
set_fast_connectable command when dealing with a < 1.2 capable
controller.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index bd61318..34caf30 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -384,7 +384,8 @@ static u32 get_supported_settings(struct hci_dev *hdev)
 
 	if (lmp_bredr_capable(hdev)) {
 		settings |= MGMT_SETTING_CONNECTABLE;
-		settings |= MGMT_SETTING_FAST_CONNECTABLE;
+		if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
+			settings |= MGMT_SETTING_FAST_CONNECTABLE;
 		settings |= MGMT_SETTING_DISCOVERABLE;
 		settings |= MGMT_SETTING_BREDR;
 		settings |= MGMT_SETTING_LINK_SECURITY;
@@ -2934,7 +2935,7 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("%s", hdev->name);
 
-	if (!lmp_bredr_capable(hdev))
+	if (!lmp_bredr_capable(hdev) || hdev->hci_ver < BLUETOOTH_VER_1_2)
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 				  MGMT_STATUS_NOT_SUPPORTED);
 
-- 
1.7.10.4


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

* [PATCH v5 17/26] Bluetooth: Fix error response for simultaneous fast connectable commands
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (15 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 16/26] Bluetooth: Limit fast connectable support to >= 1.2 controllers Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 18/26] Bluetooth: Add proper flag for fast connectable mode Johan Hedberg
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

If there's another pending mgmt_set_fast_connectable command we should
return a "busy" error response.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 34caf30..e89938e0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2953,6 +2953,12 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 
 	hci_dev_lock(hdev);
 
+	if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+				 MGMT_STATUS_BUSY);
+		goto unlock;
+	}
+
 	if (cp->val) {
 		type = PAGE_SCAN_TYPE_INTERLACED;
 
-- 
1.7.10.4


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

* [PATCH v5 18/26] Bluetooth: Add proper flag for fast connectable mode
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (16 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 17/26] Bluetooth: Fix error response for simultaneous fast connectable commands Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 19/26] Bluetooth: Refactor fast connectable HCI commands Johan Hedberg
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

In order to be able to represent fast connectable mode in the mgmt
settings we need to have a HCI dev flag for it. This patch adds the flag
and makes sure its value is changed whenever a mgmt_set_fast_connectable
command completes.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci.h |    4 +++-
 net/bluetooth/mgmt.c        |   16 ++++++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 1e40222..b854506 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -120,12 +120,14 @@ enum {
 	HCI_DISCOVERABLE,
 	HCI_LINK_SECURITY,
 	HCI_PERIODIC_INQ,
+	HCI_FAST_CONNECTABLE,
 };
 
 /* A mask for the flags that are supposed to remain when a reset happens
  * or the HCI device is closed.
  */
-#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ))
+#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \
+			      BIT(HCI_FAST_CONNECTABLE))
 
 /* HCI ioctl defines */
 #define HCIDEVUP	_IOW('H', 201, int)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e89938e0..b6a33c5 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -410,6 +410,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
 	if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
 		settings |= MGMT_SETTING_CONNECTABLE;
 
+	if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
+		settings |= MGMT_SETTING_FAST_CONNECTABLE;
+
 	if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
 		settings |= MGMT_SETTING_DISCOVERABLE;
 
@@ -2913,6 +2916,13 @@ static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
 		cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 			   mgmt_status(status));
 	} else {
+		struct mgmt_mode *cp = cmd->param;
+
+		if (cp->val)
+			set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
+		else
+			clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
+
 		send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
 		new_settings(hdev, cmd->sk);
 	}
@@ -2959,6 +2969,12 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 		goto unlock;
 	}
 
+	if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
+		err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
+					hdev);
+		goto unlock;
+	}
+
 	if (cp->val) {
 		type = PAGE_SCAN_TYPE_INTERLACED;
 
-- 
1.7.10.4


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

* [PATCH v5 19/26] Bluetooth: Refactor fast connectable HCI commands
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (17 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 18/26] Bluetooth: Add proper flag for fast connectable mode Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 20/26] Bluetooth: Disable fast connectable when disabling connectable Johan Hedberg
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch refactors the fast connectable HCI commands into their own
HCI function. This is necessary so that the same function can be reused
fo the fast connectable change required by disabling the connectable
setting.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   43 ++++++++++++++++++++++++-------------------
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index b6a33c5..f03b10c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1000,6 +1000,29 @@ failed:
 	return err;
 }
 
+static void write_fast_connectable(struct hci_request *req, bool enable)
+{
+	struct hci_cp_write_page_scan_activity acp;
+	u8 type;
+
+	if (enable) {
+		type = PAGE_SCAN_TYPE_INTERLACED;
+
+		/* 160 msec page scan interval */
+		acp.interval = __constant_cpu_to_le16(0x0100);
+	} else {
+		type = PAGE_SCAN_TYPE_STANDARD;	/* default */
+
+		/* default 1.28 sec page scan */
+		acp.interval = __constant_cpu_to_le16(0x0800);
+	}
+
+	acp.window = __constant_cpu_to_le16(0x0012);
+
+	hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), &acp);
+	hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+}
+
 static void set_connectable_complete(struct hci_dev *hdev, u8 status)
 {
 	struct pending_cmd *cmd;
@@ -2937,10 +2960,8 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 				void *data, u16 len)
 {
 	struct mgmt_mode *cp = data;
-	struct hci_cp_write_page_scan_activity acp;
 	struct pending_cmd *cmd;
 	struct hci_request req;
-	u8 type;
 	int err;
 
 	BT_DBG("%s", hdev->name);
@@ -2975,21 +2996,6 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 		goto unlock;
 	}
 
-	if (cp->val) {
-		type = PAGE_SCAN_TYPE_INTERLACED;
-
-		/* 160 msec page scan interval */
-		acp.interval = __constant_cpu_to_le16(0x0100);
-	} else {
-		type = PAGE_SCAN_TYPE_STANDARD;	/* default */
-
-		/* default 1.28 sec page scan */
-		acp.interval = __constant_cpu_to_le16(0x0800);
-	}
-
-	/* default 11.25 msec page scan window */
-	acp.window = __constant_cpu_to_le16(0x0012);
-
 	cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
 			       data, len);
 	if (!cmd) {
@@ -2999,8 +3005,7 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 
 	hci_req_init(&req, hdev);
 
-	hci_req_add(&req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), &acp);
-	hci_req_add(&req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+	write_fast_connectable(&req, cp->val);
 
 	err = hci_req_run(&req, fast_connectable_complete);
 	if (err < 0) {
-- 
1.7.10.4


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

* [PATCH v5 20/26] Bluetooth: Disable fast connectable when disabling connectable
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (18 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 19/26] Bluetooth: Refactor fast connectable HCI commands Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 21/26] Bluetooth: Add reading of page scan parameters Johan Hedberg
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

When the connectable setting is disabled the fast connectable setting
must also be disabled. This is so that we're consistent with the
pre-requisites for enabling fast connectable, one of which is that the
connectable setting is enabled.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index f03b10c..98f6295 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1119,6 +1119,9 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 
+	if (!cp->val && test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
+		write_fast_connectable(&req, false);
+
 	err = hci_req_run(&req, set_connectable_complete);
 	if (err < 0)
 		mgmt_pending_remove(cmd);
-- 
1.7.10.4


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

* [PATCH v5 21/26] Bluetooth: Add reading of page scan parameters
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (19 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 20/26] Bluetooth: Disable fast connectable when disabling connectable Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 22/26] Bluetooth: Update page scan parameters after successful write commands Johan Hedberg
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

These parameters are related to the "fast connectable" mode that can be
changed through the mgmt interface. Not all controllers properly reset
these values with HCI_Reset so they need to be read in order to be able
to verify whether the values are correct or not before enabling page
scan.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 include/net/bluetooth/hci.h      |   13 +++++++++++++
 include/net/bluetooth/hci_core.h |    4 ++++
 net/bluetooth/hci_core.c         |    6 ++++++
 net/bluetooth/hci_event.c        |   32 ++++++++++++++++++++++++++++++++
 4 files changed, 55 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b854506..b330892 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -887,12 +887,25 @@ struct hci_rp_read_data_block_size {
 	__le16   num_blocks;
 } __packed;
 
+#define HCI_OP_READ_PAGE_SCAN_ACTIVITY	0x0c1b
+struct hci_rp_read_page_scan_activity {
+	__u8     status;
+	__le16   interval;
+	__le16   window;
+} __packed;
+
 #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY	0x0c1c
 struct hci_cp_write_page_scan_activity {
 	__le16   interval;
 	__le16   window;
 } __packed;
 
+#define HCI_OP_READ_PAGE_SCAN_TYPE	0x0c46
+struct hci_rp_read_page_scan_type {
+	__u8     status;
+	__u8     type;
+} __packed;
+
 #define HCI_OP_WRITE_PAGE_SCAN_TYPE	0x0c47
 	#define PAGE_SCAN_TYPE_STANDARD		0x00
 	#define PAGE_SCAN_TYPE_INTERLACED	0x01
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cb99193..358a698 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -165,6 +165,10 @@ struct hci_dev {
 	__u16		voice_setting;
 	__u8		io_capability;
 	__s8		inq_tx_power;
+	__u16		page_scan_interval;
+	__u16		page_scan_window;
+	__u8		page_scan_type;
+
 	__u16		devid_source;
 	__u16		devid_vendor;
 	__u16		devid_product;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 0ffd358..cfcad54 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -272,6 +272,12 @@ static void bredr_setup(struct hci_request *req)
 	bacpy(&cp.bdaddr, BDADDR_ANY);
 	cp.delete_all = 0x01;
 	hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
+
+	/* Read page scan parameters */
+	if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) {
+		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
+		hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
+	}
 }
 
 static void le_setup(struct hci_request *req)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 84edacb..38cf645 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -601,6 +601,30 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
 		bacpy(&hdev->bdaddr, &rp->bdaddr);
 }
 
+static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
+					   struct sk_buff *skb)
+{
+	struct hci_rp_read_page_scan_activity *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) {
+		hdev->page_scan_interval = __le16_to_cpu(rp->interval);
+		hdev->page_scan_window = __le16_to_cpu(rp->window);
+	}
+}
+
+static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
+					   struct sk_buff *skb)
+{
+	struct hci_rp_read_page_scan_type *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+	if (test_bit(HCI_INIT, &hdev->flags) && !rp->status)
+		hdev->page_scan_type = __le16_to_cpu(rp->type);
+}
+
 static void hci_cc_read_data_block_size(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
@@ -2204,6 +2228,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_read_bd_addr(hdev, skb);
 		break;
 
+	case HCI_OP_READ_PAGE_SCAN_ACTIVITY:
+		hci_cc_read_page_scan_activity(hdev, skb);
+		break;
+
+	case HCI_OP_READ_PAGE_SCAN_TYPE:
+		hci_cc_read_page_scan_type(hdev, skb);
+		break;
+
 	case HCI_OP_READ_DATA_BLOCK_SIZE:
 		hci_cc_read_data_block_size(hdev, skb);
 		break;
-- 
1.7.10.4


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

* [PATCH v5 22/26] Bluetooth: Update page scan parameters after successful write commands
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (20 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 21/26] Bluetooth: Add reading of page scan parameters Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 23/26] Bluetooth: Fix updating page scan parameters when not necessary Johan Hedberg
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

The page scan parameters (interval, window and type) stored in struct
hci_dev should not only be updated after successful reads but also after
successful writes. This patch adds the necessary handlers for the write
command complete events and updates the stored values through them.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/hci_event.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 38cf645..8a1f511 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -614,6 +614,25 @@ static void hci_cc_read_page_scan_activity(struct hci_dev *hdev,
 	}
 }
 
+static void hci_cc_write_page_scan_activity(struct hci_dev *hdev,
+					    struct sk_buff *skb)
+{
+	u8 status = *((u8 *) skb->data);
+	struct hci_cp_write_page_scan_activity *sent;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	if (status)
+		return;
+
+	sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
+	if (!sent)
+		return;
+
+	hdev->page_scan_interval = __le16_to_cpu(sent->interval);
+	hdev->page_scan_window = __le16_to_cpu(sent->window);
+}
+
 static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
 					   struct sk_buff *skb)
 {
@@ -625,6 +644,22 @@ static void hci_cc_read_page_scan_type(struct hci_dev *hdev,
 		hdev->page_scan_type = __le16_to_cpu(rp->type);
 }
 
+static void hci_cc_write_page_scan_type(struct hci_dev *hdev,
+					struct sk_buff *skb)
+{
+	u8 status = *((u8 *) skb->data);
+	u8 *type;
+
+	BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+	if (status)
+		return;
+
+	type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
+	if (type)
+		hdev->page_scan_type = *type;
+}
+
 static void hci_cc_read_data_block_size(struct hci_dev *hdev,
 					struct sk_buff *skb)
 {
@@ -2232,10 +2267,18 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cc_read_page_scan_activity(hdev, skb);
 		break;
 
+	case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY:
+		hci_cc_write_page_scan_activity(hdev, skb);
+		break;
+
 	case HCI_OP_READ_PAGE_SCAN_TYPE:
 		hci_cc_read_page_scan_type(hdev, skb);
 		break;
 
+	case HCI_OP_WRITE_PAGE_SCAN_TYPE:
+		hci_cc_write_page_scan_type(hdev, skb);
+		break;
+
 	case HCI_OP_READ_DATA_BLOCK_SIZE:
 		hci_cc_read_data_block_size(hdev, skb);
 		break;
-- 
1.7.10.4


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

* [PATCH v5 23/26] Bluetooth: Fix updating page scan parameters when not necessary
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (21 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 22/26] Bluetooth: Update page scan parameters after successful write commands Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 24/26] Bluetooth: Fix fast connectable state when enabling page scan Johan Hedberg
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

Now that the current page scan parameters are stored in struct hci_dev
we should check against those values before sending new HCI commands to
change them.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 98f6295..7783b8d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1002,6 +1002,7 @@ failed:
 
 static void write_fast_connectable(struct hci_request *req, bool enable)
 {
+	struct hci_dev *hdev = req->hdev;
 	struct hci_cp_write_page_scan_activity acp;
 	u8 type;
 
@@ -1019,8 +1020,13 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
 
 	acp.window = __constant_cpu_to_le16(0x0012);
 
-	hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), &acp);
-	hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
+	if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
+	    __cpu_to_le16(hdev->page_scan_window) != acp.window)
+		hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
+			    sizeof(acp), &acp);
+
+	if (hdev->page_scan_type != type)
+		hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
 }
 
 static void set_connectable_complete(struct hci_dev *hdev, u8 status)
-- 
1.7.10.4


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

* [PATCH v5 24/26] Bluetooth: Fix fast connectable state when enabling page scan
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (22 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 23/26] Bluetooth: Fix updating page scan parameters when not necessary Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 25/26] Bluetooth: Simplify address parameters of user_pairing_resp() Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters Johan Hedberg
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

When powering on or enabling page scan we need to ensure that the page
scan parameters are as they should be. This is because some controllers
do not properly reset these values upon HCI_Reset. Since the
write_scan_parameters function is now called from several new places it
also checks for the >= 1.2 HCI version requirement before sending the
commands.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7783b8d..75c9d92 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1006,6 +1006,9 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
 	struct hci_cp_write_page_scan_activity acp;
 	u8 type;
 
+	if (hdev->hci_ver < BLUETOOTH_VER_1_2)
+		return;
+
 	if (enable) {
 		type = PAGE_SCAN_TYPE_INTERLACED;
 
@@ -1125,7 +1128,13 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 
-	if (!cp->val && test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
+	/* If we're going from non-connectable to connectable or
+	 * vice-versa when fast connectable is enabled ensure that fast
+	 * connectable gets disabled. write_fast_connectable won't do
+	 * anything if the page scan parameters are already what they
+	 * should be.
+	 */
+	if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
 		write_fast_connectable(&req, false);
 
 	err = hci_req_run(&req, set_connectable_complete);
@@ -3287,6 +3296,12 @@ static void set_bredr_scan(struct hci_request *req)
 	struct hci_dev *hdev = req->hdev;
 	u8 scan = 0;
 
+	/* Ensure that fast connectable is disabled. This function will
+	 * not do anything if the page scan parameters are already what
+	 * they should be.
+	 */
+	write_fast_connectable(req, false);
+
 	if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
 		scan |= SCAN_PAGE;
 	if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
-- 
1.7.10.4


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

* [PATCH v5 25/26] Bluetooth: Simplify address parameters of user_pairing_resp()
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (23 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 24/26] Bluetooth: Fix fast connectable state when enabling page scan Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-15 22:07 ` [PATCH v5 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters Johan Hedberg
  25 siblings, 0 replies; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

Instead of passing the bdaddr and bdaddr_type as separate parameters to
user_pairing_resp it's simpler to just pass the original mgmt_addr_info
struct which contains both values.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 75c9d92..8587229 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2300,7 +2300,7 @@ unlock:
 }
 
 static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
-			     bdaddr_t *bdaddr, u8 type, u16 mgmt_op,
+			     struct mgmt_addr_info *addr, u16 mgmt_op,
 			     u16 hci_op, __le32 passkey)
 {
 	struct pending_cmd *cmd;
@@ -2315,10 +2315,10 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 		goto done;
 	}
 
-	if (type == BDADDR_BREDR)
-		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr);
+	if (addr->type == BDADDR_BREDR)
+		conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
 	else
-		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
+		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
 
 	if (!conn) {
 		err = cmd_status(sk, hdev->id, mgmt_op,
@@ -2326,7 +2326,7 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 		goto done;
 	}
 
-	if (type == BDADDR_LE_PUBLIC || type == BDADDR_LE_RANDOM) {
+	if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
 		/* Continue with pairing via SMP */
 		err = smp_user_confirm_reply(conn, mgmt_op, passkey);
 
@@ -2340,7 +2340,7 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 		goto done;
 	}
 
-	cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr));
+	cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
 	if (!cmd) {
 		err = -ENOMEM;
 		goto done;
@@ -2350,11 +2350,12 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 	if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
 		struct hci_cp_user_passkey_reply cp;
 
-		bacpy(&cp.bdaddr, bdaddr);
+		bacpy(&cp.bdaddr, &addr->bdaddr);
 		cp.passkey = passkey;
 		err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
 	} else
-		err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
+		err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
+				   &addr->bdaddr);
 
 	if (err < 0)
 		mgmt_pending_remove(cmd);
@@ -2371,7 +2372,7 @@ static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				MGMT_OP_PIN_CODE_NEG_REPLY,
 				HCI_OP_PIN_CODE_NEG_REPLY, 0);
 }
@@ -2387,7 +2388,7 @@ static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
 		return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
 				  MGMT_STATUS_INVALID_PARAMS);
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_CONFIRM_REPLY,
 				 HCI_OP_USER_CONFIRM_REPLY, 0);
 }
@@ -2399,7 +2400,7 @@ static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_CONFIRM_NEG_REPLY,
 				 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
 }
@@ -2411,7 +2412,7 @@ static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_PASSKEY_REPLY,
 				 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
 }
@@ -2423,7 +2424,7 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr,
 				 MGMT_OP_USER_PASSKEY_NEG_REPLY,
 				 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
 }
-- 
1.7.10.4


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

* [PATCH v5 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters
  2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (24 preceding siblings ...)
  2013-03-15 22:07 ` [PATCH v5 25/26] Bluetooth: Simplify address parameters of user_pairing_resp() Johan Hedberg
@ 2013-03-15 22:07 ` Johan Hedberg
  2013-03-18 17:08   ` Gustavo Padovan
  25 siblings, 1 reply; 28+ messages in thread
From: Johan Hedberg @ 2013-03-15 22:07 UTC (permalink / raw)
  To: linux-bluetooth

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

The only valid mgmt response to these pairing related commands is a
mgmt_cmd_complete and the returned parameters should contain the address
and address type of the remote device.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
---
 net/bluetooth/mgmt.c |   20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8587229..03e7e73 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2310,8 +2310,9 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, hdev->id, mgmt_op,
-				 MGMT_STATUS_NOT_POWERED);
+		err = cmd_complete(sk, hdev->id, mgmt_op,
+				   MGMT_STATUS_NOT_POWERED, addr,
+				   sizeof(*addr));
 		goto done;
 	}
 
@@ -2321,8 +2322,9 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
 
 	if (!conn) {
-		err = cmd_status(sk, hdev->id, mgmt_op,
-				 MGMT_STATUS_NOT_CONNECTED);
+		err = cmd_complete(sk, hdev->id, mgmt_op,
+				   MGMT_STATUS_NOT_CONNECTED, addr,
+				   sizeof(*addr));
 		goto done;
 	}
 
@@ -2331,11 +2333,13 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
 		err = smp_user_confirm_reply(conn, mgmt_op, passkey);
 
 		if (!err)
-			err = cmd_status(sk, hdev->id, mgmt_op,
-					 MGMT_STATUS_SUCCESS);
+			err = cmd_complete(sk, hdev->id, mgmt_op,
+					   MGMT_STATUS_SUCCESS, addr,
+					   sizeof(*addr));
 		else
-			err = cmd_status(sk, hdev->id, mgmt_op,
-					 MGMT_STATUS_FAILED);
+			err = cmd_complete(sk, hdev->id, mgmt_op,
+					   MGMT_STATUS_FAILED, addr,
+					   sizeof(*addr));
 
 		goto done;
 	}
-- 
1.7.10.4


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

* Re: [PATCH v5 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters
  2013-03-15 22:07 ` [PATCH v5 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters Johan Hedberg
@ 2013-03-18 17:08   ` Gustavo Padovan
  0 siblings, 0 replies; 28+ messages in thread
From: Gustavo Padovan @ 2013-03-18 17:08 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

* Johan Hedberg <johan.hedberg@gmail.com> [2013-03-15 17:07:16 -0500]:

> From: Johan Hedberg <johan.hedberg@intel.com>
> 
> The only valid mgmt response to these pairing related commands is a
> mgmt_cmd_complete and the returned parameters should contain the address
> and address type of the remote device.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> Acked-by: Marcel Holtmann <marcel@holtmann.org>
> ---
>  net/bluetooth/mgmt.c |   20 ++++++++++++--------
>  1 file changed, 12 insertions(+), 8 deletions(-)

All patches have been applied to bluetooth-next. Thanks.

	Gustavo

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

end of thread, other threads:[~2013-03-18 17:08 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-15 22:06 [PATCH v5 00/26] Bluetooth: Management interface fixes Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 01/26] Bluetooth: Move power on HCI command updates to their own function Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 02/26] Bluetooth: Update mgmt powered HCI commands to use async requests Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 03/26] Bluetooth: Wait for HCI command completion with mgmt_set_powered Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 04/26] Bluetooth: Fix busy condition testing for EIR and class updates Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 05/26] Bluetooth: Fix UUID/class mgmt command response synchronization Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 06/26] Bluetooth: Remove useless HCI_PENDING_CLASS flag Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 07/26] Bluetooth: Add a define for the HCI persistent flags mask Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 08/26] Bluetooth: Clear non-persistent flags when closing HCI device Johan Hedberg
2013-03-15 22:06 ` [PATCH v5 09/26] Bluetooth: Fix clearing flags on power off before notifying mgmt Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 10/26] Bluetooth: Fix waiting for EIR update when setting local name Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 11/26] Bluetooth: Handle AD updating through an async request Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 12/26] Bluetooth: Fix local name setting for LE-only controllers Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 13/26] Bluetooth: Fix setting local name to the existing value Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 14/26] Bluetooth: Use an async request for mgmt_set_connectable Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 15/26] Bluetooth: Fix fast connectable response sending Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 16/26] Bluetooth: Limit fast connectable support to >= 1.2 controllers Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 17/26] Bluetooth: Fix error response for simultaneous fast connectable commands Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 18/26] Bluetooth: Add proper flag for fast connectable mode Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 19/26] Bluetooth: Refactor fast connectable HCI commands Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 20/26] Bluetooth: Disable fast connectable when disabling connectable Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 21/26] Bluetooth: Add reading of page scan parameters Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 22/26] Bluetooth: Update page scan parameters after successful write commands Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 23/26] Bluetooth: Fix updating page scan parameters when not necessary Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 24/26] Bluetooth: Fix fast connectable state when enabling page scan Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 25/26] Bluetooth: Simplify address parameters of user_pairing_resp() Johan Hedberg
2013-03-15 22:07 ` [PATCH v5 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters Johan Hedberg
2013-03-18 17:08   ` Gustavo Padovan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.