summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2013-10-02 04:41:30 -0700
committerJohan Hedberg <johan.hedberg@intel.com>2013-10-02 14:50:58 +0300
commitd13eafce2c892d57f1eb243e43dfe48b4626006d (patch)
tree6ce6e6a461756a0a5a5e7371b77a60f1977b7a10 /net/bluetooth
parenta0cdf960bec0b040307229bc25c40fa33c20dff1 (diff)
downloadop-kernel-dev-d13eafce2c892d57f1eb243e43dfe48b4626006d.zip
op-kernel-dev-d13eafce2c892d57f1eb243e43dfe48b4626006d.tar.gz
Bluetooth: Add management command for setting static address
On dual-mode BR/EDR/LE and LE only controllers it is possible to configure a random address. There are two types or random addresses, one is static and the other private. Since the random private addresses require special privacy feature to be supported, the configuration of these two are kept separate. This command allows for setting the static random address. It is only supported on controllers with LE support. The static random address is suppose to be valid for the lifetime of the controller or at least until the next power cycle. To ensure such behavior, setting of the address is limited to when the controller is powered off. The special BDADDR_ANY address (00:00:00:00:00:00) can be used to disable the static address. This is also the default value. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/mgmt.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4ac3169..b871632 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -76,6 +76,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_SET_DEVICE_ID,
MGMT_OP_SET_ADVERTISING,
MGMT_OP_SET_BREDR,
+ MGMT_OP_SET_STATIC_ADDRESS,
};
static const u16 mgmt_events[] = {
@@ -3247,6 +3248,46 @@ unlock:
return err;
}
+static int set_static_address(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct mgmt_cp_set_static_address *cp = data;
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ if (!lmp_le_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
+ MGMT_STATUS_NOT_SUPPORTED);
+
+ if (hdev_is_powered(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
+ MGMT_STATUS_REJECTED);
+
+ if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
+ if (!bacmp(&cp->bdaddr, BDADDR_NONE))
+ return cmd_status(sk, hdev->id,
+ MGMT_OP_SET_STATIC_ADDRESS,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ /* Two most significant bits shall be set */
+ if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
+ return cmd_status(sk, hdev->id,
+ MGMT_OP_SET_STATIC_ADDRESS,
+ MGMT_STATUS_INVALID_PARAMS);
+ }
+
+ hci_dev_lock(hdev);
+
+ bacpy(&hdev->static_addr, &cp->bdaddr);
+
+ err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
+
+ hci_dev_unlock(hdev);
+
+ return err;
+}
+
static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
{
struct pending_cmd *cmd;
@@ -3576,6 +3617,7 @@ static const struct mgmt_handler {
{ set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
{ set_advertising, false, MGMT_SETTING_SIZE },
{ set_bredr, false, MGMT_SETTING_SIZE },
+ { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
};
@@ -3762,6 +3804,13 @@ static int powered_update_hci(struct hci_dev *hdev)
hci_update_ad(&req);
}
+ if (lmp_le_capable(hdev)) {
+ /* Set random address to static address if configured */
+ if (bacmp(&hdev->static_addr, BDADDR_ANY))
+ hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6,
+ &hdev->static_addr);
+ }
+
if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
u8 adv = 0x01;
OpenPOWER on IntegriCloud