Skip to content

Commit d356c92

Browse files
iulia-tanasescuVudentz
authored andcommitted
Bluetooth: ISO: Handle PA sync when no BIGInfo reports are generated
In case of a Broadcast Source that has PA enabled but no active BIG, a Broadcast Sink needs to establish PA sync and parse BASE from PA reports. This commit moves the allocation of a PA sync hcon from the BIGInfo advertising report event to the PA sync established event. After the first complete PA report, the hcon is notified to the ISO layer. A child socket is allocated and enqueued in the parent's accept queue. BIGInfo reports also need to be processed, to extract the encryption field and inform userspace. After the first BIGInfo report is received, the PA sync hcon is notified again to the ISO layer. Since a socket will be found this time, the socket state will transition to BT_CONNECTED and the userspace will be woken up using sk_state_change. Signed-off-by: Iulia Tanasescu <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 311527e commit d356c92

File tree

3 files changed

+74
-81
lines changed

3 files changed

+74
-81
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,8 +1373,7 @@ hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle)
13731373
rcu_read_lock();
13741374

13751375
list_for_each_entry_rcu(c, &h->list, list) {
1376-
if (c->type != ISO_LINK ||
1377-
!test_bit(HCI_CONN_PA_SYNC, &c->flags))
1376+
if (c->type != ISO_LINK)
13781377
continue;
13791378

13801379
if (c->sync_handle == sync_handle) {

net/bluetooth/hci_event.c

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
BlueZ - Bluetooth protocol stack for Linux
33
Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
4-
Copyright 2023 NXP
4+
Copyright 2023-2024 NXP
55
66
Written 2000,2001 by Maxim Krasnyansky <[email protected]>
77
@@ -6492,14 +6492,16 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
64926492
if (!(flags & HCI_PROTO_DEFER))
64936493
goto unlock;
64946494

6495-
if (ev->status) {
6496-
/* Add connection to indicate the failed PA sync event */
6497-
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
6498-
HCI_ROLE_SLAVE);
6495+
/* Add connection to indicate PA sync event */
6496+
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
6497+
HCI_ROLE_SLAVE);
64996498

6500-
if (!pa_sync)
6501-
goto unlock;
6499+
if (!pa_sync)
6500+
goto unlock;
6501+
6502+
pa_sync->sync_handle = le16_to_cpu(ev->handle);
65026503

6504+
if (ev->status) {
65036505
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
65046506

65056507
/* Notify iso layer */
@@ -6516,15 +6518,36 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
65166518
struct hci_ev_le_per_adv_report *ev = data;
65176519
int mask = hdev->link_mode;
65186520
__u8 flags = 0;
6521+
struct hci_conn *pa_sync;
65196522

65206523
bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle));
65216524

65226525
hci_dev_lock(hdev);
65236526

65246527
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
65256528
if (!(mask & HCI_LM_ACCEPT))
6526-
hci_le_pa_term_sync(hdev, ev->sync_handle);
6529+
goto unlock;
65276530

6531+
if (!(flags & HCI_PROTO_DEFER))
6532+
goto unlock;
6533+
6534+
pa_sync = hci_conn_hash_lookup_pa_sync_handle
6535+
(hdev,
6536+
le16_to_cpu(ev->sync_handle));
6537+
6538+
if (!pa_sync)
6539+
goto unlock;
6540+
6541+
if (ev->data_status == LE_PA_DATA_COMPLETE &&
6542+
!test_and_set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags)) {
6543+
/* Notify iso layer */
6544+
hci_connect_cfm(pa_sync, 0);
6545+
6546+
/* Notify MGMT layer */
6547+
mgmt_device_connected(hdev, pa_sync, NULL, 0);
6548+
}
6549+
6550+
unlock:
65286551
hci_dev_unlock(hdev);
65296552
}
65306553

@@ -7059,10 +7082,8 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
70597082
hci_dev_lock(hdev);
70607083

70617084
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
7062-
if (!(mask & HCI_LM_ACCEPT)) {
7063-
hci_le_pa_term_sync(hdev, ev->sync_handle);
7085+
if (!(mask & HCI_LM_ACCEPT))
70647086
goto unlock;
7065-
}
70667087

70677088
if (!(flags & HCI_PROTO_DEFER))
70687089
goto unlock;
@@ -7071,24 +7092,11 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
70717092
(hdev,
70727093
le16_to_cpu(ev->sync_handle));
70737094

