linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands
@ 2012-03-01 20:33 johan.hedberg
  2012-03-01 20:33 ` [PATCH 2/5] Bluetooth: mgmt: Initialize HCI_MGMT flag for any command johan.hedberg
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: johan.hedberg @ 2012-03-01 20:33 UTC (permalink / raw)
  To: linux-bluetooth

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

Almost all mgmt commands need to lookup a struct hci_dev based on the
index received within the mgmt headers. It makese therefore sense to
look this up in a single place and then just pass the hdev pointer to
each command handler function.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/mgmt.c |  764 ++++++++++++++++++--------------------------------
 1 files changed, 274 insertions(+), 490 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 3fcccad..cc9fb64 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -624,17 +624,11 @@ static void mgmt_init_hdev(struct hci_dev *hdev)
 	}
 }
 
-static int read_controller_info(struct sock *sk, u16 index)
+static int read_controller_info(struct sock *sk, struct hci_dev *hdev)
 {
 	struct mgmt_rp_read_info rp;
-	struct hci_dev *hdev;
-
-	BT_DBG("sock %p hci%u", sk, index);
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_READ_INFO,
-						MGMT_STATUS_INVALID_PARAMS);
+	BT_DBG("sock %p %s", sk, hdev->name);
 
 	hci_dev_lock(hdev);
 
@@ -658,9 +652,9 @@ static int read_controller_info(struct sock *sk, u16 index)
 	memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
 
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 
-	return cmd_complete(sk, index, MGMT_OP_READ_INFO, 0, &rp, sizeof(rp));
+	return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
+								sizeof(rp));
 }
 
 static void mgmt_pending_free(struct pending_cmd *cmd)
@@ -744,22 +738,17 @@ static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
 							sizeof(settings));
 }
 
-static int set_powered(struct sock *sk, u16 index, void *data, u16 len)
+static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
 	struct mgmt_mode *cp = data;
-	struct hci_dev *hdev;
 	struct pending_cmd *cmd;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_POWERED,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_POWERED,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
@@ -780,7 +769,7 @@ static int set_powered(struct sock *sk, u16 index, void *data, u16 len)
 	}
 
 	if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_POWERED,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
 							MGMT_STATUS_BUSY);
 		goto failed;
 	}
@@ -800,7 +789,6 @@ static int set_powered(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 	return err;
 }
 
@@ -843,48 +831,43 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip)
 	return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
 }
 
-static int set_discoverable(struct sock *sk, u16 index, void *data, u16 len)
+static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
 	struct mgmt_cp_set_discoverable *cp = data;
-	struct hci_dev *hdev;
 	struct pending_cmd *cmd;
 	u16 timeout;
 	u8 scan;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	timeout = get_unaligned_le16(&cp->timeout);
 	if (!cp->val && timeout > 0)
-		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev) && timeout > 0) {
-		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
 						MGMT_STATUS_NOT_POWERED);
 		goto failed;
 	}
 
 	if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
 			mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
 							MGMT_STATUS_BUSY);
 		goto failed;
 	}
 
 	if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
 							MGMT_STATUS_REJECTED);
 		goto failed;
 	}
@@ -945,28 +928,21 @@ static int set_discoverable(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int set_connectable(struct sock *sk, u16 index, void *data, u16 len)
+static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
 	struct mgmt_mode *cp = data;
-	struct hci_dev *hdev;
 	struct pending_cmd *cmd;
 	u8 scan;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
@@ -996,7 +972,7 @@ static int set_connectable(struct sock *sk, u16 index, void *data, u16 len)
 
 	if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
 			mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
 							MGMT_STATUS_BUSY);
 		goto failed;
 	}
@@ -1028,26 +1004,19 @@ static int set_connectable(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int set_pairable(struct sock *sk, u16 index, void *data, u16 len)
+static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
 	struct mgmt_mode *cp = data;
-	struct hci_dev *hdev;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
@@ -1065,28 +1034,21 @@ static int set_pairable(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int set_link_security(struct sock *sk, u16 index, void *data, u16 len)
+static int set_link_security(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
 	struct mgmt_mode *cp = data;
 	struct pending_cmd *cmd;
-	struct hci_dev *hdev;
 	u8 val;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_LINK_SECURITY,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_LINK_SECURITY,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
@@ -1111,7 +1073,7 @@ static int set_link_security(struct sock *sk, u16 index, void *data, u16 len)
 	}
 
 	if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_LINK_SECURITY,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
 							MGMT_STATUS_BUSY);
 		goto failed;
 	}
@@ -1137,34 +1099,26 @@ static int set_link_security(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int set_ssp(struct sock *sk, u16 index, void *data, u16 len)
+static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 {
 	struct mgmt_mode *cp = data;
 	struct pending_cmd *cmd;
-	struct hci_dev *hdev;
 	u8 val;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_SSP,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_SSP,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_SSP,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
 						MGMT_STATUS_NOT_SUPPORTED);
 		goto failed;
 	}
@@ -1190,7 +1144,8 @@ static int set_ssp(struct sock *sk, u16 index, void *data, u16 len)
 	}
 
 	if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_SSP, MGMT_STATUS_BUSY);
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
+							MGMT_STATUS_BUSY);
 		goto failed;
 	}
 
@@ -1213,70 +1168,49 @@ static int set_ssp(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int set_hs(struct sock *sk, u16 index, void *data, u16 len)
+static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 {
 	struct mgmt_mode *cp = data;
-	struct hci_dev *hdev;
-	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_HS,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_HS,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	if (!enable_hs) {
-		err = cmd_status(sk, index, MGMT_OP_SET_HS,
-					MGMT_STATUS_NOT_SUPPORTED);
-		goto failed;
-	}
+	if (!enable_hs)
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
+						MGMT_STATUS_NOT_SUPPORTED);
 
 	if (cp->val)
 		set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
 	else
 		clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
 
-	err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
-
-failed:
-	hci_dev_put(hdev);
-	return err;
+	return send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
 }
 
-static int set_le(struct sock *sk, u16 index, void *data, u16 len)
+static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 {
 	struct mgmt_mode *cp = data;
 	struct hci_cp_write_le_host_supported hci_cp;
 	struct pending_cmd *cmd;
-	struct hci_dev *hdev;
 	int err;
 	u8 val, enabled;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_LE,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_LE,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!enable_le || !(hdev->features[4] & LMP_LE)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_LE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
 						MGMT_STATUS_NOT_SUPPORTED);
 		goto unlock;
 	}
@@ -1303,7 +1237,8 @@ static int set_le(struct sock *sk, u16 index, void *data, u16 len)
 	}
 
 	if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_LE, MGMT_STATUS_BUSY);
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
+							MGMT_STATUS_BUSY);
 		goto unlock;
 	}
 
@@ -1329,33 +1264,26 @@ static int set_le(struct sock *sk, u16 index, void *data, u16 len)
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 	return err;
 }
 
-static int add_uuid(struct sock *sk, u16 index, void *data, u16 len)
+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_dev *hdev;
 	struct bt_uuid *uuid;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_ADD_UUID,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_ADD_UUID,
+		return cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
-		err = cmd_status(sk, index, MGMT_OP_ADD_UUID,
+		err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
 							MGMT_STATUS_BUSY);
 		goto failed;
 	}
@@ -1380,7 +1308,7 @@ static int add_uuid(struct sock *sk, u16 index, void *data, u16 len)
 		goto failed;
 
 	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
-		err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, 0,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
 							hdev->dev_class, 3);
 		goto failed;
 	}
@@ -1393,8 +1321,6 @@ static int add_uuid(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
@@ -1412,30 +1338,25 @@ static bool enable_service_cache(struct hci_dev *hdev)
 	return false;
 }
 
-static int remove_uuid(struct sock *sk, u16 index, void *data, u16 len)
+static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
 	struct mgmt_cp_remove_uuid *cp = data;
 	struct pending_cmd *cmd;
 	struct list_head *p, *n;
-	struct hci_dev *hdev;
 	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 	int err, found;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
+		return cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
-		err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
+		err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
 							MGMT_STATUS_BUSY);
 		goto unlock;
 	}
@@ -1444,8 +1365,8 @@ static int remove_uuid(struct sock *sk, u16 index, void *data, u16 len)
 		err = hci_uuids_clear(hdev);
 
 		if (enable_service_cache(hdev)) {
-			err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, 0,
-							hdev->dev_class, 3);
+			err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
+							0, hdev->dev_class, 3);
 			goto unlock;
 		}
 
@@ -1465,7 +1386,7 @@ static int remove_uuid(struct sock *sk, u16 index, void *data, u16 len)
 	}
 
 	if (found == 0) {
-		err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
+		err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
 						MGMT_STATUS_INVALID_PARAMS);
 		goto unlock;
 	}
@@ -1480,7 +1401,7 @@ update_class:
 		goto unlock;
 
 	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
-		err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, 0,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
 							hdev->dev_class, 3);
 		goto unlock;
 	}
@@ -1493,33 +1414,26 @@ update_class:
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int set_dev_class(struct sock *sk, u16 index, void *data, u16 len)
+static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_set_dev_class *cp = data;
 	struct pending_cmd *cmd;
 	int err;
 
-	BT_DBG("request for hci%u", index);
+	BT_DBG("request for %s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
-		err = cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
 							MGMT_STATUS_BUSY);
 		goto unlock;
 	}
@@ -1528,7 +1442,7 @@ static int set_dev_class(struct sock *sk, u16 index, void *data, u16 len)
 	hdev->minor_class = cp->minor;
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, 0,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
 							hdev->dev_class, 3);
 		goto unlock;
 	}
@@ -1545,7 +1459,7 @@ static int set_dev_class(struct sock *sk, u16 index, void *data, u16 len)
 		goto unlock;
 
 	if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
-		err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, 0,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
 							hdev->dev_class, 3);
 		goto unlock;
 	}
@@ -1558,20 +1472,18 @@ static int set_dev_class(struct sock *sk, u16 index, void *data, u16 len)
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int load_link_keys(struct sock *sk, u16 index, void *data, u16 len)
+static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_load_link_keys *cp = data;
 	u16 key_count, expected_len;
 	int i;
 
 	if (len < sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
+		return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	key_count = get_unaligned_le16(&cp->key_count);
@@ -1581,16 +1493,11 @@ static int load_link_keys(struct sock *sk, u16 index, void *data, u16 len)
 	if (expected_len != len) {
 		BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
 							len, expected_len);
-		return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
+		return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
 						MGMT_STATUS_INVALID_PARAMS);
 	}
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
+	BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
 								key_count);
 
 	hci_dev_lock(hdev);
@@ -1611,10 +1518,9 @@ static int load_link_keys(struct sock *sk, u16 index, void *data, u16 len)
 						key->type, key->pin_len);
 	}
 
-	cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
+	cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
 
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 
 	return 0;
 }
@@ -1631,9 +1537,9 @@ static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
 								skip_sk);
 }
 
-static int unpair_device(struct sock *sk, u16 index, void *data, u16 len)
+static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_unpair_device *cp = data;
 	struct mgmt_rp_unpair_device rp;
 	struct hci_cp_disconnect dc;
@@ -1642,12 +1548,7 @@ static int unpair_device(struct sock *sk, u16 index, void *data, u16 len)
 	int err;
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_UNPAIR_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_UNPAIR_DEVICE,
+		return cmd_status(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
@@ -1657,7 +1558,7 @@ static int unpair_device(struct sock *sk, u16 index, void *data, u16 len)
 	rp.addr.type = cp->addr.type;
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_complete(sk, index, MGMT_OP_UNPAIR_DEVICE,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
 						MGMT_STATUS_NOT_POWERED,
 						&rp, sizeof(rp));
 		goto unlock;
@@ -1669,7 +1570,7 @@ static int unpair_device(struct sock *sk, u16 index, void *data, u16 len)
 		err = hci_remove_ltk(hdev, &cp->addr.bdaddr);
 
 	if (err < 0) {
-		err = cmd_complete(sk, index, MGMT_OP_UNPAIR_DEVICE,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
 						MGMT_STATUS_NOT_PAIRED,
 						&rp, sizeof(rp));
 		goto unlock;
@@ -1687,7 +1588,7 @@ static int unpair_device(struct sock *sk, u16 index, void *data, u16 len)
 	}
 
 	if (!conn) {
-		err = cmd_complete(sk, index, MGMT_OP_UNPAIR_DEVICE, 0,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
 							&rp, sizeof(rp));
 		device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
 		goto unlock;
@@ -1708,14 +1609,12 @@ static int unpair_device(struct sock *sk, u16 index, void *data, u16 len)
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int disconnect(struct sock *sk, u16 index, void *data, u16 len)
+static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_disconnect *cp = data;
 	struct hci_cp_disconnect dc;
 	struct pending_cmd *cmd;
@@ -1725,24 +1624,19 @@ static int disconnect(struct sock *sk, u16 index, void *data, u16 len)
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_DISCONNECT,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_DISCONNECT,
+		return cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
-		err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
+		err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
 						MGMT_STATUS_NOT_POWERED);
 		goto failed;
 	}
 
 	if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
+		err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
 							MGMT_STATUS_BUSY);
 		goto failed;
 	}
@@ -1753,7 +1647,7 @@ static int disconnect(struct sock *sk, u16 index, void *data, u16 len)
 		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
 
 	if (!conn) {
-		err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
+		err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
 						MGMT_STATUS_NOT_CONNECTED);
 		goto failed;
 	}
@@ -1773,8 +1667,6 @@ static int disconnect(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
@@ -1797,10 +1689,9 @@ static u8 link_to_mgmt(u8 link_type, u8 addr_type)
 	}
 }
 
-static int get_connections(struct sock *sk, u16 index)
+static int get_connections(struct sock *sk, struct hci_dev *hdev)
 {
 	struct mgmt_rp_get_connections *rp;
-	struct hci_dev *hdev;
 	struct hci_conn *c;
 	size_t rp_len;
 	int err;
@@ -1808,15 +1699,10 @@ static int get_connections(struct sock *sk, u16 index)
 
 	BT_DBG("");
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS,
+		err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
 						MGMT_STATUS_NOT_POWERED);
 		goto unlock;
 	}
@@ -1850,18 +1736,18 @@ static int get_connections(struct sock *sk, u16 index)
 	/* Recalculate length in case of filtered SCO connections, etc */
 	rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
 
-	err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, 0, rp, rp_len);
+	err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
+								rp_len);
 
 	kfree(rp);
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 	return err;
 }
 
-static int send_pin_code_neg_reply(struct sock *sk, u16 index,
-		struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
+static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
+					struct mgmt_cp_pin_code_neg_reply *cp)
 {
 	struct pending_cmd *cmd;
 	int err;
@@ -1879,9 +1765,9 @@ static int send_pin_code_neg_reply(struct sock *sk, u16 index,
 	return err;
 }
 
-static int pin_code_reply(struct sock *sk, u16 index, void *data, u16 len)
+static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct hci_conn *conn;
 	struct mgmt_cp_pin_code_reply *cp = data;
 	struct hci_cp_pin_code_reply reply;
@@ -1891,25 +1777,20 @@ static int pin_code_reply(struct sock *sk, u16 index, void *data, u16 len)
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
+		return cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
+		err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
 						MGMT_STATUS_NOT_POWERED);
 		goto failed;
 	}
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
 	if (!conn) {
-		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
+		err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
 						MGMT_STATUS_NOT_CONNECTED);
 		goto failed;
 	}
@@ -1921,9 +1802,9 @@ static int pin_code_reply(struct sock *sk, u16 index, void *data, u16 len)
 
 		BT_ERR("PIN code is not 16 bytes long");
 
-		err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
+		err = send_pin_code_neg_reply(sk, hdev, &ncp);
 		if (err >= 0)
-			err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
+			err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
 						MGMT_STATUS_INVALID_PARAMS);
 
 		goto failed;
@@ -1945,59 +1826,45 @@ static int pin_code_reply(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int pin_code_neg_reply(struct sock *sk, u16 index, void *data, u16 len)
+static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_pin_code_neg_reply *cp = data;
 	int err;
 
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+		return cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+		err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
 						MGMT_STATUS_NOT_POWERED);
 		goto failed;
 	}
 
-	err = send_pin_code_neg_reply(sk, index, hdev, cp);
+	err = send_pin_code_neg_reply(sk, hdev, cp);
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int set_io_capability(struct sock *sk, u16 index, void *data, u16 len)
+static int set_io_capability(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_set_io_capability *cp = data;
 
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
@@ -2008,9 +1875,9 @@ static int set_io_capability(struct sock *sk, u16 index, void *data, u16 len)
 							hdev->io_capability);
 
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 
-	return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, 0, NULL, 0);
+	return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
+								NULL, 0);
 }
 
 static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
@@ -2065,9 +1932,9 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
 		pairing_complete(cmd, mgmt_status(status));
 }
 
-static int pair_device(struct sock *sk, u16 index, void *data, u16 len)
+static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_pair_device *cp = data;
 	struct mgmt_rp_pair_device rp;
 	struct pending_cmd *cmd;
@@ -2078,18 +1945,13 @@ static int pair_device(struct sock *sk, u16 index, void *data, u16 len)
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
+		return cmd_status(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
 						MGMT_STATUS_NOT_POWERED);
 		goto unlock;
 	}
@@ -2112,7 +1974,7 @@ static int pair_device(struct sock *sk, u16 index, void *data, u16 len)
 	rp.addr.type = cp->addr.type;
 
 	if (IS_ERR(conn)) {
-		err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
 						MGMT_STATUS_CONNECT_FAILED,
 						&rp, sizeof(rp));
 		goto unlock;
@@ -2120,7 +1982,7 @@ static int pair_device(struct sock *sk, u16 index, void *data, u16 len)
 
 	if (conn->connect_cfm_cb) {
 		hci_conn_put(conn);
-		err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
 					MGMT_STATUS_BUSY, &rp, sizeof(rp));
 		goto unlock;
 	}
@@ -2149,16 +2011,13 @@ static int pair_device(struct sock *sk, u16 index, void *data, u16 len)
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int cancel_pair_device(struct sock *sk, u16 index,
+static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev,
 						unsigned char *data, u16 len)
 {
 	struct mgmt_addr_info *addr = (void *) data;
-	struct hci_dev *hdev;
 	struct pending_cmd *cmd;
 	struct hci_conn *conn;
 	int err;
@@ -2166,25 +2025,20 @@ static int cancel_pair_device(struct sock *sk, u16 index,
 	BT_DBG("");
 
 	if (len != sizeof(*addr))
-		return cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+		return cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
 						MGMT_STATUS_NOT_POWERED);
 		goto unlock;
 	}
 
 	cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
 	if (!cmd) {
-		err = cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
 						MGMT_STATUS_INVALID_PARAMS);
 		goto unlock;
 	}
@@ -2192,40 +2046,33 @@ static int cancel_pair_device(struct sock *sk, u16 index,
 	conn = cmd->user_data;
 
 	if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
-		err = cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+		err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
 						MGMT_STATUS_INVALID_PARAMS);
 		goto unlock;
 	}
 
 	pairing_complete(cmd, MGMT_STATUS_CANCELLED);
 
-	err = cmd_complete(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE, 0, addr,
-								sizeof(*addr));
+	err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
+							addr, sizeof(*addr));
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
-					u8 type, u16 mgmt_op, u16 hci_op,
-					__le32 passkey)
+static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
+				bdaddr_t *bdaddr, u8 type, u16 mgmt_op,
+				u16 hci_op, __le32 passkey)
 {
 	struct pending_cmd *cmd;
-	struct hci_dev *hdev;
 	struct hci_conn *conn;
 	int err;
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, mgmt_op,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED);
+		err = cmd_status(sk, hdev->id, mgmt_op,
+						MGMT_STATUS_NOT_POWERED);
 		goto done;
 	}
 
@@ -2235,7 +2082,7 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
 		conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
 
 	if (!conn) {
-		err = cmd_status(sk, index, mgmt_op,
+		err = cmd_status(sk, hdev->id, mgmt_op,
 						MGMT_STATUS_NOT_CONNECTED);
 		goto done;
 	}
@@ -2245,10 +2092,10 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
 		err = smp_user_confirm_reply(conn, mgmt_op, passkey);
 
 		if (!err)
-			err = cmd_status(sk, index, mgmt_op,
+			err = cmd_status(sk, hdev->id, mgmt_op,
 							MGMT_STATUS_SUCCESS);
 		else
-			err = cmd_status(sk, index, mgmt_op,
+			err = cmd_status(sk, hdev->id, mgmt_op,
 							MGMT_STATUS_FAILED);
 
 		goto done;
@@ -2275,92 +2122,86 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
 
 done:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len)
+static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
 	struct mgmt_cp_user_confirm_reply *cp = data;
 
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY,
+		return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	return user_pairing_resp(sk, index, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
 						MGMT_OP_USER_CONFIRM_REPLY,
 						HCI_OP_USER_CONFIRM_REPLY, 0);
 }
 
-static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,
-									u16 len)
+static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
 	struct mgmt_cp_user_confirm_neg_reply *cp = data;
 
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY,
+		return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_NEG_REPLY,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	return user_pairing_resp(sk, index, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
 					MGMT_OP_USER_CONFIRM_NEG_REPLY,
 					HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
 }
 
-static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len)
+static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
 	struct mgmt_cp_user_passkey_reply *cp = data;
 
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
+		return cmd_status(sk, hdev->id, MGMT_OP_USER_PASSKEY_REPLY,
 									EINVAL);
 
-	return user_pairing_resp(sk, index, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
 						MGMT_OP_USER_PASSKEY_REPLY,
 						HCI_OP_USER_PASSKEY_REPLY,
 						cp->passkey);
 }
 
-static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data,
-									u16 len)
+static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
 	struct mgmt_cp_user_passkey_neg_reply *cp = data;
 
 	BT_DBG("");
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
-									EINVAL);
+		return cmd_status(sk, hdev->id, MGMT_OP_USER_PASSKEY_NEG_REPLY,
+								EINVAL);
 
-	return user_pairing_resp(sk, index, &cp->addr.bdaddr, cp->addr.type,
+	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
 					MGMT_OP_USER_PASSKEY_NEG_REPLY,
 					HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
 }
 
-static int set_local_name(struct sock *sk, u16 index, void *data,
+static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 								u16 len)
 {
 	struct mgmt_cp_set_local_name *mgmt_cp = data;
 	struct hci_cp_write_local_name hci_cp;
-	struct hci_dev *hdev;
 	struct pending_cmd *cmd;
 	int err;
 
 	BT_DBG("");
 
 	if (len != sizeof(*mgmt_cp))
-		return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
@@ -2396,40 +2237,32 @@ static int set_local_name(struct sock *sk, u16 index, void *data,
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int read_local_oob_data(struct sock *sk, u16 index)
+static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev)
 {
-	struct hci_dev *hdev;
 	struct pending_cmd *cmd;
 	int err;
 
-	BT_DBG("hci%u", index);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
-						MGMT_STATUS_INVALID_PARAMS);
+	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
+		err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
 						MGMT_STATUS_NOT_POWERED);
 		goto unlock;
 	}
 
 	if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
-		err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
+		err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
 						MGMT_STATUS_NOT_SUPPORTED);
 		goto unlock;
 	}
 
 	if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
+		err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
 							MGMT_STATUS_BUSY);
 		goto unlock;
 	}
@@ -2446,35 +2279,26 @@ static int read_local_oob_data(struct sock *sk, u16 index)
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int add_remote_oob_data(struct sock *sk, u16 index, void *data,
-								u16 len)
+static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_add_remote_oob_data *cp = data;
 	u8 status;
 	int err;
 
-	BT_DBG("hci%u ", index);
+	BT_DBG("%s ", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
+		return cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
-						MGMT_STATUS_INVALID_PARAMS,
-						&cp->addr, sizeof(cp->addr));
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
 						MGMT_STATUS_NOT_POWERED,
 						&cp->addr, sizeof(cp->addr));
 		goto unlock;
@@ -2487,42 +2311,34 @@ static int add_remote_oob_data(struct sock *sk, u16 index, void *data,
 	else
 		status = 0;
 
-	err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, status,
+	err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, status,
 						&cp->addr, sizeof(cp->addr));
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int remove_remote_oob_data(struct sock *sk, u16 index,
+static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
 						void *data, u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_remove_remote_oob_data *cp = data;
 	u8 status;
 	int err;
 
-	BT_DBG("hci%u ", index);
+	BT_DBG("%s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
+		return cmd_status(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
-						MGMT_STATUS_INVALID_PARAMS,
-						&cp->addr, sizeof(cp->addr));
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
-						MGMT_STATUS_NOT_POWERED,
-						&cp->addr, sizeof(cp->addr));
+		err = cmd_complete(sk, hdev->id,
+					MGMT_OP_REMOVE_REMOTE_OOB_DATA,
+					MGMT_STATUS_NOT_POWERED,
+					&cp->addr, sizeof(cp->addr));
 		goto unlock;
 	}
 
@@ -2532,13 +2348,11 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
 	else
 		status = 0;
 
-	err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, status,
-						&cp->addr, sizeof(cp->addr));
+	err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
+					status, &cp->addr, sizeof(cp->addr));
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
@@ -2559,36 +2373,30 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev)
 	return err;
 }
 
-static int start_discovery(struct sock *sk, u16 index,
+static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 						void *data, u16 len)
 {
 	struct mgmt_cp_start_discovery *cp = data;
 	struct pending_cmd *cmd;
-	struct hci_dev *hdev;
 	int err;
 
-	BT_DBG("hci%u", index);
+	BT_DBG("%s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
+		return cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
+		err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
 						MGMT_STATUS_NOT_POWERED);
 		goto failed;
 	}
 
 	if (hdev->discovery.state != DISCOVERY_STOPPED) {
-		err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
-						MGMT_STATUS_BUSY);
+		err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+							MGMT_STATUS_BUSY);
 		goto failed;
 	}
 
@@ -2635,42 +2443,35 @@ static int start_discovery(struct sock *sk, u16 index,
 
 failed:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int stop_discovery(struct sock *sk, u16 index, void *data, u16 len)
+static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
 	struct mgmt_cp_stop_discovery *mgmt_cp = data;
-	struct hci_dev *hdev;
 	struct pending_cmd *cmd;
 	struct hci_cp_remote_name_req_cancel cp;
 	struct inquiry_entry *e;
 	int err;
 
-	BT_DBG("hci%u", index);
+	BT_DBG("%s", hdev->name);
 
 	if (len != sizeof(*mgmt_cp))
-		return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
-						MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
+		return cmd_status(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
 						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hci_discovery_active(hdev)) {
-		err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
 					MGMT_STATUS_REJECTED,
 					&mgmt_cp->type, sizeof(mgmt_cp->type));
 		goto unlock;
 	}
 
 	if (hdev->discovery.type != mgmt_cp->type) {
-		err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
 					MGMT_STATUS_INVALID_PARAMS,
 					&mgmt_cp->type, sizeof(mgmt_cp->type));
 		goto unlock;
@@ -2694,7 +2495,7 @@ static int stop_discovery(struct sock *sk, u16 index, void *data, u16 len)
 	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_PENDING);
 	if (!e) {
 		mgmt_pending_remove(cmd);
-		err = cmd_complete(sk, index, MGMT_OP_STOP_DISCOVERY, 0,
+		err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
 					&mgmt_cp->type, sizeof(mgmt_cp->type));
 		hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
 		goto unlock;
@@ -2710,41 +2511,34 @@ static int stop_discovery(struct sock *sk, u16 index, void *data, u16 len)
 
 unlock:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int confirm_name(struct sock *sk, u16 index, void *data, u16 len)
+static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
 	struct mgmt_cp_confirm_name *cp = data;
 	struct inquiry_entry *e;
-	struct hci_dev *hdev;
 	int err;
 
-	BT_DBG("hci%u", index);
+	BT_DBG("%s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_CONFIRM_NAME,
-				MGMT_STATUS_INVALID_PARAMS);
-
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_CONFIRM_NAME,
-				MGMT_STATUS_INVALID_PARAMS);
+		return cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
+						MGMT_STATUS_INVALID_PARAMS);
 
 	hci_dev_lock(hdev);
 
 	if (!hci_discovery_active(hdev)) {
-		err = cmd_status(sk, index, MGMT_OP_CONFIRM_NAME,
+		err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
 							MGMT_STATUS_FAILED);
 		goto failed;
 	}
 
 	e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
 	if (!e) {
-		err = cmd_status(sk, index, MGMT_OP_CONFIRM_NAME,
-				MGMT_STATUS_INVALID_PARAMS);
+		err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
+						MGMT_STATUS_INVALID_PARAMS);
 		goto failed;
 	}
 
@@ -2760,29 +2554,22 @@ static int confirm_name(struct sock *sk, u16 index, void *data, u16 len)
 
 failed:
 	hci_dev_unlock(hdev);
-
 	return err;
 }
 
-static int block_device(struct sock *sk, u16 index, void *data, u16 len)
+static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_block_device *cp = data;
 	u8 status;
 	int err;
 
-	BT_DBG("hci%u", index);
+	BT_DBG("%s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
+		return cmd_status(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS,
-						&cp->addr, sizeof(cp->addr));
-
 	hci_dev_lock(hdev);
 
 	err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
@@ -2791,34 +2578,27 @@ static int block_device(struct sock *sk, u16 index, void *data, u16 len)
 	else
 		status = 0;
 
-	err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, status,
+	err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
 						&cp->addr, sizeof(cp->addr));
 
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 
 	return err;
 }
 
-static int unblock_device(struct sock *sk, u16 index, void *data, u16 len)
+static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
+								u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_unblock_device *cp = data;
 	u8 status;
 	int err;
 
-	BT_DBG("hci%u", index);
+	BT_DBG("%s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+		return cmd_status(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS,
-						&cp->addr, sizeof(cp->addr));
-
 	hci_dev_lock(hdev);
 
 	err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
@@ -2827,41 +2607,35 @@ static int unblock_device(struct sock *sk, u16 index, void *data, u16 len)
 	else
 		status = 0;
 
-	err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, status,
+	err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
 						&cp->addr, sizeof(cp->addr));
 
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 
 	return err;
 }
 
-static int set_fast_connectable(struct sock *sk, u16 index,
-					void *data, u16 len)
+static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
+							void *data, u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_mode *cp = data;
 	struct hci_cp_write_page_scan_activity acp;
 	u8 type;
 	int err;
 
-	BT_DBG("hci%u", index);
+	BT_DBG("%s", hdev->name);
 
 	if (len != sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 						MGMT_STATUS_INVALID_PARAMS);
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
-						MGMT_STATUS_INVALID_PARAMS);
 	if (!hdev_is_powered(hdev))
-		return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 						MGMT_STATUS_NOT_POWERED);
 
 	if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
-		return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
-							MGMT_STATUS_REJECTED);
+		return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+						MGMT_STATUS_REJECTED);
 
 	hci_dev_lock(hdev);
 
@@ -2878,37 +2652,34 @@ static int set_fast_connectable(struct sock *sk, u16 index,
 	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
 						sizeof(acp), &acp);
 	if (err < 0) {
-		err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
-							MGMT_STATUS_FAILED);
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+						MGMT_STATUS_FAILED);
 		goto done;
 	}
 
 	err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
 	if (err < 0) {
-		err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
-							MGMT_STATUS_FAILED);
+		err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
+						MGMT_STATUS_FAILED);
 		goto done;
 	}
 
-	err = cmd_complete(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, 0,
+	err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0,
 								NULL, 0);
 done:
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-
 	return err;
 }
 
-static int load_long_term_keys(struct sock *sk, u16 index,
+static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 					void *cp_data, u16 len)
 {
-	struct hci_dev *hdev;
 	struct mgmt_cp_load_long_term_keys *cp = cp_data;
 	u16 key_count, expected_len;
 	int i;
 
 	if (len < sizeof(*cp))
-		return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS,
+		return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
 								EINVAL);
 
 	key_count = get_unaligned_le16(&cp->key_count);
@@ -2918,16 +2689,11 @@ static int load_long_term_keys(struct sock *sk, u16 index,
 	if (expected_len != len) {
 		BT_ERR("load_keys: expected %u bytes, got %u bytes",
 							len, expected_len);
-		return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS,
+		return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
 								EINVAL);
 	}
 
-	hdev = hci_dev_get(index);
-	if (!hdev)
-		return cmd_status(sk, index, MGMT_OP_LOAD_LONG_TERM_KEYS,
-								ENODEV);
-
-	BT_DBG("hci%u key_count %u", index, key_count);
+	BT_DBG("%s key_count %u", hdev->name, key_count);
 
 	hci_dev_lock(hdev);
 
@@ -2948,7 +2714,6 @@ static int load_long_term_keys(struct sock *sk, u16 index,
 	}
 
 	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
 
 	return 0;
 }
@@ -2959,6 +2724,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 	u8 *cp;
 	struct mgmt_hdr *hdr;
 	u16 opcode, index, len;
+	struct hci_dev *hdev = NULL;
 	int err;
 
 	BT_DBG("got %zu bytes", msglen);
@@ -2985,6 +2751,21 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 		goto done;
 	}
 
+	if (opcode < MGMT_OP_READ_INFO) {
+		if (index != MGMT_INDEX_NONE) {
+			err = cmd_status(sk, index, opcode,
+						MGMT_STATUS_INVALID_PARAMS);
+			goto done;
+		}
+	} else {
+		hdev = hci_dev_get(index);
+		if (!hdev) {
+			err = cmd_status(sk, index, opcode,
+						MGMT_STATUS_INVALID_PARAMS);
+			goto done;
+		}
+	}
+
 	cp = buf + sizeof(*hdr);
 
 	switch (opcode) {
@@ -2998,112 +2779,112 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 		err = read_index_list(sk);
 		break;
 	case MGMT_OP_READ_INFO:
-		err = read_controller_info(sk, index);
+		err = read_controller_info(sk, hdev);
 		break;
 	case MGMT_OP_SET_POWERED:
-		err = set_powered(sk, index, cp, len);
+		err = set_powered(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_DISCOVERABLE:
-		err = set_discoverable(sk, index, cp, len);
+		err = set_discoverable(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_CONNECTABLE:
-		err = set_connectable(sk, index, cp, len);
+		err = set_connectable(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_FAST_CONNECTABLE:
-		err = set_fast_connectable(sk, index, cp, len);
+		err = set_fast_connectable(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_PAIRABLE:
-		err = set_pairable(sk, index, cp, len);
+		err = set_pairable(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_LINK_SECURITY:
-		err = set_link_security(sk, index, cp, len);
+		err = set_link_security(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_SSP:
-		err = set_ssp(sk, index, cp, len);
+		err = set_ssp(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_HS:
-		err = set_hs(sk, index, cp, len);
+		err = set_hs(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_LE:
-		err = set_le(sk, index, cp, len);
+		err = set_le(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_ADD_UUID:
-		err = add_uuid(sk, index, cp, len);
+		err = add_uuid(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_REMOVE_UUID:
-		err = remove_uuid(sk, index, cp, len);
+		err = remove_uuid(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_DEV_CLASS:
-		err = set_dev_class(sk, index, cp, len);
+		err = set_dev_class(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_LOAD_LINK_KEYS:
-		err = load_link_keys(sk, index, cp, len);
+		err = load_link_keys(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_DISCONNECT:
-		err = disconnect(sk, index, cp, len);
+		err = disconnect(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_GET_CONNECTIONS:
-		err = get_connections(sk, index);
+		err = get_connections(sk, hdev);
 		break;
 	case MGMT_OP_PIN_CODE_REPLY:
-		err = pin_code_reply(sk, index, cp, len);
+		err = pin_code_reply(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_PIN_CODE_NEG_REPLY:
-		err = pin_code_neg_reply(sk, index, cp, len);
+		err = pin_code_neg_reply(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_IO_CAPABILITY:
-		err = set_io_capability(sk, index, cp, len);
+		err = set_io_capability(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_PAIR_DEVICE:
-		err = pair_device(sk, index, cp, len);
+		err = pair_device(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_CANCEL_PAIR_DEVICE:
-		err = cancel_pair_device(sk, index, buf + sizeof(*hdr), len);
+		err = cancel_pair_device(sk, hdev, buf + sizeof(*hdr), len);
 		break;
 	case MGMT_OP_UNPAIR_DEVICE:
-		err = unpair_device(sk, index, cp, len);
+		err = unpair_device(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_USER_CONFIRM_REPLY:
-		err = user_confirm_reply(sk, index, cp, len);
+		err = user_confirm_reply(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
-		err = user_confirm_neg_reply(sk, index, cp, len);
+		err = user_confirm_neg_reply(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_USER_PASSKEY_REPLY:
-		err = user_passkey_reply(sk, index, cp, len);
+		err = user_passkey_reply(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
-		err = user_passkey_neg_reply(sk, index, cp, len);
+		err = user_passkey_neg_reply(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_SET_LOCAL_NAME:
-		err = set_local_name(sk, index, cp, len);
+		err = set_local_name(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_READ_LOCAL_OOB_DATA:
-		err = read_local_oob_data(sk, index);
+		err = read_local_oob_data(sk, hdev);
 		break;
 	case MGMT_OP_ADD_REMOTE_OOB_DATA:
-		err = add_remote_oob_data(sk, index, cp, len);
+		err = add_remote_oob_data(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
-		err = remove_remote_oob_data(sk, index, cp, len);
+		err = remove_remote_oob_data(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_START_DISCOVERY:
-		err = start_discovery(sk, index, cp, len);
+		err = start_discovery(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_STOP_DISCOVERY:
-		err = stop_discovery(sk, index, cp, len);
+		err = stop_discovery(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_CONFIRM_NAME:
-		err = confirm_name(sk, index, cp, len);
+		err = confirm_name(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_BLOCK_DEVICE:
-		err = block_device(sk, index, cp, len);
+		err = block_device(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_UNBLOCK_DEVICE:
-		err = unblock_device(sk, index, cp, len);
+		err = unblock_device(sk, hdev, cp, len);
 		break;
 	case MGMT_OP_LOAD_LONG_TERM_KEYS:
-		err = load_long_term_keys(sk, index, cp, len);
+		err = load_long_term_keys(sk, hdev, cp, len);
 		break;
 	default:
 		BT_DBG("Unknown op %u", opcode);
@@ -3118,6 +2899,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 	err = msglen;
 
 done:
+	if (hdev)
+		hci_dev_put(hdev);
+
 	kfree(buf);
 	return err;
 }
-- 
1.7.9.1


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

* [PATCH 2/5] Bluetooth: mgmt: Initialize HCI_MGMT flag for any command
  2012-03-01 20:33 [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands johan.hedberg
@ 2012-03-01 20:33 ` johan.hedberg
  2012-03-01 20:46   ` Marcel Holtmann
  2012-03-01 20:33 ` [PATCH 3/5] Bluetooth: mgmt: Move command handlers into a table johan.hedberg
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: johan.hedberg @ 2012-03-01 20:33 UTC (permalink / raw)
  To: linux-bluetooth

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

