Bluetooth: Track the current configured random address
authorMarcel Holtmann <marcel@holtmann.org>
Thu, 20 Feb 2014 03:52:13 +0000 (19:52 -0800)
committerJohan Hedberg <johan.hedberg@intel.com>
Thu, 20 Feb 2014 06:28:04 +0000 (08:28 +0200)
For Bluetooth controllers with LE support, track the value of the
currently configured random address. It is important to know what
the current random address is to avoid unneeded attempts to set
a new address. This will become important when introducing the
LE privacy support in the future.

In addition expose the current configured random address via
debugfs for debugging purposes.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c

index 3be2905010cd9dc3efbb5ed6f9177d095429d8d5..3a8e22e9b25d48fbab72332616cb9cda42c8d282 100644 (file)
@@ -151,6 +151,7 @@ struct hci_dev {
        __u8            bus;
        __u8            dev_type;
        bdaddr_t        bdaddr;
+       bdaddr_t        random_addr;
        bdaddr_t        static_addr;
        __u8            own_addr_type;
        __u8            dev_name[HCI_MAX_NAME_LENGTH];
index b25a36c3064b7f7f2e1e41be41664425585b80b4..877330b4876faef29aa988b4b8340b3ae0572ef6 100644 (file)
@@ -548,6 +548,29 @@ static int sniff_max_interval_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get,
                        sniff_max_interval_set, "%llu\n");
 
+static int random_address_show(struct seq_file *f, void *p)
+{
+       struct hci_dev *hdev = f->private;
+
+       hci_dev_lock(hdev);
+       seq_printf(f, "%pMR\n", &hdev->random_addr);
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+static int random_address_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, random_address_show, inode->i_private);
+}
+
+static const struct file_operations random_address_fops = {
+       .open           = random_address_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int static_address_show(struct seq_file *f, void *p)
 {
        struct hci_dev *hdev = f->private;
@@ -1557,6 +1580,8 @@ static int __hci_init(struct hci_dev *hdev)
        }
 
        if (lmp_le_capable(hdev)) {
+               debugfs_create_file("random_address", 0444, hdev->debugfs,
+                                   hdev, &random_address_fops);
                debugfs_create_file("static_address", 0444, hdev->debugfs,
                                    hdev, &static_address_fops);
 
@@ -2205,6 +2230,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
        memset(hdev->eir, 0, sizeof(hdev->eir));
        memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
+       bacpy(&hdev->random_addr, BDADDR_ANY);
 
        hci_req_unlock(hdev);
 
index 7228fa100b1f1a8279ca3194a199de51d4265cba..4327b129d38e2d4d7c6d92f3d274538ecf3fa6ea 100644 (file)
@@ -959,6 +959,26 @@ static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
        hci_dev_unlock(hdev);
 }
 
+
+static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       __u8 status = *((__u8 *) skb->data);
+       bdaddr_t *sent;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
+       if (!sent)
+               return;
+
+       hci_dev_lock(hdev);
+
+       if (!status)
+               bacpy(&hdev->random_addr, sent);
+
+       hci_dev_unlock(hdev);
+}
+
 static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 *sent, status = *((__u8 *) skb->data);
@@ -2308,6 +2328,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_user_passkey_neg_reply(hdev, skb);
                break;
 
+       case HCI_OP_LE_SET_RANDOM_ADDR:
+               hci_cc_le_set_random_addr(hdev, skb);
+               break;
+
        case HCI_OP_LE_SET_ADV_ENABLE:
                hci_cc_le_set_adv_enable(hdev, skb);
                break;