7074-
if (pa_sync)
7075-
goto unlock;
7076-
7077-
/* Add connection to indicate the PA sync event */
7078-
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
7079-
HCI_ROLE_SLAVE);
7080-
70817095
if (!pa_sync)
70827096
goto unlock;
70837097

7084-
pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
7085-
set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags);
7086-
70877098
/* Notify iso layer */
7088-
hci_connect_cfm(pa_sync, 0x00);
7089-
7090-
/* Notify MGMT layer */
7091-
mgmt_device_connected(hdev, pa_sync, NULL, 0);
7099+
hci_connect_cfm(pa_sync, 0);
70927100

70937101
unlock:
70947102
hci_dev_unlock(hdev);

net/bluetooth/iso.c

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ static void iso_sock_kill(struct sock *sk);
5454
enum {
5555
BT_SK_BIG_SYNC,
5656
BT_SK_PA_SYNC,
57-
BT_SK_PA_SYNC_TERM,
5857
};
5958

6059
struct iso_pinfo {
@@ -81,6 +80,7 @@ static bool check_ucast_qos(struct bt_iso_qos *qos);
8180
static bool check_bcast_qos(struct bt_iso_qos *qos);
8281
static bool iso_match_sid(struct sock *sk, void *data);
8382
static bool iso_match_sync_handle(struct sock *sk, void *data);
83+
static bool iso_match_sync_handle_pa_report(struct sock *sk, void *data);
8484
static void iso_sock_disconn(struct sock *sk);
8585

8686
typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
@@ -197,21 +197,10 @@ static void iso_chan_del(struct sock *sk, int err)
197197
sock_set_flag(sk, SOCK_ZAPPED);
198198
}
199199

200-
static bool iso_match_conn_sync_handle(struct sock *sk, void *data)
201-
{
202-
struct hci_conn *hcon = data;
203-
204-
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags))
205-
return false;
206-
207-
return hcon->sync_handle == iso_pi(sk)->sync_handle;
208-
}
209-
210200
static void iso_conn_del(struct hci_conn *hcon, int err)
211201
{
212202
struct iso_conn *conn = hcon->iso_data;
213203
struct sock *sk;
214-
struct sock *parent;
215204

216205
if (!conn)
217206
return;
@@ -227,26 +216,6 @@ static void iso_conn_del(struct hci_conn *hcon, int err)
227216

228217
if (sk) {
229218
lock_sock(sk);
230-
231-
/* While a PA sync hcon is in the process of closing,
232-
* mark parent socket with a flag, so that any residual
233-
* BIGInfo adv reports that arrive before PA sync is
234-
* terminated are not processed anymore.
235-
*/
236-
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
237-
parent = iso_get_sock(&hcon->src,
238-
&hcon->dst,
239-
BT_LISTEN,
240-
iso_match_conn_sync_handle,
241-
hcon);
242-
243-
if (parent) {
244-
set_bit(BT_SK_PA_SYNC_TERM,
245-
&iso_pi(parent)->flags);
246-
sock_put(parent);
247-
}
248-
}
249-
250219
iso_sock_clear_timer(sk);
251220
iso_chan_del(sk, err);
252221
release_sock(sk);
@@ -860,6 +829,7 @@ static struct sock *iso_sock_alloc(struct net *net, struct socket *sock,
860829
iso_pi(sk)->src_type = BDADDR_LE_PUBLIC;
861830

862831
iso_pi(sk)->qos = default_qos;
832+
iso_pi(sk)->sync_handle = -1;
863833

864834
bt_sock_link(&iso_sk_list, sk);
865835
return sk;
@@ -907,7 +877,6 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
907877
return -EINVAL;
908878

909879
iso_pi(sk)->dst_type = sa->iso_bc->bc_bdaddr_type;
910-
iso_pi(sk)->sync_handle = -1;
911880

912881
if (sa->iso_bc->bc_sid > 0x0f)
913882
return -EINVAL;
@@ -984,7 +953,8 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr *addr,
984953
/* Allow the user to bind a PA sync socket to a number
985954
* of BISes to sync to.
986955
*/
987-
if (sk->sk_state == BT_CONNECT2 &&
956+
if ((sk->sk_state == BT_CONNECT2 ||
957+
sk->sk_state == BT_CONNECTED) &&
988958
test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
989959
err = iso_sock_bind_pa_sk(sk, sa, addr_len);
990960
goto done;
@@ -1396,6 +1366,16 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
13961366
}
13971367
release_sock(sk);
13981368
return 0;
1369+
case BT_CONNECTED:
1370+
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
1371+
iso_conn_big_sync(sk);
1372+
sk->sk_state = BT_LISTEN;
1373+
release_sock(sk);
1374+
return 0;
1375+
}
1376+
1377+
release_sock(sk);
1378+
break;
13991379
case BT_CONNECT:
14001380
release_sock(sk);
14011381
return iso_connect_cis(sk);
@@ -1541,7 +1521,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
15411521

15421522
case BT_ISO_QOS:
15431523
if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
1544-
sk->sk_state != BT_CONNECT2) {
1524+
sk->sk_state != BT_CONNECT2 &&
1525+
(!test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags) ||
1526+
sk->sk_state != BT_CONNECTED)) {
15451527
err = -EINVAL;
15461528
break;
15471529
}
@@ -1762,7 +1744,7 @@ static void iso_conn_ready(struct iso_conn *conn)
17621744
struct sock *sk = conn->sk;
17631745
struct hci_ev_le_big_sync_estabilished *ev = NULL;
17641746
struct hci_ev_le_pa_sync_established *ev2 = NULL;
1765-
struct hci_evt_le_big_info_adv_report *ev3 = NULL;
1747+
struct hci_ev_le_per_adv_report *ev3 = NULL;
17661748
struct hci_conn *hcon;
17671749