The read_controller_info is typically the first command that user space
sends when taking a controller into use. This is also the reason why
this command has been used as the trigger to set the HCI_MGMT flag.
However, when not running the user-space daemon and using command line
tools it is possible that read_controller_info is not the first
controller specific command. This patch moves the HCI_MGMT
initialization to a generic place where it will be set for whatever
happens to be the first mgmt command targetting a specific controller.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/mgmt.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index cc9fb64..cf8c840 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -610,8 +610,11 @@ static void service_cache_off(struct work_struct *work)
 	hci_dev_unlock(hdev);
 }
 
-static void mgmt_init_hdev(struct hci_dev *hdev)
+static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
 {
+	if (!test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags))
+		return;
+
 	if (!test_and_set_bit(HCI_MGMT, &hdev->dev_flags)) {
 		INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
 
@@ -632,9 +635,6 @@ static int read_controller_info(struct sock *sk, struct hci_dev *hdev)
 
 	hci_dev_lock(hdev);
 
-	if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags))
-		mgmt_init_hdev(hdev);
-
 	memset(&rp, 0, sizeof(rp));
 
 	bacpy(&rp.bdaddr, &hdev->bdaddr);
@@ -2764,6 +2764,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 						MGMT_STATUS_INVALID_PARAMS);
 			goto done;
 		}
