Bluetooth: Allow scannable adv with extended MGMT APIs
authorDaniel Winkler <danielwinkler@google.com>
Wed, 3 Mar 2021 19:15:23 +0000 (11:15 -0800)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 3 Mar 2021 17:14:38 +0000 (18:14 +0100)
An issue was found, where if a bluetooth client requests a broadcast
advertisement with scan response data, it will not be properly
registered with the controller. This is because at the time that the
hci_cp_le_set_scan_param structure is created, the scan response will
not yet have been received since it comes in a second MGMT call. With
empty scan response, the request defaults to a non-scannable PDU type.
On some controllers, the subsequent scan response request will fail due
to incorrect PDU type, and others will succeed and not use the scan
response.

This fix allows the advertising parameters MGMT call to include a flag
to let the kernel know whether a scan response will be coming, so that
the correct PDU type is used in the first place. A bluetoothd change is
also incoming to take advantage of it.

To test this, I created a broadcast advertisement with scan response
data and registered it on the hatch chromebook. Without this change, the
request fails, and with it will succeed.

Reviewed-by: Alain Michaud <alainm@chromium.org>
Reviewed-by: Sonny Sasaka <sonnysasaka@chromium.org>
Reviewed-by: Miao-chen Chou <mcchou@chromium.org>
Signed-off-by: Daniel Winkler <danielwinkler@google.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/mgmt.h
net/bluetooth/hci_request.c
net/bluetooth/mgmt.c

index 839a2028009ea12a5bf277cdb5143dc5f41172df..a7cffb069565174eb4be22d7c530f10a2b316e52 100644 (file)
@@ -578,6 +578,7 @@ struct mgmt_rp_add_advertising {
 #define MGMT_ADV_PARAM_TIMEOUT         BIT(13)
 #define MGMT_ADV_PARAM_INTERVALS       BIT(14)
 #define MGMT_ADV_PARAM_TX_POWER                BIT(15)
+#define MGMT_ADV_PARAM_SCAN_RSP                BIT(16)
 
 #define MGMT_ADV_FLAG_SEC_MASK (MGMT_ADV_FLAG_SEC_1M | MGMT_ADV_FLAG_SEC_2M | \
                                 MGMT_ADV_FLAG_SEC_CODED)
index 75a42178c82d9bb5e035abb4600b7e5f8e668b39..d7ee11ef70d3e1f547cd66d894870c5b4e1f7b7d 100644 (file)
@@ -2180,7 +2180,8 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
                        cp.evt_properties = cpu_to_le16(LE_EXT_ADV_CONN_IND);
                else
                        cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);
-       } else if (adv_instance_is_scannable(hdev, instance)) {
+       } else if (adv_instance_is_scannable(hdev, instance) ||
+                  (flags & MGMT_ADV_PARAM_SCAN_RSP)) {
                if (secondary_adv)
                        cp.evt_properties = cpu_to_le16(LE_EXT_ADV_SCAN_IND);
                else
index 74971b4bd4570db34b87a26602c25743cb84e4cd..90334ac4a135897360c212aac35cdcb5a1574bbf 100644 (file)
@@ -7432,6 +7432,7 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
        flags |= MGMT_ADV_PARAM_TIMEOUT;
        flags |= MGMT_ADV_PARAM_INTERVALS;
        flags |= MGMT_ADV_PARAM_TX_POWER;
+       flags |= MGMT_ADV_PARAM_SCAN_RSP;
 
        /* In extended adv TX_POWER returned from Set Adv Param
         * will be always valid.