aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-07-04 10:54:37 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2014-07-04 11:09:32 -0400
commit89bc22d23f63c2d437f677d7eae0fa922bedcdcb (patch)
tree2c797d8fe591af18be6f453abcfa2c14b74ead1a
parent118305b50a73b46ff6c1c0453d7ae642b26dff82 (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>
-rw-r--r--include/net/bluetooth/hci.h10
-rw-r--r--net/bluetooth/hci_core.c6
-rw-r--r--net/bluetooth/mgmt.c21
3 files changed, 32 insertions, 5 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 744713cd5335..148b21699446 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -110,6 +110,16 @@ enum {
110 * This quirk must be set before hci_register_dev is called. 110 * This quirk must be set before hci_register_dev is called.
111 */ 111 */
112 HCI_QUIRK_BROKEN_STORED_LINK_KEY, 112 HCI_QUIRK_BROKEN_STORED_LINK_KEY,
113
114 /* When this quirk is set, the public Bluetooth address
115 * initially reported by HCI Read BD Address command
116 * is considered invalid. Controller configuration is
117 * required before this device can be used.
118 *
119 * This quirk can be set before hci_register_dev is called or
120 * during the hdev->setup vendor callback.
121 */
122 HCI_QUIRK_INVALID_BDADDR,
113}; 123};
114 124
115/* HCI device flags */ 125/* HCI device flags */
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)
2246 atomic_set(&hdev->cmd_cnt, 1); 2246 atomic_set(&hdev->cmd_cnt, 1);
2247 set_bit(HCI_INIT, &hdev->flags); 2247 set_bit(HCI_INIT, &hdev->flags);
2248 2248
2249 if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags)) 2249 if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags)) {
2250 ret = hdev->setup(hdev); 2250 ret = hdev->setup(hdev);
2251 2251
2252 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks))
2253 set_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
2254 }
2255
2252 /* If public address change is configured, ensure that the 2256 /* If public address change is configured, ensure that the
2253 * address gets programmed. If the driver does not support 2257 * address gets programmed. If the driver does not support
2254 * changing the public address, fail the power on procedure. 2258 * 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,
441 return err; 441 return err;
442} 442}
443 443
444static __le32 get_missing_options(struct hci_dev *hdev)
445{
446 u32 options = 0;
447
448 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
449 !bacmp(&hdev->public_addr, BDADDR_ANY))
450 options |= MGMT_OPTION_PUBLIC_ADDRESS;
451
452 return cpu_to_le32(options);
453}
454
444static int read_config_info(struct sock *sk, struct hci_dev *hdev, 455static int read_config_info(struct sock *sk, struct hci_dev *hdev,
445 void *data, u16 data_len) 456 void *data, u16 data_len)
446{ 457{
447 struct mgmt_rp_read_config_info rp; 458 struct mgmt_rp_read_config_info rp;
459 u32 options = 0;
448 460
449 BT_DBG("sock %p %s", sk, hdev->name); 461 BT_DBG("sock %p %s", sk, hdev->name);
450 462
@@ -452,11 +464,12 @@ static int read_config_info(struct sock *sk, struct hci_dev *hdev,
452 464
453 memset(&rp, 0, sizeof(rp)); 465 memset(&rp, 0, sizeof(rp));
454 rp.manufacturer = cpu_to_le16(hdev->manufacturer); 466 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
467
455 if (hdev->set_bdaddr) 468 if (hdev->set_bdaddr)
456 rp.supported_options = cpu_to_le32(MGMT_OPTION_PUBLIC_ADDRESS); 469 options |= MGMT_OPTION_PUBLIC_ADDRESS;
457 else 470
458 rp.supported_options = cpu_to_le32(0); 471 rp.supported_options = cpu_to_le32(options);
459 rp.missing_options = cpu_to_le32(0); 472 rp.missing_options = get_missing_options(hdev);
460 473
461 hci_dev_unlock(hdev); 474 hci_dev_unlock(hdev);
462 475