diff options
author | Marcel Holtmann | 2014-07-04 16:54:37 +0200 |
---|---|---|
committer | Johan Hedberg | 2014-07-04 18:09:32 +0300 |
commit | 89bc22d23f63c2d437f677d7eae0fa922bedcdcb (patch) | |
tree | 2c797d8fe591af18be6f453abcfa2c14b74ead1a /net/bluetooth | |
parent | 118305b50a73b46ff6c1c0453d7ae642b26dff82 (diff) |
Bluetooth: Add quirk for invalid controller address setting
When a Bluetooth controller does not have a valid public Bluetooth
address, then allow the driver to indicate this. If the quirk is
set, the Bluetooth core will switch to unconfigured state first
and will allow userspace to configure the address before starting
the full initialization of the controller.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_core.c | 6 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 21 |
2 files changed, 22 insertions, 5 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 038b4748375b..c92bee84413f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2246,9 +2246,13 @@ static int hci_dev_do_open(struct hci_dev *hdev) atomic_set(&hdev->cmd_cnt, 1); set_bit(HCI_INIT, &hdev->flags); - if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags)) + if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags)) { ret = hdev->setup(hdev); + if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks)) + set_bit(HCI_UNCONFIGURED, &hdev->dev_flags); + } + /* If public address change is configured, ensure that the * address gets programmed. If the driver does not support * changing the public address, fail the power on procedure. diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 90eabcae3ed2..c7e5d4651021 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -441,10 +441,22 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, return err; } +static __le32 get_missing_options(struct hci_dev *hdev) +{ + u32 options = 0; + + if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) && + !bacmp(&hdev->public_addr, BDADDR_ANY)) + options |= MGMT_OPTION_PUBLIC_ADDRESS; + + return cpu_to_le32(options); +} + static int read_config_info(struct sock *sk, struct hci_dev *hdev, void *data, u16 data_len) { struct mgmt_rp_read_config_info rp; + u32 options = 0; BT_DBG("sock %p %s", sk, hdev->name); @@ -452,11 +464,12 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev, memset(&rp, 0, sizeof(rp)); rp.manufacturer = cpu_to_le16(hdev->manufacturer); + if (hdev->set_bdaddr) - rp.supported_options = cpu_to_le32(MGMT_OPTION_PUBLIC_ADDRESS); - else - rp.supported_options = cpu_to_le32(0); - rp.missing_options = cpu_to_le32(0); + options |= MGMT_OPTION_PUBLIC_ADDRESS; + + rp.supported_options = cpu_to_le32(options); + rp.missing_options = get_missing_options(hdev); hci_dev_unlock(hdev); |