Skip to content

Commit

Permalink
Bluetooth: Convert Set SC to use HCI Request
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johan Hedberg authored and Marcel Holtmann committed Jan 23, 2015
1 parent 484aabc commit a1443f5
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 47 deletions.
1 change: 0 additions & 1 deletion include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 1 addition & 3 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
92 changes: 49 additions & 43 deletions net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -4741,11 +4741,57 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit a1443f5

Please sign in to comment.