+
+		mgmt_init_hdev(sk, hdev);
 	}
 
 	cp = buf + sizeof(*hdr);
-- 
1.7.9.1


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

* [PATCH 3/5] Bluetooth: mgmt: Move command handlers into a table
  2012-03-01 20:33 [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands johan.hedberg
  2012-03-01 20:33 ` [PATCH 2/5] Bluetooth: mgmt: Initialize HCI_MGMT flag for any command johan.hedberg
@ 2012-03-01 20:33 ` johan.hedberg
  2012-03-01 20:47   ` Marcel Holtmann
  2012-03-01 20:33 ` [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes johan.hedberg
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: johan.hedberg @ 2012-03-01 20:33 UTC (permalink / raw)
  To: linux-bluetooth

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

By moving the command handlers into a table (the index being equal to
the opcode) the lookup is made a bit more efficient. Having a struct to
describe each handler also paves the way to add more meta-data for each
handler, e.g. the minimum message size for the command and allow
handling of common tasks like this in a centralized place.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/mgmt.c |  219 ++++++++++++++++++--------------------------------
 1 files changed, 79 insertions(+), 140 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index cf8c840..88a342a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -267,7 +267,8 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
 	return err;
 }
 
-static int read_version(struct sock *sk)
+static int read_version(struct sock *sk, struct hci_dev *hdev,
+						void *data, u16 data_len)
 {
 	struct mgmt_rp_read_version rp;
 
@@ -280,7 +281,8 @@ static int read_version(struct sock *sk)
 								sizeof(rp));
 }
 
