mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
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>
This commit is contained in:
parent
56897b217a
commit
7a0e5b15ca
@ -158,6 +158,18 @@ enum {
|
|||||||
*/
|
*/
|
||||||
HCI_QUIRK_INVALID_BDADDR,
|
HCI_QUIRK_INVALID_BDADDR,
|
||||||
|
|
||||||
|
/* When this quirk is set, the public Bluetooth address
|
||||||
|
* initially reported by HCI Read BD Address command
|
||||||
|
* is considered invalid. The public BD Address can be
|
||||||
|
* specified in the fwnode property 'local-bd-address'.
|
||||||
|
* If this property does not exist or is invalid controller
|
||||||
|
* configuration is required before this device can be used.
|
||||||
|
*
|
||||||
|
* This quirk can be set before hci_register_dev is called or
|
||||||
|
* during the hdev->setup vendor callback.
|
||||||
|
*/
|
||||||
|
HCI_QUIRK_USE_BDADDR_PROPERTY,
|
||||||
|
|
||||||
/* When this quirk is set, the duplicate filtering during
|
/* When this quirk is set, the duplicate filtering during
|
||||||
* scanning is based on Bluetooth devices addresses. To allow
|
* scanning is based on Bluetooth devices addresses. To allow
|
||||||
* RSSI based updates, restart scanning if needed.
|
* RSSI based updates, restart scanning if needed.
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <linux/rfkill.h>
|
#include <linux/rfkill.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
@ -1355,6 +1356,32 @@ done:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hci_dev_get_bd_addr_from_property - Get the Bluetooth Device Address
|
||||||
|
* (BD_ADDR) for a HCI device from
|
||||||
|
* a firmware node property.
|
||||||
|
* @hdev: The HCI device
|
||||||
|
*
|
||||||
|
* Search the firmware node for 'local-bd-address'.
|
||||||
|
*
|
||||||
|
* All-zero BD addresses are rejected, because those could be properties
|
||||||
|
* that exist in the firmware tables, but were not updated by the firmware. For
|
||||||
|
* example, the DTS could define 'local-bd-address', with zero BD addresses.
|
||||||
|
*/
|
||||||
|
static void hci_dev_get_bd_addr_from_property(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct fwnode_handle *fwnode = dev_fwnode(hdev->dev.parent);
|
||||||
|
bdaddr_t ba;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = fwnode_property_read_u8_array(fwnode, "local-bd-address",
|
||||||
|
(u8 *)&ba, sizeof(ba));
|
||||||
|
if (ret < 0 || !bacmp(&ba, BDADDR_ANY))
|
||||||
|
return;
|
||||||
|
|
||||||
|
bacpy(&hdev->public_addr, &ba);
|
||||||
|
}
|
||||||
|
|
||||||
static int hci_dev_do_open(struct hci_dev *hdev)
|
static int hci_dev_do_open(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -1422,6 +1449,22 @@ static int hci_dev_do_open(struct hci_dev *hdev)
|
|||||||
if (hdev->setup)
|
if (hdev->setup)
|
||||||
ret = hdev->setup(hdev);
|
ret = hdev->setup(hdev);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
goto setup_failed;
|
||||||
|
|
||||||
|
if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) {
|
||||||
|
if (!bacmp(&hdev->public_addr, BDADDR_ANY))
|
||||||
|
hci_dev_get_bd_addr_from_property(hdev);
|
||||||
|
|
||||||
|
if (bacmp(&hdev->public_addr, BDADDR_ANY) &&
|
||||||
|
hdev->set_bdaddr)
|
||||||
|
ret = hdev->set_bdaddr(hdev,
|
||||||
|
&hdev->public_addr);
|
||||||
|
else
|
||||||
|
ret = -EADDRNOTAVAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_failed:
|
||||||
/* The transport driver can set these quirks before
|
/* The transport driver can set these quirks before
|
||||||
* creating the HCI device or in its setup callback.
|
* creating the HCI device or in its setup callback.
|
||||||
*
|
*
|
||||||
|
@ -549,7 +549,8 @@ static bool is_configured(struct hci_dev *hdev)
|
|||||||
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
|
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
|
if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
|
||||||
|
test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
|
||||||
!bacmp(&hdev->public_addr, BDADDR_ANY))
|
!bacmp(&hdev->public_addr, BDADDR_ANY))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -564,7 +565,8 @@ static __le32 get_missing_options(struct hci_dev *hdev)
|
|||||||
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
|
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
|
||||||
options |= MGMT_OPTION_EXTERNAL_CONFIG;
|
options |= MGMT_OPTION_EXTERNAL_CONFIG;
|
||||||
|
|
||||||
if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
|
if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
|
||||||
|
test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
|
||||||
!bacmp(&hdev->public_addr, BDADDR_ANY))
|
!bacmp(&hdev->public_addr, BDADDR_ANY))
|
||||||
options |= MGMT_OPTION_PUBLIC_ADDRESS;
|
options |= MGMT_OPTION_PUBLIC_ADDRESS;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user