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>
This commit is contained in:
Родитель
484aabc1c4
Коммит
a1443f5a27
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче