Bluetooth: ISO: Add hcon for listening bis sk

This creates a hcon instance at bis listen, before the PA sync
procedure is started.

Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Iulia Tanasescu 2024-02-23 15:14:41 +02:00 committed by Luiz Augusto von Dentz
parent 6e62ebfb49
commit 02171da6e8
3 changed files with 60 additions and 19 deletions

View File

@ -1,7 +1,7 @@
/* /*
BlueZ - Bluetooth protocol stack for Linux BlueZ - Bluetooth protocol stack for Linux
Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Copyright 2023 NXP Copyright 2023-2024 NXP
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@ -1528,8 +1528,8 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
__u8 dst_type, struct bt_iso_qos *qos, __u8 dst_type, struct bt_iso_qos *qos,
__u8 data_len, __u8 *data); __u8 data_len, __u8 *data);
int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type, struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
__u8 sid, struct bt_iso_qos *qos); __u8 dst_type, __u8 sid, struct bt_iso_qos *qos);
int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon, int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
struct bt_iso_qos *qos, struct bt_iso_qos *qos,
__u16 sync_handle, __u8 num_bis, __u8 bis[]); __u16 sync_handle, __u8 num_bis, __u8 bis[]);

View File

@ -1,7 +1,7 @@
/* /*
BlueZ - Bluetooth protocol stack for Linux BlueZ - Bluetooth protocol stack for Linux
Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Copyright 2023 NXP Copyright 2023-2024 NXP
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@ -2057,18 +2057,31 @@ static int create_pa_sync(struct hci_dev *hdev, void *data)
return hci_update_passive_scan_sync(hdev); return hci_update_passive_scan_sync(hdev);
} }
int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type, struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
__u8 sid, struct bt_iso_qos *qos) __u8 dst_type, __u8 sid,
struct bt_iso_qos *qos)
{ {
struct hci_cp_le_pa_create_sync *cp; struct hci_cp_le_pa_create_sync *cp;
struct hci_conn *conn;
int err;
if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC)) if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC))
return -EBUSY; return ERR_PTR(-EBUSY);
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE);
if (!conn)
return ERR_PTR(-ENOMEM);
conn->iso_qos = *qos;
conn->state = BT_LISTEN;
hci_conn_hold(conn);
cp = kzalloc(sizeof(*cp), GFP_KERNEL); cp = kzalloc(sizeof(*cp), GFP_KERNEL);
if (!cp) { if (!cp) {
hci_dev_clear_flag(hdev, HCI_PA_SYNC); hci_dev_clear_flag(hdev, HCI_PA_SYNC);
return -ENOMEM; hci_conn_drop(conn);
return ERR_PTR(-ENOMEM);
} }
cp->options = qos->bcast.options; cp->options = qos->bcast.options;
@ -2080,7 +2093,14 @@ int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type,
cp->sync_cte_type = qos->bcast.sync_cte_type; cp->sync_cte_type = qos->bcast.sync_cte_type;
/* Queue start pa_create_sync and scan */ /* Queue start pa_create_sync and scan */
return hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete); err = hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete);
if (err < 0) {
hci_conn_drop(conn);
kfree(cp);
return ERR_PTR(err);
}
return conn;
} }
int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon, int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,

View File

@ -3,7 +3,7 @@
* BlueZ - Bluetooth protocol stack for Linux * BlueZ - Bluetooth protocol stack for Linux
* *
* Copyright (C) 2022 Intel Corporation * Copyright (C) 2022 Intel Corporation
* Copyright 2023 NXP * Copyright 2023-2024 NXP
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -690,11 +690,8 @@ static void iso_sock_cleanup_listen(struct sock *parent)
iso_sock_kill(sk); iso_sock_kill(sk);
} }
/* If listening socket stands for a PA sync connection, /* If listening socket has a hcon, properly disconnect it */
* properly disconnect the hcon and socket. if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon) {
*/
if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon &&
test_bit(HCI_CONN_PA_SYNC, &iso_pi(parent)->conn->hcon->flags)) {
iso_sock_disconn(parent); iso_sock_disconn(parent);
return; return;
} }
@ -1076,6 +1073,8 @@ static int iso_listen_bis(struct sock *sk)
{ {
struct hci_dev *hdev; struct hci_dev *hdev;
int err = 0; int err = 0;
struct iso_conn *conn;
struct hci_conn *hcon;
BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src, BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src,
&iso_pi(sk)->dst, iso_pi(sk)->bc_sid); &iso_pi(sk)->dst, iso_pi(sk)->bc_sid);
@ -1096,18 +1095,40 @@ static int iso_listen_bis(struct sock *sk)
if (!hdev) if (!hdev)
return -EHOSTUNREACH; return -EHOSTUNREACH;
hci_dev_lock(hdev);
/* Fail if user set invalid QoS */ /* Fail if user set invalid QoS */
if (iso_pi(sk)->qos_user_set && !check_bcast_qos(&iso_pi(sk)->qos)) { if (iso_pi(sk)->qos_user_set && !check_bcast_qos(&iso_pi(sk)->qos)) {
iso_pi(sk)->qos = default_qos; iso_pi(sk)->qos = default_qos;
return -EINVAL; err = -EINVAL;
goto unlock;
} }
err = hci_pa_create_sync(hdev, &iso_pi(sk)->dst, hcon = hci_pa_create_sync(hdev, &iso_pi(sk)->dst,
le_addr_type(iso_pi(sk)->dst_type), le_addr_type(iso_pi(sk)->dst_type),
iso_pi(sk)->bc_sid, &iso_pi(sk)->qos); iso_pi(sk)->bc_sid, &iso_pi(sk)->qos);
if (IS_ERR(hcon)) {
err = PTR_ERR(hcon);
goto unlock;
}
conn = iso_conn_add(hcon);
if (!conn) {
hci_conn_drop(hcon);
err = -ENOMEM;
goto unlock;
}
err = iso_chan_add(conn, sk, NULL);
if (err) {
hci_conn_drop(hcon);
goto unlock;
}
hci_dev_put(hdev); hci_dev_put(hdev);
unlock:
hci_dev_unlock(hdev);
return err; return err;
} }