Skip to content

Commit

Permalink
Bluetooth: ISO: Send BIG Create Sync via hci_sync
Browse files Browse the repository at this point in the history
Before issuing the LE BIG Create Sync command, an available BIG handle
is chosen by iterating through the conn_hash list and finding the first
unused value.

If a BIG is terminated, the associated hcons are removed from the list
and the LE BIG Terminate Sync command is sent via hci_sync queue.
However, a new LE BIG Create sync command might be issued via
hci_send_cmd, before the previous BIG sync was terminated. This
can cause the same BIG handle to be reused and the LE BIG Create Sync
to fail with Command Disallowed.

< HCI Command: LE Broadcast Isochronous Group Create Sync (0x08|0x006b)
        BIG Handle: 0x00
        BIG Sync Handle: 0x0002
        Encryption: Unencrypted (0x00)
        Broadcast Code[16]: 00000000000000000000000000000000
        Maximum Number Subevents: 0x00
        Timeout: 20000 ms (0x07d0)
        Number of BIS: 1
        BIS ID: 0x01
> HCI Event: Command Status (0x0f) plen 4
      LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1
        Status: Command Disallowed (0x0c)
< HCI Command: LE Broadcast Isochronous Group Terminate Sync (0x08|0x006c)
        BIG Handle: 0x00

This commit fixes the ordering of the LE BIG Create Sync/LE BIG Terminate
Sync commands, to make sure that either the previous BIG sync is
terminated before reusing the handle, or that a new handle is chosen
for a new sync.

Fixes: eca0ae4 ("Bluetooth: Add initial implementation of BIS connections")
Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
iulia-tanasescu authored and Vudentz committed Nov 14, 2024
1 parent 25ab2db commit 07a9342
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
17 changes: 16 additions & 1 deletion net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2180,7 +2180,15 @@ static bool hci_conn_check_create_big_sync(struct hci_conn *conn)
return true;
}

int hci_le_big_create_sync_pending(struct hci_dev *hdev)
static void big_create_sync_complete(struct hci_dev *hdev, void *data, int err)
{
bt_dev_dbg(hdev, "");

if (err)
bt_dev_err(hdev, "Unable to create BIG sync: %d", err);
}

static int big_create_sync(struct hci_dev *hdev, void *data)
{
DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11);
struct hci_conn *conn;
Expand Down Expand Up @@ -2237,6 +2245,13 @@ int hci_le_big_create_sync_pending(struct hci_dev *hdev)
struct_size(pdu, bis, pdu->num_bis), pdu);
}

int hci_le_big_create_sync_pending(struct hci_dev *hdev)
{
/* Queue big_create_sync */
return hci_cmd_sync_queue_once(hdev, big_create_sync,
NULL, big_create_sync_complete);
}

int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
struct bt_iso_qos *qos,
__u16 sync_handle, __u8 num_bis, __u8 bis[])
Expand Down
9 changes: 9 additions & 0 deletions net/bluetooth/iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,13 @@ static void iso_conn_big_sync(struct sock *sk)
if (!hdev)
return;

/* hci_le_big_create_sync requires hdev lock to be held, since
* it enqueues the HCI LE BIG Create Sync command via
* hci_cmd_sync_queue_once, which checks hdev flags that might
* change.
*/
hci_dev_lock(hdev);

if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
&iso_pi(sk)->qos,
Expand All @@ -1402,6 +1409,8 @@ static void iso_conn_big_sync(struct sock *sk)
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
err);
}

hci_dev_unlock(hdev);
}

static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
Expand Down

0 comments on commit 07a9342

Please sign in to comment.