Skip to content

Commit

Permalink
Bluetooth: ISO: use correct CIS order in Set CIG Parameters event
Browse files Browse the repository at this point in the history
The order of CIS handle array in Set CIG Parameters response shall match
the order of the CIS_ID array in the command (Core v5.3 Vol 4 Part E Sec
7.8.97).  We send CIS_IDs mainly in the order of increasing CIS_ID (but
with "last" CIS first if it has fixed CIG_ID).  In handling of the
reply, we currently assume this is also the same as the order of
hci_conn in hdev->conn_hash, but that is not true.

Match the correct hci_conn to the correct handle by matching them based
on the CIG+CIS combination.  The CIG+CIS combination shall be unique for
ISO_LINK hci_conn at state >= BT_BOUND, which we maintain in
hci_le_set_cig_params.

Fixes: 26afbd8 ("Bluetooth: Add initial implementation of CIS connections")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Pauli Virtanen authored and Luiz Augusto von Dentz committed Jun 6, 2023
1 parent 6c242c6 commit 71e9588
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 19 deletions.
3 changes: 2 additions & 1 deletion include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,8 @@ static inline struct hci_conn *hci_conn_hash_lookup_cis(struct hci_dev *hdev,
if (id != BT_ISO_QOS_CIS_UNSET && id != c->iso_qos.ucast.cis)
continue;

if (ba_type == c->dst_type && !bacmp(&c->dst, ba)) {
/* Match destination address if set */
if (!ba || (ba_type == c->dst_type && !bacmp(&c->dst, ba))) {
rcu_read_unlock();
return c;
}
Expand Down
44 changes: 26 additions & 18 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -3804,48 +3804,56 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_set_cig_params *rp = data;
struct hci_cp_le_set_cig_params *cp;
struct hci_conn *conn;
int i = 0;
u8 status = rp->status;
int i;

bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);

cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_CIG_PARAMS);
if (!cp || rp->num_handles != cp->num_cis || rp->cig_id != cp->cig_id) {
bt_dev_err(hdev, "unexpected Set CIG Parameters response data");
status = HCI_ERROR_UNSPECIFIED;
}

hci_dev_lock(hdev);

if (rp->status) {
if (status) {
while ((conn = hci_conn_hash_lookup_cig(hdev, rp->cig_id))) {
conn->state = BT_CLOSED;
hci_connect_cfm(conn, rp->status);
hci_connect_cfm(conn, status);
hci_conn_del(conn);
}
goto unlock;
}

rcu_read_lock();
/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 2553
*
* If the Status return parameter is zero, then the Controller shall
* set the Connection_Handle arrayed return parameter to the connection
* handle(s) corresponding to the CIS configurations specified in
* the CIS_IDs command parameter, in the same order.
*/
for (i = 0; i < rp->num_handles; ++i) {
conn = hci_conn_hash_lookup_cis(hdev, NULL, 0, rp->cig_id,
cp->cis[i].cis_id);
if (!conn || !bacmp(&conn->dst, BDADDR_ANY))
continue;

list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
if (conn->type != ISO_LINK ||
conn->iso_qos.ucast.cig != rp->cig_id ||
conn->state == BT_CONNECTED)
if (conn->state != BT_BOUND && conn->state != BT_CONNECT)
continue;

conn->handle = __le16_to_cpu(rp->handle[i++]);
conn->handle = __le16_to_cpu(rp->handle[i]);

bt_dev_dbg(hdev, "%p handle 0x%4.4x parent %p", conn,
conn->handle, conn->parent);

/* Create CIS if LE is already connected */
if (conn->parent && conn->parent->state == BT_CONNECTED) {
rcu_read_unlock();
if (conn->parent && conn->parent->state == BT_CONNECTED)
hci_le_create_cis(conn);
rcu_read_lock();
}

if (i == rp->num_handles)
break;
}

rcu_read_unlock();

unlock:
hci_dev_unlock(hdev);

Expand Down

0 comments on commit 71e9588

Please sign in to comment.