aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-02-23 12:42:27 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-02-23 15:24:26 -0500
commit62b04cd124cb76ce0b9a6391c6c046c08c1ac8b7 (patch)
treed767548185774ba3acd6cdfa07fdb3ef5b2694c1 /net/bluetooth/mgmt.c
parentc982b2ea29af7a78685b9e32ea028917a07b783e (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.c48
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
4231static 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
4271unlock:
4272 hci_dev_unlock(hdev);
4273 return err;
4274}
4275
4230static bool irk_is_valid(struct mgmt_irk_info *irk) 4276static 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