Skip to content

Commit e2d471b

Browse files
committed
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 <[email protected]>
1 parent 96ace55 commit e2d471b

File tree

5 files changed

+75
-14
lines changed

5 files changed

+75
-14
lines changed

net/bluetooth/hci_conn.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,6 +2070,8 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
20702070
{
20712071
struct hci_conn *conn;
20722072

2073+
bt_dev_dbg(hdev, "dst %pMR type %d sid %d", dst, dst_type, sid);
2074+
20732075
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE);
20742076
if (IS_ERR(conn))
20752077
return conn;

net/bluetooth/hci_core.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4068,19 +4068,20 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
40684068
return;
40694069
}
40704070

4071-
err = hci_send_frame(hdev, skb);
4072-
if (err < 0) {
4073-
hci_cmd_sync_cancel_sync(hdev, -err);
4074-
return;
4071+
if (hci_skb_opcode(skb) != HCI_OP_NOP) {
4072+
err = hci_send_frame(hdev, skb);
4073+
if (err < 0) {
4074+
hci_cmd_sync_cancel_sync(hdev, -err);
4075+
return;
4076+
}
4077+
atomic_dec(&hdev->cmd_cnt);
40754078
}
40764079

40774080
if (hdev->req_status == HCI_REQ_PEND &&
40784081
!hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) {
40794082
kfree_skb(hdev->req_skb);
40804083
hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
40814084
}
4082-
4083-
atomic_dec(&hdev->cmd_cnt);
40844085
}
40854086

40864087
static void hci_cmd_work(struct work_struct *work)

net/bluetooth/hci_event.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6351,6 +6351,17 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
63516351
info->secondary_phy &= 0x1f;
63526352
}
63536353

6354+
/* Check if PA Sync is pending and if the hci_conn SID has not
6355+
* been set update it.
6356+
*/
6357+
if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) {
6358+
struct hci_conn *conn;
6359+
6360+
conn = hci_conn_hash_lookup_create_pa_sync(hdev);
6361+
if (conn && conn->sid == HCI_SID_INVALID)
6362+
conn->sid = info->sid;
6363+
}
6364+
63546365
if (legacy_evt_type != LE_ADV_INVALID) {
63556366
process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
63566367
info->bdaddr_type, NULL, 0,
@@ -7155,7 +7166,8 @@ static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
71557166

71567167
/* Only match event if command OGF is for LE */
71577168
if (hdev->req_skb &&
7158-
hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) == 0x08 &&
7169+
(hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) == 0x08 ||
7170+
hci_skb_opcode(hdev->req_skb) == HCI_OP_NOP) &&
71597171
hci_skb_event(hdev->req_skb) == ev->subevent) {
71607172
*opcode = hci_skb_opcode(hdev->req_skb);
71617173
hci_req_cmd_complete(hdev, *opcode, 0x00, req_complete,
@@ -7511,8 +7523,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
75117523
goto done;
75127524
}
75137525

7526+
hci_dev_lock(hdev);
75147527
kfree_skb(hdev->recv_event);
75157528
hdev->recv_event = skb_clone(skb, GFP_KERNEL);
7529+
hci_dev_unlock(hdev);
75167530

75177531
event = hdr->evt;
75187532
if (!event) {

net/bluetooth/hci_sync.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6898,20 +6898,37 @@ int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
68986898

68996899
static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
69006900
{
6901+
struct hci_conn *conn = data;
6902+
struct hci_conn *pa_sync;
6903+
69016904
bt_dev_dbg(hdev, "err %d", err);
69026905

6903-
if (!err)
6906+
if (err == -ECANCELED)
69046907
return;
69056908

6909+
hci_dev_lock(hdev);
6910+
69066911
hci_dev_clear_flag(hdev, HCI_PA_SYNC);
69076912

6908-
if (err == -ECANCELED)
6909-
return;
6913+
if (!hci_conn_valid(hdev, conn))
6914+
clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
69106915

6911-
hci_dev_lock(hdev);
6916+
if (!err)
6917+
goto unlock;
69126918

6913-
hci_update_passive_scan_sync(hdev);
6919+
/* Add connection to indicate PA sync error */
6920+
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
6921+
HCI_ROLE_SLAVE);
69146922

6923+
if (IS_ERR(pa_sync))
6924+
goto unlock;
6925+
6926+
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
6927+
6928+
/* Notify iso layer */
6929+
hci_connect_cfm(pa_sync, bt_status(err));
6930+
6931+
unlock:
69156932
hci_dev_unlock(hdev);
69166933
}
69176934

@@ -6925,9 +6942,23 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
69256942
if (!hci_conn_valid(hdev, conn))
69266943
return -ECANCELED;
69276944

6945+
if (conn->sync_handle != HCI_SYNC_HANDLE_INVALID)
6946+
return -EINVAL;
6947+
69286948
if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC))
69296949
return -EBUSY;
69306950

6951+
/* Stop scanning if SID has not been set and active scanning is enabled
6952+
* so we use passive scanning which will be scanning using the allow
6953+
* list programmed to contain only the connection address.
6954+
*/
6955+
if (conn->sid == HCI_SID_INVALID &&
6956+
hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
6957+
hci_scan_disable_sync(hdev);
6958+
hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED);
6959+
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
6960+
}
6961+
69316962
/* Mark HCI_CONN_CREATE_PA_SYNC so hci_update_passive_scan_sync can
69326963
* program the address in the allow list so PA advertisements can be
69336964
* received.
@@ -6936,6 +6967,14 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
69366967

69376968
hci_update_passive_scan_sync(hdev);
69386969

6970+
/* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update
6971+
* it.
6972+
*/
6973+
if (conn->sid == HCI_SID_INVALID)
6974+
__hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL,
6975+
HCI_EV_LE_EXT_ADV_REPORT,
6976+
conn->conn_timeout, NULL);
6977+
69396978
memset(&cp, 0, sizeof(cp));
69406979
cp.options = qos->bcast.options;
69416980
cp.sid = conn->sid;

net/bluetooth/iso.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
941941

942942
iso_pi(sk)->dst_type = sa->iso_bc->bc_bdaddr_type;
943943

944-
if (sa->iso_bc->bc_sid > 0x0f)
944+
if (sa->iso_bc->bc_sid > 0x0f && sa->iso_bc->bc_sid != HCI_SID_INVALID)
945945
return -EINVAL;
946946

947947
iso_pi(sk)->bc_sid = sa->iso_bc->bc_sid;
@@ -2029,6 +2029,9 @@ static bool iso_match_sid(struct sock *sk, void *data)
20292029
{
20302030
struct hci_ev_le_pa_sync_established *ev = data;
20312031

2032+
if (iso_pi(sk)->bc_sid == HCI_SID_INVALID)
2033+
return true;
2034+
20322035
return ev->sid == iso_pi(sk)->bc_sid;
20332036
}
20342037

@@ -2075,8 +2078,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
20752078
if (ev1) {
20762079
sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
20772080
iso_match_sid, ev1);
2078-
if (sk && !ev1->status)
2081+
if (sk && !ev1->status) {
20792082
iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle);
2083+
iso_pi(sk)->bc_sid = ev1->sid;
2084+
}
20802085

20812086
goto done;
20822087
}

0 commit comments

Comments
 (0)