Skip to content

Commit 7a0e5b1

Browse files
Matthias Kaehlckeholtmann
authored andcommitted
Bluetooth: Add quirk for reading BD_ADDR from fwnode property
Add HCI_QUIRK_USE_BDADDR_PROPERTY to allow controllers to retrieve the public Bluetooth address from the firmware node property 'local-bd-address'. If quirk is set and the property does not exist or is invalid the controller is marked as unconfigured. Signed-off-by: Matthias Kaehlcke <mka@chromium.org> Reviewed-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Tested-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 parent 56897b2 commit 7a0e5b1

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

include/net/bluetooth/hci.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ enum {
158158
*/
159159
HCI_QUIRK_INVALID_BDADDR,
160160

161+
/* When this quirk is set, the public Bluetooth address
162+
* initially reported by HCI Read BD Address command
163+
* is considered invalid. The public BD Address can be
164+
* specified in the fwnode property 'local-bd-address'.
165+
* If this property does not exist or is invalid controller
166+
* configuration is required before this device can be used.
167+
*
168+
* This quirk can be set before hci_register_dev is called or
169+
* during the hdev->setup vendor callback.
170+
*/
171+
HCI_QUIRK_USE_BDADDR_PROPERTY,
172+
161173
/* When this quirk is set, the duplicate filtering during
162174
* scanning is based on Bluetooth devices addresses. To allow
163175
* RSSI based updates, restart scanning if needed.

net/bluetooth/hci_core.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/rfkill.h>
3131
#include <linux/debugfs.h>
3232
#include <linux/crypto.h>
33+
#include <linux/property.h>
3334
#include <asm/unaligned.h>
3435

3536
#include <net/bluetooth/bluetooth.h>
@@ -1355,6 +1356,32 @@ int hci_inquiry(void __user *arg)
13551356
return err;
13561357
}
13571358

1359+
/**
1360+
* hci_dev_get_bd_addr_from_property - Get the Bluetooth Device Address
1361+
* (BD_ADDR) for a HCI device from
1362+
* a firmware node property.
1363+
* @hdev: The HCI device
1364+
*
1365+
* Search the firmware node for 'local-bd-address'.
1366+
*
1367+
* All-zero BD addresses are rejected, because those could be properties
1368+
* that exist in the firmware tables, but were not updated by the firmware. For
1369+
* example, the DTS could define 'local-bd-address', with zero BD addresses.
1370+
*/
1371+
static void hci_dev_get_bd_addr_from_property(struct hci_dev *hdev)
1372+
{
1373+
struct fwnode_handle *fwnode = dev_fwnode(hdev->dev.parent);
1374+
bdaddr_t ba;
1375+
int ret;
1376+
1377+
ret = fwnode_property_read_u8_array(fwnode, "local-bd-address",
1378+
(u8 *)&ba, sizeof(ba));
1379+
if (ret < 0 || !bacmp(&ba, BDADDR_ANY))
1380+
return;
1381+
1382+
bacpy(&hdev->public_addr, &ba);
1383+
}
1384+
13581385
static int hci_dev_do_open(struct hci_dev *hdev)
13591386
{
13601387
int ret = 0;
@@ -1422,6 +1449,22 @@ static int hci_dev_do_open(struct hci_dev *hdev)
14221449
if (hdev->setup)
14231450
ret = hdev->setup(hdev);
14241451

1452+
if (ret)
1453+
goto setup_failed;
1454+
1455+
if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) {
1456+
if (!bacmp(&hdev->public_addr, BDADDR_ANY))
1457+
hci_dev_get_bd_addr_from_property(hdev);
1458+
1459+
if (bacmp(&hdev->public_addr, BDADDR_ANY) &&
1460+
hdev->set_bdaddr)
1461+
ret = hdev->set_bdaddr(hdev,
1462+
&hdev->public_addr);
1463+
else
1464+
ret = -EADDRNOTAVAIL;
1465+
}
1466+
1467+
setup_failed:
14251468
/* The transport driver can set these quirks before
14261469
* creating the HCI device or in its setup callback.
14271470
*

net/bluetooth/mgmt.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,8 @@ static bool is_configured(struct hci_dev *hdev)
549549
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
550550
return false;
551551

552-
if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
552+
if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
553+
test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
553554
!bacmp(&hdev->public_addr, BDADDR_ANY))
554555
return false;
555556

@@ -564,7 +565,8 @@ static __le32 get_missing_options(struct hci_dev *hdev)
564565
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
565566
options |= MGMT_OPTION_EXTERNAL_CONFIG;
566567

567-
if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
568+
if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
569+
test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
568570
!bacmp(&hdev->public_addr, BDADDR_ANY))
569571
options |= MGMT_OPTION_PUBLIC_ADDRESS;
570572

0 commit comments

Comments
 (0)