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

Hi,

I'm sending all 26 patches I had pending in my local tree, as requested
by Marcel. The first six in this set are identical to my patch set
titled "[PATCH v3 0/6] Bluetooth: HCI command synchronisation fixes".

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] 32+ messages in thread

* [PATCH v4 01/26] Bluetooth: Move power on HCI command updates to their own function
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 02/26] Bluetooth: Update mgmt powered HCI commands to use async requests Johan Hedberg
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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] 32+ messages in thread

* [PATCH v4 02/26] Bluetooth: Update mgmt powered HCI commands to use async requests
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 01/26] Bluetooth: Move power on HCI command updates to their own function Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 03/26] Bluetooth: Wait for HCI command completion with mgmt_set_powered Johan Hedberg
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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] 32+ messages in thread

* [PATCH v4 03/26] Bluetooth: Wait for HCI command completion with mgmt_set_powered
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 01/26] Bluetooth: Move power on HCI command updates to their own function Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 02/26] Bluetooth: Update mgmt powered HCI commands to use async requests Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 04/26] Bluetooth: Fix busy condition testing for EIR and class updates Johan Hedberg
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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] 32+ messages in thread

* [PATCH v4 04/26] Bluetooth: Fix busy condition testing for EIR and class updates
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (2 preceding siblings ...)
  2013-03-13 18:11 ` [PATCH v4 03/26] Bluetooth: Wait for HCI command completion with mgmt_set_powered Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 05/26] Bluetooth: Fix UUID/class mgmt command response synchronization Johan Hedberg
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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] 32+ messages in thread

* [PATCH v4 05/26] Bluetooth: Fix UUID/class mgmt command response synchronization
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (3 preceding siblings ...)
  2013-03-13 18:11 ` [PATCH v4 04/26] Bluetooth: Fix busy condition testing for EIR and class updates Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 06/26] Bluetooth: Remove useless HCI_PENDING_CLASS flag Johan Hedberg
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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] 32+ messages in thread

* [PATCH v4 06/26] Bluetooth: Remove useless HCI_PENDING_CLASS flag
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (4 preceding siblings ...)
  2013-03-13 18:11 ` [PATCH v4 05/26] Bluetooth: Fix UUID/class mgmt command response synchronization Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-13 18:11 ` [PATCH v4 07/26] Bluetooth: Add a define for the HCI persistent flags mask Johan Hedberg
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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] 32+ messages in thread

* [PATCH v4 07/26] Bluetooth: Add a define for the HCI persistent flags mask
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (5 preceding siblings ...)
  2013-03-13 18:11 ` [PATCH v4 06/26] Bluetooth: Remove useless HCI_PENDING_CLASS flag Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-15 20:23   ` Marcel Holtmann
  2013-03-13 18:11 ` [PATCH v4 08/26] Bluetooth: Clear non-persistent flags when closing HCI device Johan Hedberg
                   ` (20 subsequent siblings)
  27 siblings, 1 reply; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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..a09d5e9 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..ec24d9a 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] 32+ messages in thread

* [PATCH v4 08/26] Bluetooth: Clear non-persistent flags when closing HCI device
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (6 preceding siblings ...)
  2013-03-13 18:11 ` [PATCH v4 07/26] Bluetooth: Add a define for the HCI persistent flags mask Johan Hedberg
@ 2013-03-13 18:11 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 09/26] Bluetooth: Fix clearing flags on power off before notifying mgmt Johan Hedberg
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:11 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>
---
 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..37ee261 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] 32+ messages in thread

* [PATCH v4 09/26] Bluetooth: Fix clearing flags on power off before notifying mgmt
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (7 preceding siblings ...)
  2013-03-13 18:11 ` [PATCH v4 08/26] Bluetooth: Clear non-persistent flags when closing HCI device Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 10/26] Bluetooth: Fix waiting for EIR update when setting local name Johan Hedberg
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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 37ee261..5436e02 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] 32+ messages in thread

* [PATCH v4 10/26] Bluetooth: Fix waiting for EIR update when setting local name
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (8 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 09/26] Bluetooth: Fix clearing flags on power off before notifying mgmt Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 11/26] Bluetooth: Handle AD updating through an async request Johan Hedberg
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 11/26] Bluetooth: Handle AD updating through an async request
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (9 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 10/26] Bluetooth: Fix waiting for EIR update when setting local name Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 12/26] Bluetooth: Fix local name setting for LE-only controllers Johan Hedberg
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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 5436e02..d828e49 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 ec24d9a..4debf4a 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] 32+ messages in thread