-static int read_commands(struct sock *sk)
+static int read_commands(struct sock *sk, struct hci_dev *hdev,
+						void *data, u16 data_len)
 {
 	struct mgmt_rp_read_commands *rp;
 	u16 num_commands = ARRAY_SIZE(mgmt_commands);
@@ -313,7 +315,8 @@ static int read_commands(struct sock *sk)
 	return err;
 }
 
-static int read_index_list(struct sock *sk)
+static int read_index_list(struct sock *sk, struct hci_dev *hdev,
+						void *data, u16 data_len)
 {
 	struct mgmt_rp_read_index_list *rp;
 	struct list_head *p;
@@ -627,7 +630,8 @@ static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
 	}
 }
 
-static int read_controller_info(struct sock *sk, struct hci_dev *hdev)
+static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
+						void *data, u16 data_len)
 {
 	struct mgmt_rp_read_info rp;
 
@@ -1689,7 +1693,8 @@ static u8 link_to_mgmt(u8 link_type, u8 addr_type)
 	}
 }
 
-static int get_connections(struct sock *sk, struct hci_dev *hdev)
+static int get_connections(struct sock *sk, struct hci_dev *hdev,
+						void *data, u16 data_len)
 {
 	struct mgmt_rp_get_connections *rp;
 	struct hci_conn *c;
@@ -2015,9 +2020,9 @@ unlock:
 }
 
 static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev,
