summaryrefslogtreecommitdiff
path: root/net/bluetooth/hci_sync.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2025-04-11 12:37:50 -0400
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2025-05-21 10:28:08 -0400
commite2d471b7806b09744d65a64bcf41337468f2443b (patch)
tree8daa471b0e79df82edfec5c9f059ddacf30132f2 /net/bluetooth/hci_sync.c
parent96ace5519f8ff12644be626b278a02d742b7694c (diff)
Bluetooth: ISO: Fix not using SID from adv report
Up until now it has been assumed that the application would be able to enter the advertising SID in sockaddr_iso_bc.bc_sid, but userspace has no access to SID since the likes of MGMT_EV_DEVICE_FOUND cannot carry it, so it was left unset (0x00) which means it would be unable to synchronize if the broadcast source is using a different SID e.g. 0x04: > HCI Event: LE Meta Event (0x3e) plen 57 LE Extended Advertising Report (0x0d) Num reports: 1 Entry 0 Event type: 0x0000 Props: 0x0000 Data status: Complete Address type: Random (0x01) Address: 0B:82:E8:50:6D:C8 (Non-Resolvable) Primary PHY: LE 1M Secondary PHY: LE 2M SID: 0x04 TX power: 127 dBm RSSI: -55 dBm (0xc9) Periodic advertising interval: 180.00 msec (0x0090) Direct address type: Public (0x00) Direct address: 00:00:00:00:00:00 (OUI 00-00-00) Data length: 0x1f 06 16 52 18 5b 0b e1 05 16 56 18 04 00 11 30 4c ..R.[....V....0L 75 69 7a 27 73 20 53 32 33 20 55 6c 74 72 61 uiz's S23 Ultra Service Data: Broadcast Audio Announcement (0x1852) Broadcast ID: 14748507 (0xe10b5b) Service Data: Public Broadcast Announcement (0x1856) Data[2]: 0400 Unknown EIR field 0x30[16]: 4c75697a27732053323320556c747261 < HCI Command: LE Periodic Advertising Create Sync (0x08|0x0044) plen 14 Options: 0x0000 Use advertising SID, Advertiser Address Type and address Reporting initially enabled SID: 0x00 (<- Invalid) Adv address type: Random (0x01) Adv address: 0B:82:E8:50:6D:C8 (Non-Resolvable) Skip: 0x0000 Sync timeout: 20000 msec (0x07d0) Sync CTE type: 0x0000 So instead this changes now allow application to set HCI_SID_INVALID which will make hci_le_pa_create_sync to wait for a report, update the conn->sid using the report SID and only then issue PA create sync command: < HCI Command: LE Periodic Advertising Create Sync Options: 0x0000 Use advertising SID, Advertiser Address Type and address Reporting initially enabled SID: 0x04 Adv address type: Random (0x01) Adv address: 0B:82:E8:50:6D:C8 (Non-Resolvable) Skip: 0x0000 Sync timeout: 20000 msec (0x07d0) Sync CTE type: 0x0000 > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) Status: Success (0x00) Sync handle: 64 Advertising SID: 0x04 Advertiser address type: Random (0x01) Advertiser address: 0B:82:E8:50:6D:C8 (Non-Resolvable) Advertiser PHY: LE 2M (0x02) Periodic advertising interval: 180.00 msec (0x0090) Advertiser clock accuracy: 0x05 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'net/bluetooth/hci_sync.c')
-rw-r--r--net/bluetooth/hci_sync.c49
1 files changed, 44 insertions, 5 deletions
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index e56b1cbedab9..d00ff18f3be0 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -6898,20 +6898,37 @@ int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
{
+ struct hci_conn *conn = data;
+ struct hci_conn *pa_sync;
+
bt_dev_dbg(hdev, "err %d", err);
- if (!err)
+ if (err == -ECANCELED)
return;
+ hci_dev_lock(hdev);
+
hci_dev_clear_flag(hdev, HCI_PA_SYNC);
- if (err == -ECANCELED)
- return;
+ if (!hci_conn_valid(hdev, conn))
+ clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
- hci_dev_lock(hdev);
+ if (!err)
+ goto unlock;
- hci_update_passive_scan_sync(hdev);
+ /* Add connection to indicate PA sync error */
+ pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
+ HCI_ROLE_SLAVE);
+ if (IS_ERR(pa_sync))
+ goto unlock;
+
+ set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
+
+ /* Notify iso layer */
+ hci_connect_cfm(pa_sync, bt_status(err));
+
+unlock:
hci_dev_unlock(hdev);
}
@@ -6925,9 +6942,23 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
if (!hci_conn_valid(hdev, conn))
return -ECANCELED;
+ if (conn->sync_handle != HCI_SYNC_HANDLE_INVALID)
+ return -EINVAL;
+
if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC))
return -EBUSY;
+ /* Stop scanning if SID has not been set and active scanning is enabled
+ * so we use passive scanning which will be scanning using the allow
+ * list programmed to contain only the connection address.
+ */
+ if (conn->sid == HCI_SID_INVALID &&
+ hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
+ hci_scan_disable_sync(hdev);
+ hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED);
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ }
+
/* Mark HCI_CONN_CREATE_PA_SYNC so hci_update_passive_scan_sync can
* program the address in the allow list so PA advertisements can be
* received.
@@ -6936,6 +6967,14 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
hci_update_passive_scan_sync(hdev);
+ /* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update
+ * it.
+ */
+ if (conn->sid == HCI_SID_INVALID)
+ __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL,
+ HCI_EV_LE_EXT_ADV_REPORT,
+ conn->conn_timeout, NULL);
+
memset(&cp, 0, sizeof(cp));
cp.options = qos->bcast.options;
cp.sid = conn->sid;