diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-01-23 16:42:46 +0300 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-01-23 21:07:03 +0300 |
commit | a1443f5a273713d4bfda360e45aa6e1d14fe7324 (patch) | |
tree | 1c1ff41e6bac931e44c1d8da3b5ccb747fc6a6a1 | |
parent | 484aabc1c4e869879e614a621e2dfabc9f98fb00 (diff) | |
download | linux-a1443f5a273713d4bfda360e45aa6e1d14fe7324.tar.xz |
Bluetooth: Convert Set SC to use HCI Request
This patch converts the Set Secure Connection HCI handling to use a HCI
request instead of using a hard-coded callback in hci_event.c. This e.g.
ensures that we don't clear the flags incorrectly if something goes
wrong with the power up process (not related to a mgmt Set SC command).
The code can also be simplified a bit since only one pending Set SC
command is allowed, i.e. mgmt_pending_foreach usage is not needed.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | include/net/bluetooth/hci_core.h | 1 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 4 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 92 |
3 files changed, 50 insertions, 47 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7777124bff55..0f5e59f1e3cb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1369,7 +1369,6 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_auth_failed(struct hci_conn *conn, u8 status); void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); -void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, u8 status); void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a58845e98921..e2b81adc232f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -525,9 +525,7 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) hdev->features[1][0] &= ~LMP_HOST_SC; } - if (test_bit(HCI_MGMT, &hdev->dev_flags)) - mgmt_sc_enable_complete(hdev, sent->support, status); - else if (!status) { + if (!test_bit(HCI_MGMT, &hdev->dev_flags) && !status) { if (sent->support) set_bit(HCI_SC_ENABLED, &hdev->dev_flags); else diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 862a005d9db2..25e40e82b9a2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4741,11 +4741,57 @@ unlock: return err; } +static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) +{ + struct pending_cmd *cmd; + struct mgmt_mode *cp; + + BT_DBG("%s status %u", hdev->name, status); + + hci_dev_lock(hdev); + + cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev); + if (!cmd) + goto unlock; + + if (status) { + cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_status(status)); + goto remove; + } + + cp = cmd->param; + + switch (cp->val) { + case 0x00: + clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); + clear_bit(HCI_SC_ONLY, &hdev->dev_flags); + break; + case 0x01: + set_bit(HCI_SC_ENABLED, &hdev->dev_flags); + clear_bit(HCI_SC_ONLY, &hdev->dev_flags); + break; + case 0x02: + set_bit(HCI_SC_ENABLED, &hdev->dev_flags); + set_bit(HCI_SC_ONLY, &hdev->dev_flags); + break; + } + + send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev); + new_settings(hdev, cmd->sk); + +remove: + mgmt_pending_remove(cmd); +unlock: + hci_dev_unlock(hdev); +} + static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_mode *cp = data; struct pending_cmd *cmd; + struct hci_request req; u8 val; int err; @@ -4814,17 +4860,14 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, goto failed; } - err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val); + hci_req_init(&req, hdev); + hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val); + err = hci_req_run(&req, sc_enable_complete); if (err < 0) { mgmt_pending_remove(cmd); goto failed; } - if (cp->val == 0x02) - set_bit(HCI_SC_ONLY, &hdev->dev_flags); - else - clear_bit(HCI_SC_ONLY, &hdev->dev_flags); - failed: hci_dev_unlock(hdev); return err; @@ -7001,43 +7044,6 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) hci_req_run(&req, NULL); } -void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) -{ - struct cmd_lookup match = { NULL, hdev }; - bool changed = false; - - if (status) { - u8 mgmt_err = mgmt_status(status); - - if (enable) { - if (test_and_clear_bit(HCI_SC_ENABLED, - &hdev->dev_flags)) - new_settings(hdev, NULL); - clear_bit(HCI_SC_ONLY, &hdev->dev_flags); - } - - mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, - cmd_status_rsp, &mgmt_err); - return; - } - - if (enable) { - changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags); - } else { - changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); - clear_bit(HCI_SC_ONLY, &hdev->dev_flags); - } - - mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, - settings_rsp, &match); - - if (changed) - new_settings(hdev, match.sk); - - if (match.sk) - sock_put(match.sk); -} - static void sk_lookup(struct pending_cmd *cmd, void *data) { struct cmd_lookup *match = data; |