mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-11-27 01:11:31 +00:00
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:
parent
484aabc1c4
commit
a1443f5a27
3 changed files with 50 additions and 47 deletions
|
|
@ -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_failed(struct hci_conn *conn, u8 status);
|
||||||
void mgmt_auth_enable_complete(struct hci_dev *hdev, 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_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,
|
void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
|
||||||
u8 status);
|
u8 status);
|
||||||
void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, 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;
|
hdev->features[1][0] &= ~LMP_HOST_SC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
if (!test_bit(HCI_MGMT, &hdev->dev_flags) && !status) {
|
||||||
mgmt_sc_enable_complete(hdev, sent->support, status);
|
|
||||||
else if (!status) {
|
|
||||||
if (sent->support)
|
if (sent->support)
|
||||||
set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -4741,11 +4741,57 @@ unlock:
|
||||||
return err;
|
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,
|
static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
|
||||||
void *data, u16 len)
|
void *data, u16 len)
|
||||||
{
|
{
|
||||||
struct mgmt_mode *cp = data;
|
struct mgmt_mode *cp = data;
|
||||||
struct pending_cmd *cmd;
|
struct pending_cmd *cmd;
|
||||||
|
struct hci_request req;
|
||||||
u8 val;
|
u8 val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|
@ -4814,17 +4860,14 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
|
||||||
goto failed;
|
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) {
|
if (err < 0) {
|
||||||
mgmt_pending_remove(cmd);
|
mgmt_pending_remove(cmd);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cp->val == 0x02)
|
|
||||||
set_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
|
||||||
else
|
|
||||||
clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
|
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -7001,43 +7044,6 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
|
||||||
hci_req_run(&req, NULL);
|
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)
|
static void sk_lookup(struct pending_cmd *cmd, void *data)
|
||||||
{
|
{
|
||||||
struct cmd_lookup *match = data;
|
struct cmd_lookup *match = data;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue