diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2014-02-23 19:42:27 +0200 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-02-23 12:24:26 -0800 |
commit | 62b04cd124cb76ce0b9a6391c6c046c08c1ac8b7 (patch) | |
tree | d767548185774ba3acd6cdfa07fdb3ef5b2694c1 /net/bluetooth/mgmt.c | |
parent | c982b2ea29af7a78685b9e32ea028917a07b783e (diff) | |
download | talos-obmc-linux-62b04cd124cb76ce0b9a6391c6c046c08c1ac8b7.tar.gz talos-obmc-linux-62b04cd124cb76ce0b9a6391c6c046c08c1ac8b7.zip |
Bluetooth: Add support for Set Privacy command
This patch adds support for handling the Set Privacy mgmt command,
including copying the value to hdev->irk and toggling the HCI_PRIVACY
flag.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 49d52a37bdac..37305facf4d6 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -81,6 +81,7 @@ static const u16 mgmt_commands[] = { MGMT_OP_SET_SCAN_PARAMS, MGMT_OP_SET_SECURE_CONN, MGMT_OP_SET_DEBUG_KEYS, + MGMT_OP_SET_PRIVACY, MGMT_OP_LOAD_IRKS, }; @@ -4227,6 +4228,51 @@ unlock: return err; } +static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, + u16 len) +{ + struct mgmt_cp_set_privacy *cp = cp_data; + bool changed; + int err; + + BT_DBG("request for %s", hdev->name); + + if (!lmp_le_capable(hdev)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, + MGMT_STATUS_NOT_SUPPORTED); + + if (cp->privacy != 0x00 && cp->privacy != 0x01) + return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, + MGMT_STATUS_INVALID_PARAMS); + + if (hdev_is_powered(hdev)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, + MGMT_STATUS_REJECTED); + + hci_dev_lock(hdev); + + if (cp->privacy) { + changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags); + memcpy(hdev->irk, cp->irk, sizeof(hdev->irk)); + set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); + } else { + changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags); + memset(hdev->irk, 0, sizeof(hdev->irk)); + clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); + } + + err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev); + if (err < 0) + goto unlock; + + if (changed) + err = new_settings(hdev, sk); + +unlock: + hci_dev_unlock(hdev); + return err; +} + static bool irk_is_valid(struct mgmt_irk_info *irk) { switch (irk->addr.type) { @@ -4441,7 +4487,7 @@ static const struct mgmt_handler { { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, { set_secure_conn, false, MGMT_SETTING_SIZE }, { set_debug_keys, false, MGMT_SETTING_SIZE }, - { }, + { set_privacy, false, MGMT_SET_PRIVACY_SIZE }, { load_irks, true, MGMT_LOAD_IRKS_SIZE }, }; |