* [PATCH v4 12/26] Bluetooth: Fix local name setting for LE-only controllers
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (10 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 11/26] Bluetooth: Handle AD updating through an async request Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 13/26] Bluetooth: Fix setting local name to the existing value Johan Hedberg
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 13/26] Bluetooth: Fix setting local name to the existing value
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (11 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 12/26] Bluetooth: Fix local name setting for LE-only controllers Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 14/26] Bluetooth: Use an async request for mgmt_set_connectable Johan Hedberg
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 14/26] Bluetooth: Use an async request for mgmt_set_connectable
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (12 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 13/26] Bluetooth: Fix setting local name to the existing value Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 15/26] Bluetooth: Fix fast connectable response sending Johan Hedberg
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 15/26] Bluetooth: Fix fast connectable response sending
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (13 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 14/26] Bluetooth: Use an async request for mgmt_set_connectable Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 16/26] Bluetooth: Limit fast connectable support to >= 1.2 controllers Johan Hedberg
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 16/26] Bluetooth: Limit fast connectable support to >= 1.2 controllers
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (14 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 15/26] Bluetooth: Fix fast connectable response sending Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 17/26] Bluetooth: Fix error response for simultaneous fast connectable commands Johan Hedberg
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 17/26] Bluetooth: Fix error response for simultaneous fast connectable commands
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (15 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 16/26] Bluetooth: Limit fast connectable support to >= 1.2 controllers Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 18/26] Bluetooth: Add proper flag for fast connectable mode Johan Hedberg
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 18/26] Bluetooth: Add proper flag for fast connectable mode
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (16 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 17/26] Bluetooth: Fix error response for simultaneous fast connectable commands Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 19/26] Bluetooth: Refactor fast connectable HCI commands Johan Hedberg
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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 a09d5e9..3570367 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] 32+ messages in thread

* [PATCH v4 19/26] Bluetooth: Refactor fast connectable HCI commands
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (17 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 18/26] Bluetooth: Add proper flag for fast connectable mode Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 20/26] Bluetooth: Disable fast connectable when disabling connectable Johan Hedberg
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 20/26] Bluetooth: Disable fast connectable when disabling connectable
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (18 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 19/26] Bluetooth: Refactor fast connectable HCI commands Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 21/26] Bluetooth: Add reading of page scan parameters Johan Hedberg
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 21/26] Bluetooth: Add reading of page scan parameters
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (19 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 20/26] Bluetooth: Disable fast connectable when disabling connectable Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 22/26] Bluetooth: Update page scan parameters after successful write commands Johan Hedberg
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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 3570367..08373f3 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 d828e49..7aeff36 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 4debf4a..4a57913 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] 32+ messages in thread

* [PATCH v4 22/26] Bluetooth: Update page scan parameters after successful write commands
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (20 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 21/26] Bluetooth: Add reading of page scan parameters Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 23/26] Bluetooth: Fix updating page scan parameters when not necessary Johan Hedberg
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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 4a57913..7cbe35f 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] 32+ messages in thread

* [PATCH v4 23/26] Bluetooth: Fix updating page scan parameters when not necessary
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (21 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 22/26] Bluetooth: Update page scan parameters after successful write commands Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 24/26] Bluetooth: Fix fast connectable state when enabling page scan Johan Hedberg
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 24/26] Bluetooth: Fix fast connectable state when enabling page scan
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (22 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 23/26] Bluetooth: Fix updating page scan parameters when not necessary Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 25/26] Bluetooth: Simplify address parameters of user_pairing_resp() Johan Hedberg
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 25/26] Bluetooth: Simplify address parameters of user_pairing_resp()
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (23 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 24/26] Bluetooth: Fix fast connectable state when enabling page scan Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-13 18:12 ` [PATCH v4 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters Johan Hedberg
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* [PATCH v4 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (24 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 25/26] Bluetooth: Simplify address parameters of user_pairing_resp() Johan Hedberg
@ 2013-03-13 18:12 ` Johan Hedberg
  2013-03-15 20:29 ` [PATCH v4 00/26] Bluetooth: Management interface fixes Marcel Holtmann
  2013-03-15 23:09 ` Scott James Remnant
  27 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-13 18:12 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>
---
 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] 32+ messages in thread

* Re: [PATCH v4 07/26] Bluetooth: Add a define for the HCI persistent flags mask
  2013-03-13 18:11 ` [PATCH v4 07/26] Bluetooth: Add a define for the HCI persistent flags mask Johan Hedberg
@ 2013-03-15 20:23   ` Marcel Holtmann
  2013-03-15 21:34     ` Johan Hedberg
  0 siblings, 1 reply; 32+ messages in thread
From: Marcel Holtmann @ 2013-03-15 20:23 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> 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>
> ---
> 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..a09d5e9 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))
> +

didn't we agree and getting this fixed and moving the ~ to the actual call.

> /* 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..ec24d9a 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;

So this should be &= ~HCI_PERSISTENT_MASK

Regards

Marcel


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

* Re: [PATCH v4 00/26] Bluetooth: Management interface fixes
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (25 preceding siblings ...)
  2013-03-13 18:12 ` [PATCH v4 26/26] Bluetooth: Fix PIN/Confirm/Passkey response parameters Johan Hedberg
@ 2013-03-15 20:29 ` Marcel Holtmann
  2013-03-15 23:09 ` Scott James Remnant
  27 siblings, 0 replies; 32+ messages in thread
From: Marcel Holtmann @ 2013-03-15 20:29 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

Hi Johan,

> I'm sending all 26 patches I had pending in my local tree, as requested
> by Marcel. The first six in this set are identical to my patch set
> titled "[PATCH v3 0/6] Bluetooth: HCI command synchronisation fixes".
> 
> 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(-)

besides my one comment about the mask clearing, I did not see anything obvious. So this patch set is fine with me.

However as we discussed there are cleanups to be done in some areas after this gets merged.

Regards

Marcel


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

* Re: [PATCH v4 07/26] Bluetooth: Add a define for the HCI persistent flags mask
  2013-03-15 20:23   ` Marcel Holtmann
@ 2013-03-15 21:34     ` Johan Hedberg
  0 siblings, 0 replies; 32+ messages in thread
From: Johan Hedberg @ 2013-03-15 21:34 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth

Hi Marcel,

On Fri, Mar 15, 2013, Marcel Holtmann wrote:
> > +/* 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))
> > +
> 
> didn't we agree and getting this fixed and moving the ~ to the actual call.

Yes we did. I just forgot about it, sorry. v5 of this patch coming in a
minute.

Johan

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

* Re: [PATCH v4 00/26] Bluetooth: Management interface fixes
  2013-03-13 18:11 [PATCH v4 00/26] Bluetooth: Management interface fixes Johan Hedberg
                   ` (26 preceding siblings ...)
  2013-03-15 20:29 ` [PATCH v4 00/26] Bluetooth: Management interface fixes Marcel Holtmann
@ 2013-03-15 23:09 ` Scott James Remnant
  2013-03-15 23:14   ` Marcel Holtmann
  27 siblings, 1 reply; 32+ messages in thread
From: Scott James Remnant @ 2013-03-15 23:09 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth

On Wed, Mar 13, 2013 at 11:11 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:

> I'm sending all 26 patches I had pending in my local tree, as requested
> by Marcel. The first six in this set are identical to my patch set
> titled "[PATCH v3 0/6] Bluetooth: HCI command synchronisation fixes".
>

Which version of BlueZ are these intended to be used with?

Thanks,

Scott
-- 
Scott James Remnant | Chrome OS Systems | keybuk@google.com | Google

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

* Re: [PATCH v4 00/26] Bluetooth: Management interface fixes
  2013-03-15 23:09 ` Scott James Remnant
@ 2013-03-15 23:14   ` Marcel Holtmann
  0 siblings, 0 replies; 32+ messages in thread
From: Marcel Holtmann @ 2013-03-15 23:14 UTC (permalink / raw)
  To: Scott James Remnant; +Cc: Johan Hedberg, linux-bluetooth

Hi Scott,

>> I'm sending all 26 patches I had pending in my local tree, as requested
>> by Marcel. The first six in this set are identical to my patch set
>> titled "[PATCH v3 0/6] Bluetooth: HCI command synchronisation fixes".
>> 
> 
> Which version of BlueZ are these intended to be used with?

these are for bluetooth-next. They are ensuring that we do not reply to userspace too early. Internal usage for controller specific setup and AMP are possible as well.

Main driving factor is of course the LE extensions we are planning. The capability to execute command sequences is really important there. 

Regards

Marcel


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

end of thread, other threads:[~2013-03-15 23:14 UTC | newest]

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

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.