Bluetooth: ISO: Send BIG Create Sync via hci_sync
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: eca0ae4aea
("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>
This commit is contained in:
parent
25ab2db3e6
commit
07a9342b94
2 changed files with 25 additions and 1 deletions
|
@ -2180,7 +2180,15 @@ static bool hci_conn_check_create_big_sync(struct hci_conn *conn)
|
||||||
return true;
|
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);
|
DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11);
|
||||||
struct hci_conn *conn;
|
struct hci_conn *conn;
|
||||||
|
@ -2237,6 +2245,13 @@ unlock:
|
||||||
struct_size(pdu, bis, pdu->num_bis), pdu);
|
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,
|
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[])
|
||||||
|
|
|
@ -1392,6 +1392,13 @@ static void iso_conn_big_sync(struct sock *sk)
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return;
|
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)) {
|
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,
|
err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
|
||||||
&iso_pi(sk)->qos,
|
&iso_pi(sk)->qos,
|
||||||
|
@ -1402,6 +1409,8 @@ static void iso_conn_big_sync(struct sock *sk)
|
||||||
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
|
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
|
||||||
err);
|
err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hci_dev_unlock(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||||
|
|
Loading…
Add table
Reference in a new issue