Skip to content

Commit 0d218c3

Browse files
jwrdegoedeVudentz
authored andcommitted
Bluetooth: hci_bcm: Fall back to getting bdaddr from EFI if not set
On some devices the BCM Bluetooth adapter does not have a valid bdaddr set. btbcm.c currently sets HCI_QUIRK_INVALID_BDADDR to indicate when this is the case. But this requires users to manual setup a btaddr, by doing e.g.: btmgmt -i hci0 public-addr 'B0:F1:EC:82:1D:B3' Which means that Bluetooth will not work out of the box on such devices. To avoid this (where possible) hci_bcm sets: HCI_QUIRK_USE_BDADDR_PROPERTY which tries to get the bdaddr from devicetree. But this only works on devicetree platforms. On UEFI based platforms there is a special Broadcom UEFI variable which when present contains the devices bdaddr, just like how there is another UEFI variable which contains wifi nvram contents including the wifi MAC address. Add support for getting the bdaddr from this Broadcom UEFI variable, so that Bluetooth will work OOTB for users on devices where this UEFI variable is present. This fixes Bluetooth not working on for example Asus T100HA 2-in-1s. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
1 parent 3c0d41f commit 0d218c3

File tree

1 file changed

+44
-3
lines changed

1 file changed

+44
-3
lines changed

drivers/bluetooth/btbcm.c

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Copyright (C) 2015 Intel Corporation
77
*/
88

9+
#include <linux/efi.h>
910
#include <linux/module.h>
1011
#include <linux/firmware.h>
1112
#include <linux/dmi.h>
@@ -34,6 +35,43 @@
3435
/* For kmalloc-ing the fw-name array instead of putting it on the stack */
3536
typedef char bcm_fw_name[BCM_FW_NAME_LEN];
3637

38+
#ifdef CONFIG_EFI
39+
static int btbcm_set_bdaddr_from_efi(struct hci_dev *hdev)
40+
{
41+
efi_guid_t guid = EFI_GUID(0x74b00bd9, 0x805a, 0x4d61, 0xb5, 0x1f,
42+
0x43, 0x26, 0x81, 0x23, 0xd1, 0x13);
43+
bdaddr_t efi_bdaddr, bdaddr;
44+
efi_status_t status;
45+
unsigned long len;
46+
int ret;
47+
48+
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
49+
return -EOPNOTSUPP;
50+
51+
len = sizeof(efi_bdaddr);
52+
status = efi.get_variable(L"BDADDR", &guid, NULL, &len, &efi_bdaddr);
53+
if (status != EFI_SUCCESS)
54+
return -ENXIO;
55+
56+
if (len != sizeof(efi_bdaddr))
57+
return -EIO;
58+
59+
baswap(&bdaddr, &efi_bdaddr);
60+
61+
ret = btbcm_set_bdaddr(hdev, &bdaddr);
62+
if (ret)
63+
return ret;
64+
65+
bt_dev_info(hdev, "BCM: Using EFI device address (%pMR)", &bdaddr);
66+
return 0;
67+
}
68+
#else
69+
static int btbcm_set_bdaddr_from_efi(struct hci_dev *hdev)
70+
{
71+
return -EOPNOTSUPP;
72+
}
73+
#endif
74+
3775
int btbcm_check_bdaddr(struct hci_dev *hdev)
3876
{
3977
struct hci_rp_read_bd_addr *bda;
@@ -87,9 +125,12 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
87125
!bacmp(&bda->bdaddr, BDADDR_BCM4345C5) ||
88126
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
89127
!bacmp(&bda->bdaddr, BDADDR_BCM43341B)) {
90-
bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
91-
&bda->bdaddr);
92-
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
128+
/* Try falling back to BDADDR EFI variable */
129+
if (btbcm_set_bdaddr_from_efi(hdev) != 0) {
130+
bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
131+
&bda->bdaddr);
132+
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
133+
}
93134
}
94135

95136
kfree_skb(skb);

0 commit comments

Comments
 (0)