17681750
BT_DBG("conn %p", conn);
@@ -1799,12 +1781,12 @@ static void iso_conn_ready(struct iso_conn *conn)
17991781
iso_match_sid, ev2);
18001782
} else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) {
18011783
ev3 = hci_recv_event_data(hcon->hdev,
1802-
HCI_EVT_LE_BIG_INFO_ADV_REPORT);
1784+
HCI_EV_LE_PER_ADV_REPORT);
18031785
if (ev3)
18041786
parent = iso_get_sock(&hcon->src,
18051787
&hcon->dst,
18061788
BT_LISTEN,
1807-
iso_match_sync_handle,
1789+
iso_match_sync_handle_pa_report,
18081790
ev3);
18091791
}
18101792

@@ -1847,7 +1829,6 @@ static void iso_conn_ready(struct iso_conn *conn)
18471829

18481830
if (ev3) {
18491831
iso_pi(sk)->qos = iso_pi(parent)->qos;
1850-
iso_pi(sk)->qos.bcast.encryption = ev3->encryption;
18511832
hcon->iso_qos = iso_pi(sk)->qos;
18521833
iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis;
18531834
memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS);
@@ -1941,26 +1922,29 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
19411922

19421923
ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT);
19431924
if (ev2) {
1944-
/* Try to get PA sync listening socket, if it exists */
1945-
sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
1946-
iso_match_pa_sync_flag, NULL);
1947-
1948-
if (!sk) {
1949-
sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
1950-
iso_match_sync_handle, ev2);
1951-
1952-
/* If PA Sync is in process of terminating,
1953-
* do not handle any more BIGInfo adv reports.
1954-
*/
1955-
1956-
if (sk && test_bit(BT_SK_PA_SYNC_TERM,
1957-
&iso_pi(sk)->flags))
1958-
return 0;
1925+
/* Check if BIGInfo report has already been handled */
1926+
sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECTED,
1927+
iso_match_sync_handle, ev2);
1928+
if (sk) {
1929+
sock_put(sk);
1930+
sk = NULL;
1931+
goto done;
19591932
}
19601933

1934+
/* Try to get PA sync socket, if it exists */
1935+
sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECT2,
1936+
iso_match_sync_handle, ev2);
1937+
if (!sk)
1938+
sk = iso_get_sock(&hdev->bdaddr, bdaddr,
1939+
BT_LISTEN,
1940+
iso_match_sync_handle,
1941+
ev2);
1942+
19611943
if (sk) {
19621944
int err;
19631945

1946+
iso_pi(sk)->qos.bcast.encryption = ev2->encryption;
1947+
19641948
if (ev2->num_bis < iso_pi(sk)->bc_num_bis)
19651949
iso_pi(sk)->bc_num_bis = ev2->num_bis;
19661950

@@ -1979,6 +1963,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
19791963
}
19801964
}
19811965
}
1966+
1967+
goto done;
19821968
}
19831969

19841970
ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT);

0 commit comments

Comments
 (0)