diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2014-02-23 12:42:27 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-02-23 15:24:26 -0500 |
commit | 62b04cd124cb76ce0b9a6391c6c046c08c1ac8b7 (patch) | |
tree | d767548185774ba3acd6cdfa07fdb3ef5b2694c1 /net/bluetooth/mgmt.c | |
parent | c982b2ea29af7a78685b9e32ea028917a07b783e (diff) |
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[] = { | |||
81 | MGMT_OP_SET_SCAN_PARAMS, | 81 | MGMT_OP_SET_SCAN_PARAMS, |
82 | MGMT_OP_SET_SECURE_CONN, | 82 | MGMT_OP_SET_SECURE_CONN, |
83 | MGMT_OP_SET_DEBUG_KEYS, | 83 | MGMT_OP_SET_DEBUG_KEYS, |
84 | MGMT_OP_SET_PRIVACY, | ||
84 | MGMT_OP_LOAD_IRKS, | 85 | MGMT_OP_LOAD_IRKS, |
85 | }; | 86 | }; |
86 | 87 | ||
@@ -4227,6 +4228,51 @@ unlock: | |||
4227 | return err; | 4228 | return err; |
4228 | } | 4229 | } |
4229 | 4230 | ||
4231 | static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, | ||
4232 | u16 len) | ||
4233 | { | ||
4234 | struct mgmt_cp_set_privacy *cp = cp_data; | ||
4235 | bool changed; | ||
4236 | int err; | ||
4237 | |||
4238 | BT_DBG("request for %s", hdev->name); | ||
4239 | |||
4240 | if (!lmp_le_capable(hdev)) | ||
4241 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, | ||
4242 | MGMT_STATUS_NOT_SUPPORTED); | ||
4243 | |||
4244 | if (cp->privacy != 0x00 && cp->privacy != 0x01) | ||
4245 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, | ||
4246 | MGMT_STATUS_INVALID_PARAMS); | ||
4247 | |||
4248 | if (hdev_is_powered(hdev)) | ||
4249 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, | ||
4250 | MGMT_STATUS_REJECTED); | ||
4251 | |||
4252 | hci_dev_lock(hdev); | ||
4253 | |||
4254 | if (cp->privacy) { | ||
4255 | changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags); | ||
4256 | memcpy(hdev->irk, cp->irk, sizeof(hdev->irk)); | ||
4257 | set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); | ||
4258 | } else { | ||
4259 | changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags); | ||
4260 | memset(hdev->irk, 0, sizeof(hdev->irk)); | ||
4261 | clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); | ||
4262 | } | ||
4263 | |||
4264 | err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev); | ||
4265 | if (err < 0) | ||
4266 | goto unlock; | ||
4267 | |||
4268 | if (changed) | ||
4269 | err = new_settings(hdev, sk); | ||
4270 | |||
4271 | unlock: | ||
4272 | hci_dev_unlock(hdev); | ||
4273 | return err; | ||
4274 | } | ||
4275 | |||
4230 | static bool irk_is_valid(struct mgmt_irk_info *irk) | 4276 | static bool irk_is_valid(struct mgmt_irk_info *irk) |
4231 | { | 4277 | { |
4232 | switch (irk->addr.type) { | 4278 | switch (irk->addr.type) { |
@@ -4441,7 +4487,7 @@ static const struct mgmt_handler { | |||
4441 | { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, | 4487 | { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, |
4442 | { set_secure_conn, false, MGMT_SETTING_SIZE }, | 4488 | { set_secure_conn, false, MGMT_SETTING_SIZE }, |
4443 | { set_debug_keys, false, MGMT_SETTING_SIZE }, | 4489 | { set_debug_keys, false, MGMT_SETTING_SIZE }, |
4444 | { }, | 4490 | { set_privacy, false, MGMT_SET_PRIVACY_SIZE }, |
4445 | { load_irks, true, MGMT_LOAD_IRKS_SIZE }, | 4491 | { load_irks, true, MGMT_LOAD_IRKS_SIZE }, |
4446 | }; | 4492 | }; |
4447 | 4493 | ||