Bluetooth: Fix controller configuration with HCI_QUIRK_INVALID_BDADDR
authorMarcel Holtmann <marcel@holtmann.org>
Tue, 23 Dec 2014 22:10:48 +0000 (23:10 +0100)
committerJohan Hedberg <johan.hedberg@intel.com>
Wed, 24 Dec 2014 18:35:46 +0000 (20:35 +0200)
When controllers set the HCI_QUIRK_INVALID_BDADDR flag, it is required
by userspace to program a valid public Bluetooth device address into
the controller before it can be used.

After successful address configuration, the internal state changes and
the controller runs the complete initialization procedure. However one
small difference is that this is no longer the HCI_SETUP stage. The
HCI_SETUP stage is only valid during initial controller setup. In this
case the stack runs the initialization as part of the HCI_CONFIG stage.

The controller version information, default name and supported commands
are only stored during HCI_SETUP. While these information are static,
they are not read initially when HCI_QUIRK_INVALID_BDADDR is set. So
when running in HCI_CONFIG state, these information need to be updated
as well.

This especially impacts Bluetooth 4.1 and later controllers using
extended feature pages and second event mask page.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Cc: stable@vger.kernel.org # 3.17+
net/bluetooth/hci_event.c

index 39a5c8a017263694f1dbdca7888abd700c12952b..c03d4b09caa30011a84a0a278985f476d432c28f 100644 (file)
@@ -242,7 +242,8 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
        if (rp->status)
                return;
 
-       if (test_bit(HCI_SETUP, &hdev->dev_flags))
+       if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
+           test_bit(HCI_CONFIG, &hdev->dev_flags))
                memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
 }
 
@@ -509,7 +510,8 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
        if (rp->status)
                return;
 
-       if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
+       if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
+           test_bit(HCI_CONFIG, &hdev->dev_flags)) {
                hdev->hci_ver = rp->hci_ver;
                hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
                hdev->lmp_ver = rp->lmp_ver;
@@ -528,7 +530,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
        if (rp->status)
                return;
 
-       if (test_bit(HCI_SETUP, &hdev->dev_flags))
+       if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
+           test_bit(HCI_CONFIG, &hdev->dev_flags))
                memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
 }