-						unsigned char *data, u16 len)
+							void *data, u16 len)
 {
-	struct mgmt_addr_info *addr = (void *) data;
+	struct mgmt_addr_info *addr = data;
 	struct pending_cmd *cmd;
 	struct hci_conn *conn;
 	int err;
@@ -2240,7 +2245,8 @@ failed:
 	return err;
 }
 
-static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev)
+static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
+						void *data, u16 data_len)
 {
 	struct pending_cmd *cmd;
 	int err;
@@ -2718,6 +2724,53 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 	return 0;
 }
 
+struct mgmt_handler {
+	int (*func) (struct sock *sk, struct hci_dev *hdev,
+						void *data, u16 data_len);
+} mgmt_handlers[] = {
+	{ NULL }, /* 0x0000 (no command) */
+	{ read_version, },
+	{ read_commands, },
+	{ read_index_list, },
+	{ read_controller_info, },
+	{ set_powered, },
+	{ set_discoverable, },
+	{ set_connectable, },
+	{ set_fast_connectable, },
+	{ set_pairable,	},
+	{ set_link_security, },
+	{ set_ssp, },
+	{ set_hs, },
+	{ set_le, },
+	{ set_dev_class, },
+	{ set_local_name, },
+	{ add_uuid, },
+	{ remove_uuid, },
+	{ load_link_keys, },
+	{ load_long_term_keys, },
+	{ disconnect, },
+	{ get_connections, },
+	{ pin_code_reply, },
+	{ pin_code_neg_reply, },
+	{ set_io_capability, },
+	{ pair_device, },
+	{ cancel_pair_device, },
+	{ unpair_device, },
+	{ user_confirm_reply, },
+	{ user_confirm_neg_reply, },
+	{ user_passkey_reply, },
+	{ user_passkey_neg_reply, },
+	{ read_local_oob_data, },
+	{ add_remote_oob_data, },
+	{ remove_remote_oob_data, },
+	{ start_discovery, },
+	{ stop_discovery, },
+	{ confirm_name, },
+	{ block_device, },
+	{ unblock_device, },
+};
+
+
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 {
 	void *buf;
@@ -2751,150 +2804,36 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 		goto done;
 	}
 
-	if (opcode < MGMT_OP_READ_INFO) {
-		if (index != MGMT_INDEX_NONE) {
-			err = cmd_status(sk, index, opcode,
-						MGMT_STATUS_INVALID_PARAMS);
-			goto done;
-		}
-	} else {
+	if (index != MGMT_INDEX_NONE) {
 		hdev = hci_dev_get(index);
 		if (!hdev) {
 			err = cmd_status(sk, index, opcode,
-						MGMT_STATUS_INVALID_PARAMS);
+					MGMT_STATUS_INVALID_PARAMS);
 			goto done;
 		}
-
-		mgmt_init_hdev(sk, hdev);
 	}
 
