Skip to content

Commit 7860dcb

Browse files
iulia-tanasescugregkh
authored andcommitted
Bluetooth: ISO: Handle PA sync when no BIGInfo reports are generated
[ Upstream commit d356c92 ] 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]> Stable-dep-of: a5b862c ("Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init()") Signed-off-by: Sasha Levin <[email protected]>
1 parent ca5ad9c commit 7860dcb

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
@@ -1335,8 +1335,7 @@ hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle)
13351335
rcu_read_lock();
13361336

13371337
list_for_each_entry_rcu(c, &h->list, list) {
1338-
if (c->type != ISO_LINK ||
1339-
!test_bit(HCI_CONN_PA_SYNC, &c->flags))
1338+
if (c->type != ISO_LINK)
13401339
continue;
13411340

13421341
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
@@ -6359,14 +6359,16 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
63596359
if (!(flags & HCI_PROTO_DEFER))
63606360
goto unlock;
63616361

6362-
if (ev->status) {
6363-
/* Add connection to indicate the failed PA sync event */
6364-
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
6365-
HCI_ROLE_SLAVE);
6362+
/* Add connection to indicate PA sync event */
6363+
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
6364+
HCI_ROLE_SLAVE);
63666365

6367-
if (!pa_sync)
6368-
goto unlock;
6366+
if (!pa_sync)
6367+
goto unlock;
63696368

6369+
pa_sync->sync_handle = le16_to_cpu(ev->handle);
6370+
6371+
if (ev->status) {
63706372
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
63716373

63726374
/* Notify iso layer */
@@ -6383,15 +6385,36 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
63836385
struct hci_ev_le_per_adv_report *ev = data;
63846386
int mask = hdev->link_mode;
63856387
__u8 flags = 0;
6388+
struct hci_conn *pa_sync;
63866389

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

63896392
hci_dev_lock(hdev);
63906393

63916394
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
63926395
if (!(mask & HCI_LM_ACCEPT))
6393-
hci_le_pa_term_sync(hdev, ev->sync_handle);
6396+
goto unlock;
63946397

6398+
if (!(flags & HCI_PROTO_DEFER))
6399+
goto unlock;
6400+
6401+
pa_sync = hci_conn_hash_lookup_pa_sync_handle
6402+
(hdev,
6403+
le16_to_cpu(ev->sync_handle));
6404+
6405+
if (!pa_sync)
6406+
goto unlock;
6407+
6408+
if (ev->data_status == LE_PA_DATA_COMPLETE &&
6409+
!test_and_set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags)) {
6410+
/* Notify iso layer */
6411+
hci_connect_cfm(pa_sync, 0);
6412+
6413+
/* Notify MGMT layer */
6414+
mgmt_device_connected(hdev, pa_sync, NULL, 0);
6415+
}
6416+
6417+
unlock:
63956418
hci_dev_unlock(hdev);
63966419
}
63976420

@@ -6926,10 +6949,8 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
69266949
hci_dev_lock(hdev);
69276950

69286951
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
6929-
if (!(mask & HCI_LM_ACCEPT)) {
6930-
hci_le_pa_term_sync(hdev, ev->sync_handle);
6952+
if (!(mask & HCI_LM_ACCEPT))
69316953
goto unlock;
6932-
}
69336954

69346955
if (!(flags & HCI_PROTO_DEFER))
69356956
goto unlock;
@@ -6938,24 +6959,11 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
69386959
(hdev,
69396960
le16_to_cpu(ev->sync_handle));
69406961

6941-
if (pa_sync)
6942-
goto unlock;
6943-
6944-
/* Add connection to indicate the PA sync event */
6945-
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
6946-
HCI_ROLE_SLAVE);
6947-
69486962
if (IS_ERR(pa_sync))
69496963
goto unlock;
69506964

6951-
pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
6952-
set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags);
6953-
69546965
/* Notify iso layer */
6955-
hci_connect_cfm(pa_sync, 0x00);
6956-
6957-
/* Notify MGMT layer */
6958-
mgmt_device_connected(hdev, pa_sync, NULL, 0);
6966+
hci_connect_cfm(pa_sync, 0);
69596967

69606968
unlock:
69616969
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)