-	cp = buf + sizeof(*hdr);
-
-	switch (opcode) {
-	case MGMT_OP_READ_VERSION:
-		err = read_version(sk);
-		break;
-	case MGMT_OP_READ_COMMANDS:
-		err = read_commands(sk);
-		break;
-	case MGMT_OP_READ_INDEX_LIST:
-		err = read_index_list(sk);
-		break;
-	case MGMT_OP_READ_INFO:
-		err = read_controller_info(sk, hdev);
-		break;
-	case MGMT_OP_SET_POWERED:
-		err = set_powered(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_DISCOVERABLE:
-		err = set_discoverable(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_CONNECTABLE:
-		err = set_connectable(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_FAST_CONNECTABLE:
-		err = set_fast_connectable(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_PAIRABLE:
-		err = set_pairable(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_LINK_SECURITY:
-		err = set_link_security(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_SSP:
-		err = set_ssp(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_HS:
-		err = set_hs(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_LE:
-		err = set_le(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_ADD_UUID:
-		err = add_uuid(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_REMOVE_UUID:
-		err = remove_uuid(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_DEV_CLASS:
-		err = set_dev_class(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_LOAD_LINK_KEYS:
-		err = load_link_keys(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_DISCONNECT:
-		err = disconnect(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_GET_CONNECTIONS:
-		err = get_connections(sk, hdev);
-		break;
-	case MGMT_OP_PIN_CODE_REPLY:
-		err = pin_code_reply(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_PIN_CODE_NEG_REPLY:
-		err = pin_code_neg_reply(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_IO_CAPABILITY:
-		err = set_io_capability(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_PAIR_DEVICE:
-		err = pair_device(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_CANCEL_PAIR_DEVICE:
-		err = cancel_pair_device(sk, hdev, buf + sizeof(*hdr), len);
-		break;
-	case MGMT_OP_UNPAIR_DEVICE:
-		err = unpair_device(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_USER_CONFIRM_REPLY:
-		err = user_confirm_reply(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
-		err = user_confirm_neg_reply(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_USER_PASSKEY_REPLY:
-		err = user_passkey_reply(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
-		err = user_passkey_neg_reply(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_SET_LOCAL_NAME:
-		err = set_local_name(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_READ_LOCAL_OOB_DATA:
-		err = read_local_oob_data(sk, hdev);
-		break;
-	case MGMT_OP_ADD_REMOTE_OOB_DATA:
-		err = add_remote_oob_data(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_REMOVE_REMOTE_OOB_DATA:
-		err = remove_remote_oob_data(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_START_DISCOVERY:
-		err = start_discovery(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_STOP_DISCOVERY:
-		err = stop_discovery(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_CONFIRM_NAME:
-		err = confirm_name(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_BLOCK_DEVICE:
-		err = block_device(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_UNBLOCK_DEVICE:
-		err = unblock_device(sk, hdev, cp, len);
-		break;
-	case MGMT_OP_LOAD_LONG_TERM_KEYS:
-		err = load_long_term_keys(sk, hdev, cp, len);
-		break;
-	default:
+	if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
+					mgmt_handlers[opcode].func == NULL) {
 		BT_DBG("Unknown op %u", opcode);
 		err = cmd_status(sk, index, opcode,
 						MGMT_STATUS_UNKNOWN_COMMAND);
-		break;
+		goto done;
+	}
+
+	if ((hdev && opcode < MGMT_OP_READ_INFO) ||
+			(!hdev && opcode >= MGMT_OP_READ_INFO)) {
+		err = cmd_status(sk, index, opcode,
+						MGMT_STATUS_INVALID_PARAMS);
+		goto done;
 	}
 
+	if (hdev)
+		mgmt_init_hdev(sk, hdev);
+
+	cp = buf + sizeof(*hdr);
+
+	err = mgmt_handlers[opcode].func(sk, hdev, cp, len);
 	if (err < 0)
 		goto done;
 
-- 
1.7.9.1


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

* [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes
  2012-03-01 20:33 [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands johan.hedberg
  2012-03-01 20:33 ` [PATCH 2/5] Bluetooth: mgmt: Initialize HCI_MGMT flag for any command johan.hedberg
  2012-03-01 20:33 ` [PATCH 3/5] Bluetooth: mgmt: Move command handlers into a table johan.hedberg
@ 2012-03-01 20:33 ` johan.hedberg
  2012-03-01 20:47   ` Marcel Holtmann
  2012-03-02 13:29   ` Andrei Emeltchenko
  2012-03-01 20:33 ` [PATCH 5/5] Bluetooth: mgmt: Centralize message length checks johan.hedberg
  2012-03-01 20:45 ` [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands Marcel Holtmann
  4 siblings, 2 replies; 11+ messages in thread
From: johan.hedberg @ 2012-03-01 20:33 UTC (permalink / raw)
  To: linux-bluetooth

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

These defines are shorter than "sizeof(struct mgmt_cp_foo_bar...)" and
will be helpful when extending the command lookup table to contain the
expected command size information.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/mgmt.h |   34 ++++++++++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 7aab53e..d33457d 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -52,14 +52,17 @@ struct mgmt_addr_info {
 	bdaddr_t bdaddr;
 	__u8 type;
 } __packed;
+#define MGMT_ADDR_INFO_SIZE		7
 
 #define MGMT_OP_READ_VERSION		0x0001
+#define MGMT_READ_VERSION_SIZE		0
 struct mgmt_rp_read_version {
 	__u8 version;
 	__le16 revision;
 } __packed;
 
 #define MGMT_OP_READ_COMMANDS		0x0002
+#define MGMT_READ_COMMANDS_SIZE		0
 struct mgmt_rp_read_commands {
 	__le16 num_commands;
 	__le16 num_events;
@@ -67,6 +70,7 @@ struct mgmt_rp_read_commands {
 } __packed;
 
 #define MGMT_OP_READ_INDEX_LIST		0x0003
+#define MGMT_READ_INDEX_LIST_SIZE	0
 struct mgmt_rp_read_index_list {
 	__le16 num_controllers;
 	__le16 index[0];
@@ -89,6 +93,7 @@ struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_LE			0x00000200
 
 #define MGMT_OP_READ_INFO		0x0004
+#define MGMT_READ_INFO_SIZE		0
 struct mgmt_rp_read_info {
 	bdaddr_t bdaddr;
 	__u8 version;
@@ -104,6 +109,8 @@ struct mgmt_mode {
 	__u8 val;
 } __packed;
 
+#define MGMT_SETTING_SIZE		1
+
 #define MGMT_OP_SET_POWERED		0x0005
 
 #define MGMT_OP_SET_DISCOVERABLE	0x0006
@@ -111,6 +118,7 @@ struct mgmt_cp_set_discoverable {
 	__u8 val;
 	__u16 timeout;
 } __packed;
+#define MGMT_SET_DISCOVERABLE_SIZE	3
 
 #define MGMT_OP_SET_CONNECTABLE		0x0007
 
@@ -131,23 +139,27 @@ struct mgmt_cp_set_dev_class {
 	__u8 major;
 	__u8 minor;
 } __packed;
+#define MGMT_SET_DEV_CLASS_SIZE		2
 
 #define MGMT_OP_SET_LOCAL_NAME		0x000F
 struct mgmt_cp_set_local_name {
 	__u8 name[MGMT_MAX_NAME_LENGTH];
 	__u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
 } __packed;
+#define MGMT_SET_LOCAL_NAME_SIZE	260
 
 #define MGMT_OP_ADD_UUID		0x0010
 struct mgmt_cp_add_uuid {
 	__u8 uuid[16];
 	__u8 svc_hint;
 } __packed;
+#define MGMT_ADD_UUID_SIZE		17
 
 #define MGMT_OP_REMOVE_UUID		0x0011
 struct mgmt_cp_remove_uuid {
 	__u8 uuid[16];
 } __packed;
+#define MGMT_REMOVE_UUID_SIZE		16
 
 struct mgmt_link_key_info {
 	struct mgmt_addr_info addr;
@@ -162,6 +174,7 @@ struct mgmt_cp_load_link_keys {
 	__le16 key_count;
 	struct mgmt_link_key_info keys[0];
 } __packed;
+#define MGMT_LOAD_LINK_KEYS_SIZE	3
 
 struct mgmt_ltk_info {
 	struct mgmt_addr_info addr;
@@ -178,16 +191,19 @@ struct mgmt_cp_load_long_term_keys {
 	__le16 key_count;
 	struct mgmt_ltk_info keys[0];
 } __packed;
+#define MGMT_LOAD_LONG_TERM_KEYS_SIZE	2
 
 #define MGMT_OP_DISCONNECT		0x0014
 struct mgmt_cp_disconnect {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_DISCONNECT_SIZE		MGMT_ADDR_INFO_SIZE
 struct mgmt_rp_disconnect {
 	struct mgmt_addr_info addr;
 } __packed;
 
 #define MGMT_OP_GET_CONNECTIONS		0x0015
+#define MGMT_GET_CONNECTIONS_SIZE	0
 struct mgmt_rp_get_connections {
 	__le16 conn_count;
 	struct mgmt_addr_info addr[0];
@@ -199,6 +215,7 @@ struct mgmt_cp_pin_code_reply {
 	__u8 pin_len;
 	__u8 pin_code[16];
 } __packed;
+#define MGMT_PIN_CODE_REPLY_SIZE	(MGMT_ADDR_INFO_SIZE + 17)
 struct mgmt_rp_pin_code_reply {
 	struct mgmt_addr_info addr;
 } __packed;
@@ -207,28 +224,33 @@ struct mgmt_rp_pin_code_reply {
 struct mgmt_cp_pin_code_neg_reply {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_PIN_CODE_NEG_REPLY_SIZE	MGMT_ADDR_INFO_SIZE
 
 #define MGMT_OP_SET_IO_CAPABILITY	0x0018
 struct mgmt_cp_set_io_capability {
 	__u8 io_capability;
 } __packed;
+#define MGMT_SET_IO_CAPABILITY_SIZE	1
 
 #define MGMT_OP_PAIR_DEVICE		0x0019
 struct mgmt_cp_pair_device {
 	struct mgmt_addr_info addr;
 	__u8 io_cap;
 } __packed;
+#define MGMT_PAIR_DEVICE_SIZE		(MGMT_ADDR_INFO_SIZE + 1)
 struct mgmt_rp_pair_device {
 	struct mgmt_addr_info addr;
 } __packed;
 
 #define MGMT_OP_CANCEL_PAIR_DEVICE	0x001A
+#define MGMT_CANCEL_PAIR_DEVICE_SIZE	MGMT_ADDR_INFO_SIZE
 
 #define MGMT_OP_UNPAIR_DEVICE		0x001B
 struct mgmt_cp_unpair_device {
 	struct mgmt_addr_info addr;
 	__u8 disconnect;
 } __packed;
+#define MGMT_UNPAIR_DEVICE_SIZE		(MGMT_ADDR_INFO_SIZE + 1)
 struct mgmt_rp_unpair_device {
 	struct mgmt_addr_info addr;
 };
@@ -237,6 +259,7 @@ struct mgmt_rp_unpair_device {
 struct mgmt_cp_user_confirm_reply {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_USER_CONFIRM_REPLY_SIZE	MGMT_ADDR_INFO_SIZE
 struct mgmt_rp_user_confirm_reply {
 	struct mgmt_addr_info addr;
 } __packed;
@@ -245,12 +268,14 @@ struct mgmt_rp_user_confirm_reply {
 struct mgmt_cp_user_confirm_neg_reply {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_USER_CONFIRM_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
 
 #define MGMT_OP_USER_PASSKEY_REPLY	0x001E
 struct mgmt_cp_user_passkey_reply {
 	struct mgmt_addr_info addr;
 	__le32 passkey;
 } __packed;
+#define MGMT_USER_PASSKEY_REPLY_SIZE	(MGMT_ADDR_INFO_SIZE + 4)
 struct mgmt_rp_user_passkey_reply {
 	struct mgmt_addr_info addr;
 } __packed;
@@ -259,8 +284,10 @@ struct mgmt_rp_user_passkey_reply {
 struct mgmt_cp_user_passkey_neg_reply {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_USER_PASSKEY_NEG_REPLY_SIZE MGMT_ADDR_INFO_SIZE
 
 #define MGMT_OP_READ_LOCAL_OOB_DATA	0x0020
+#define MGMT_READ_LOCAL_OOB_DATA_SIZE	0
 struct mgmt_rp_read_local_oob_data {
 	__u8 hash[16];
 	__u8 randomizer[16];
@@ -272,27 +299,32 @@ struct mgmt_cp_add_remote_oob_data {
 	__u8 hash[16];
 	__u8 randomizer[16];
 } __packed;
+#define MGMT_ADD_REMOTE_OOB_DATA_SIZE	(MGMT_ADDR_INFO_SIZE + 32)
 
 #define MGMT_OP_REMOVE_REMOTE_OOB_DATA	0x0022
 struct mgmt_cp_remove_remote_oob_data {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_REMOVE_REMOTE_OOB_DATA_SIZE MGMT_ADDR_INFO_SIZE
 
 #define MGMT_OP_START_DISCOVERY		0x0023
 struct mgmt_cp_start_discovery {
 	__u8 type;
 } __packed;
+#define MGMT_START_DISCOVERY_SIZE	1
 
 #define MGMT_OP_STOP_DISCOVERY		0x0024
 struct mgmt_cp_stop_discovery {
 	__u8 type;
 } __packed;
+#define MGMT_STOP_DISCOVERY_SIZE	1
 
 #define MGMT_OP_CONFIRM_NAME		0x0025
 struct mgmt_cp_confirm_name {
 	struct mgmt_addr_info addr;
 	__u8 name_known;
 } __packed;
+#define MGMT_CONFIRM_NAME_SIZE		(MGMT_ADDR_INFO_SIZE + 1)
 struct mgmt_rp_confirm_name {
 	struct mgmt_addr_info addr;
 } __packed;
@@ -301,11 +333,13 @@ struct mgmt_rp_confirm_name {
 struct mgmt_cp_block_device {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_BLOCK_DEVICE_SIZE		MGMT_ADDR_INFO_SIZE
 
 #define MGMT_OP_UNBLOCK_DEVICE		0x0027
 struct mgmt_cp_unblock_device {
 	struct mgmt_addr_info addr;
 } __packed;
+#define MGMT_UNBLOCK_DEVICE_SIZE	MGMT_ADDR_INFO_SIZE
 
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
-- 
1.7.9.1


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

* [PATCH 5/5] Bluetooth: mgmt: Centralize message length checks
  2012-03-01 20:33 [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands johan.hedberg
                   ` (2 preceding siblings ...)
  2012-03-01 20:33 ` [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes johan.hedberg
@ 2012-03-01 20:33 ` johan.hedberg
  2012-03-01 20:48   ` Marcel Holtmann
  2012-03-01 20:45 ` [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands Marcel Holtmann
  4 siblings, 1 reply; 11+ messages in thread
From: johan.hedberg @ 2012-03-01 20:33 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch moves the command length information into the command handler
table allowing the removal of length checks from the handler functions
and doing the check in a single place before calling the handler
function.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/mgmt.c |  220 ++++++++++++--------------------------------------
 1 files changed, 52 insertions(+), 168 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 88a342a..7bd7d57 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -751,10 +751,6 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
@@ -846,10 +842,6 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	timeout = get_unaligned_le16(&cp->timeout);
 	if (!cp->val && timeout > 0)
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
@@ -945,10 +937,6 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -1019,10 +1007,6 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (cp->val)
@@ -1051,10 +1035,6 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -1115,10 +1095,6 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
@@ -1181,10 +1157,6 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	if (!enable_hs)
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
 						MGMT_STATUS_NOT_SUPPORTED);
@@ -1207,10 +1179,6 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!enable_le || !(hdev->features[4] & LMP_LE)) {
@@ -1280,10 +1248,6 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
@@ -1353,10 +1317,6 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
@@ -1430,10 +1390,6 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("request for %s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
@@ -1486,10 +1442,6 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
 	u16 key_count, expected_len;
 	int i;
 
-	if (len < sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	key_count = get_unaligned_le16(&cp->key_count);
 
 	expected_len = sizeof(*cp) + key_count *
@@ -1551,10 +1503,6 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
 	struct hci_conn *conn;
 	int err;
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	memset(&rp, 0, sizeof(rp));
@@ -1627,10 +1575,6 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!test_bit(HCI_UP, &hdev->flags)) {
@@ -1781,10 +1725,6 @@ static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -1842,10 +1782,6 @@ static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -1868,10 +1804,6 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	hdev->io_capability = cp->io_capability;
@@ -1949,10 +1881,6 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -2029,10 +1957,6 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	if (len != sizeof(*addr))
-		return cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -2153,10 +2077,6 @@ static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_NEG_REPLY,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
 					MGMT_OP_USER_CONFIRM_NEG_REPLY,
 					HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
@@ -2169,10 +2089,6 @@ static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_USER_PASSKEY_REPLY,
-									EINVAL);
-
 	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
 						MGMT_OP_USER_PASSKEY_REPLY,
 						HCI_OP_USER_PASSKEY_REPLY,
@@ -2186,10 +2102,6 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("");
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_USER_PASSKEY_NEG_REPLY,
-								EINVAL);
-
 	return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
 					MGMT_OP_USER_PASSKEY_NEG_REPLY,
 					HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
@@ -2205,10 +2117,6 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("");
 
-	if (len != sizeof(*mgmt_cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	memcpy(hdev->short_name, mgmt_cp->short_name,
@@ -2297,10 +2205,6 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("%s ", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -2334,10 +2238,6 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("%s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -2388,10 +2288,6 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("%s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hdev_is_powered(hdev)) {
@@ -2463,10 +2359,6 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("%s", hdev->name);
 
-	if (len != sizeof(*mgmt_cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hci_discovery_active(hdev)) {
@@ -2529,10 +2421,6 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("%s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	if (!hci_discovery_active(hdev)) {
@@ -2572,10 +2460,6 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("%s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
@@ -2601,10 +2485,6 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	BT_DBG("%s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	hci_dev_lock(hdev);
 
 	err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
@@ -2631,10 +2511,6 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 
 	BT_DBG("%s", hdev->name);
 
-	if (len != sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
-						MGMT_STATUS_INVALID_PARAMS);
-
 	if (!hdev_is_powered(hdev))
 		return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
 						MGMT_STATUS_NOT_POWERED);
@@ -2684,10 +2560,6 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 	u16 key_count, expected_len;
 	int i;
 
-	if (len < sizeof(*cp))
-		return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
-								EINVAL);
-
 	key_count = get_unaligned_le16(&cp->key_count);
 
 	expected_len = sizeof(*cp) + key_count *
@@ -2727,47 +2599,49 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 struct mgmt_handler {
 	int (*func) (struct sock *sk, struct hci_dev *hdev,
 						void *data, u16 data_len);
+	bool var_len;
+	size_t data_len;
 } mgmt_handlers[] = {
 	{ NULL }, /* 0x0000 (no command) */
-	{ read_version, },
-	{ read_commands, },
-	{ read_index_list, },
-	{ read_controller_info, },
-	{ set_powered, },
-	{ set_discoverable, },
-	{ set_connectable, },
-	{ set_fast_connectable, },
-	{ set_pairable,	},
-	{ set_link_security, },
-	{ set_ssp, },
-	{ set_hs, },
-	{ set_le, },
-	{ set_dev_class, },
-	{ set_local_name, },
-	{ add_uuid, },
-	{ remove_uuid, },
-	{ load_link_keys, },
-	{ load_long_term_keys, },
-	{ disconnect, },
-	{ get_connections, },
-	{ pin_code_reply, },
-	{ pin_code_neg_reply, },
-	{ set_io_capability, },
-	{ pair_device, },
-	{ cancel_pair_device, },
-	{ unpair_device, },
-	{ user_confirm_reply, },
-	{ user_confirm_neg_reply, },
-	{ user_passkey_reply, },
-	{ user_passkey_neg_reply, },
-	{ read_local_oob_data, },
-	{ add_remote_oob_data, },
-	{ remove_remote_oob_data, },
-	{ start_discovery, },
-	{ stop_discovery, },
-	{ confirm_name, },
-	{ block_device, },
-	{ unblock_device, },
+	{ read_version,           false, MGMT_READ_VERSION_SIZE },
+	{ read_commands,          false, MGMT_READ_COMMANDS_SIZE },
+	{ read_index_list,        false, MGMT_READ_INDEX_LIST_SIZE },
+	{ read_controller_info,   false, MGMT_READ_INFO_SIZE },
+	{ set_powered,            false, MGMT_SETTING_SIZE },
+	{ set_discoverable,       false, MGMT_SET_DISCOVERABLE_SIZE },
+	{ set_connectable,        false, MGMT_SETTING_SIZE },
+	{ set_fast_connectable,   false, MGMT_SETTING_SIZE },
+	{ set_pairable,           false, MGMT_SETTING_SIZE },
+	{ set_link_security,      false, MGMT_SETTING_SIZE },
+	{ set_ssp,                false, MGMT_SETTING_SIZE },
+	{ set_hs,                 false, MGMT_SETTING_SIZE },
+	{ set_le,                 false, MGMT_SETTING_SIZE },
+	{ set_dev_class,          false, MGMT_SET_DEV_CLASS_SIZE },
+	{ set_local_name,         false, MGMT_SET_LOCAL_NAME_SIZE },
+	{ add_uuid,               false, MGMT_ADD_UUID_SIZE },
+	{ remove_uuid,            false, MGMT_REMOVE_UUID_SIZE },
+	{ load_link_keys,         true,  MGMT_LOAD_LINK_KEYS_SIZE },
+	{ load_long_term_keys,    true,  MGMT_LOAD_LONG_TERM_KEYS_SIZE },
+	{ disconnect,             false, MGMT_DISCONNECT_SIZE },
+	{ get_connections,        false, MGMT_GET_CONNECTIONS_SIZE },
+	{ pin_code_reply,         false, MGMT_PIN_CODE_REPLY_SIZE },
+	{ pin_code_neg_reply,     false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
+	{ set_io_capability,      false, MGMT_SET_IO_CAPABILITY_SIZE },
+	{ pair_device,            false, MGMT_PAIR_DEVICE_SIZE },
+	{ cancel_pair_device,     false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
+	{ unpair_device,          false, MGMT_UNPAIR_DEVICE_SIZE },
+	{ user_confirm_reply,     false, MGMT_USER_CONFIRM_REPLY_SIZE },
+	{ user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
+	{ user_passkey_reply,     false, MGMT_USER_PASSKEY_REPLY_SIZE },
+	{ user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
+	{ read_local_oob_data,    false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
+	{ add_remote_oob_data,    false, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
+	{ remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
+	{ start_discovery,        false, MGMT_START_DISCOVERY_SIZE },
+	{ stop_discovery,         false, MGMT_STOP_DISCOVERY_SIZE },
+	{ confirm_name,           false, MGMT_CONFIRM_NAME_SIZE },
+	{ block_device,           false, MGMT_BLOCK_DEVICE_SIZE },
+	{ unblock_device,         false, MGMT_UNBLOCK_DEVICE_SIZE },
 };
 
 
@@ -2778,6 +2652,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 	struct mgmt_hdr *hdr;
 	u16 opcode, index, len;
 	struct hci_dev *hdev = NULL;
+	struct mgmt_handler *handler;
 	int err;
 
 	BT_DBG("got %zu bytes", msglen);
@@ -2828,12 +2703,21 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 		goto done;
 	}
 
+	handler = &mgmt_handlers[opcode];
+
+	if ((handler->var_len && len < handler->data_len) ||
+			(!handler->var_len && len != handler->data_len)) {
+		err = cmd_status(sk, index, opcode,
+						MGMT_STATUS_INVALID_PARAMS);
+		goto done;
+	}
+
 	if (hdev)
 		mgmt_init_hdev(sk, hdev);
 
 	cp = buf + sizeof(*hdr);
 
-	err = mgmt_handlers[opcode].func(sk, hdev, cp, len);
+	err = handler->func(sk, hdev, cp, len);
 	if (err < 0)
 		goto done;
 
-- 
1.7.9.1


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

* Re: [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands
  2012-03-01 20:33 [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands johan.hedberg
                   ` (3 preceding siblings ...)
  2012-03-01 20:33 ` [PATCH 5/5] Bluetooth: mgmt: Centralize message length checks johan.hedberg
@ 2012-03-01 20:45 ` Marcel Holtmann
  4 siblings, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2012-03-01 20:45 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi Johan,

> Almost all mgmt commands need to lookup a struct hci_dev based on the
> index received within the mgmt headers. It makese therefore sense to
> look this up in a single place and then just pass the hdev pointer to
> each command handler function.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
>  net/bluetooth/mgmt.c |  764 ++++++++++++++++++--------------------------------
>  1 files changed, 274 insertions(+), 490 deletions(-)

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



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

* Re: [PATCH 2/5] Bluetooth: mgmt: Initialize HCI_MGMT flag for any command
  2012-03-01 20:33 ` [PATCH 2/5] Bluetooth: mgmt: Initialize HCI_MGMT flag for any command johan.hedberg
@ 2012-03-01 20:46   ` Marcel Holtmann
  0 siblings, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2012-03-01 20:46 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi Johan,

> The read_controller_info is typically the first command that user space
> sends when taking a controller into use. This is also the reason why
> this command has been used as the trigger to set the HCI_MGMT flag.
> However, when not running the user-space daemon and using command line
> tools it is possible that read_controller_info is not the first
> controller specific command. This patch moves the HCI_MGMT
> initialization to a generic place where it will be set for whatever
> happens to be the first mgmt command targetting a specific controller.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
>  net/bluetooth/mgmt.c |   10 ++++++----
>  1 files changed, 6 insertions(+), 4 deletions(-)

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



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

* Re: [PATCH 3/5] Bluetooth: mgmt: Move command handlers into a table
  2012-03-01 20:33 ` [PATCH 3/5] Bluetooth: mgmt: Move command handlers into a table johan.hedberg
@ 2012-03-01 20:47   ` Marcel Holtmann
  0 siblings, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2012-03-01 20:47 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi Johan,

> By moving the command handlers into a table (the index being equal to
> the opcode) the lookup is made a bit more efficient. Having a struct to
> describe each handler also paves the way to add more meta-data for each
> handler, e.g. the minimum message size for the command and allow
> handling of common tasks like this in a centralized place.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
>  net/bluetooth/mgmt.c |  219 ++++++++++++++++++--------------------------------
>  1 files changed, 79 insertions(+), 140 deletions(-)

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



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

* Re: [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes
  2012-03-01 20:33 ` [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes johan.hedberg
@ 2012-03-01 20:47   ` Marcel Holtmann
  2012-03-02 13:29   ` Andrei Emeltchenko
  1 sibling, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2012-03-01 20:47 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi Johan,

> These defines are shorter than "sizeof(struct mgmt_cp_foo_bar...)" and
> will be helpful when extending the command lookup table to contain the
> expected command size information.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
>  include/net/bluetooth/mgmt.h |   34 ++++++++++++++++++++++++++++++++++
>  1 files changed, 34 insertions(+), 0 deletions(-)

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



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

* Re: [PATCH 5/5] Bluetooth: mgmt: Centralize message length checks
  2012-03-01 20:33 ` [PATCH 5/5] Bluetooth: mgmt: Centralize message length checks johan.hedberg
@ 2012-03-01 20:48   ` Marcel Holtmann
  0 siblings, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2012-03-01 20:48 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi Johan,

> This patch moves the command length information into the command handler
> table allowing the removal of length checks from the handler functions
> and doing the check in a single place before calling the handler
> function.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
>  net/bluetooth/mgmt.c |  220 ++++++++++++--------------------------------------
>  1 files changed, 52 insertions(+), 168 deletions(-)

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



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

* Re: [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes
  2012-03-01 20:33 ` [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes johan.hedberg
  2012-03-01 20:47   ` Marcel Holtmann
@ 2012-03-02 13:29   ` Andrei Emeltchenko
  1 sibling, 0 replies; 11+ messages in thread
From: Andrei Emeltchenko @ 2012-03-02 13:29 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth

Hi Johan,

On Thu, Mar 01, 2012 at 12:33:31PM -0800, johan.hedberg@gmail.com wrote:
> From: Johan Hedberg <johan.hedberg@intel.com>
> 
> These defines are shorter than "sizeof(struct mgmt_cp_foo_bar...)" and

Maybe matter of taste but I would leave sizeof.

Best regards 
Andrei Emeltchenko 


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

end of thread, other threads:[~2012-03-02 13:29 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-01 20:33 [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands johan.hedberg
2012-03-01 20:33 ` [PATCH 2/5] Bluetooth: mgmt: Initialize HCI_MGMT flag for any command johan.hedberg
2012-03-01 20:46   ` Marcel Holtmann
2012-03-01 20:33 ` [PATCH 3/5] Bluetooth: mgmt: Move command handlers into a table johan.hedberg
2012-03-01 20:47   ` Marcel Holtmann
2012-03-01 20:33 ` [PATCH 4/5] Bluetooth: mgmt: Add defines for command sizes johan.hedberg
2012-03-01 20:47   ` Marcel Holtmann
2012-03-02 13:29   ` Andrei Emeltchenko
2012-03-01 20:33 ` [PATCH 5/5] Bluetooth: mgmt: Centralize message length checks johan.hedberg
2012-03-01 20:48   ` Marcel Holtmann
2012-03-01 20:45 ` [PATCH 1/5] Bluetooth: mgmt: Refactor hci_dev lookup for commands Marcel Holtmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).