From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v1 06/11] emulator: use the handle of the receiving side
Date: Tue, 15 Sep 2026 17:15:23 -0400 [thread overview]
Message-ID: <20260915211528.1223784-7-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260915211528.1223784-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Every device assigns its own connection handles, so the two sides of a
link do not necessarily know it by the same handle: conn_link() picks
the lowest one free on each device, which differ as soon as a device
has more than one connection.
The events and the data delivered to the peer carried the handle of the
sender though, so the receiving side got a handle it knows nothing
about and dropped what it received: with three devices the second link
of the initiator is handle 2 on it and handle 1 on the peer, so neither
the ACL data nor the CIS requests reached their destination.
Give the receiving side its own handle, as the disconnection already
does, for the data as well as for the events reporting a connection, a
key request, a connection update and the CIS of a CIG.
This changes nothing for two devices, as both sides then assign the
same handles.
Assisted-by: opencode:claude-opus-5
---
emulator/btdev.c | 84 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 64 insertions(+), 20 deletions(-)
diff --git a/emulator/btdev.c b/emulator/btdev.c
index fcc516f4947c..e29e050fad59 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -1589,9 +1589,14 @@ static int cmd_add_sco_conn(struct btdev *dev, const void *data, uint8_t len)
done:
send_event(dev, BT_HCI_EVT_CONN_COMPLETE, &cc, sizeof(cc));
- if (conn)
+ if (conn) {
+ /* Each device assigns its own handles, so the event of
+ * the receiving side carries its handle.
+ */
+ cc.handle = cpu_to_le16(conn->link->handle);
send_event(conn->link->dev, BT_HCI_EVT_CONN_COMPLETE,
&cc, sizeof(cc));
+ }
return 0;
}
@@ -4196,12 +4201,17 @@ static void le_conn_complete(struct btdev *btdev,
memcpy(cc.peer_addr, btdev->bdaddr, 6);
cc.role = 0x01;
- cc.handle = cpu_to_le16(conn->handle);
+ /* Each device assigns its own handles, so the event of
+ * the receiving side carries its handle.
+ */
+ cc.handle = cpu_to_le16(conn->link->handle);
cc.interval = lecc->max_interval;
cc.latency = lecc->latency;
cc.supv_timeout = lecc->supv_timeout;
le_meta_event(conn->link->dev, BT_HCI_EVT_LE_CONN_COMPLETE,
&cc, sizeof(cc));
+
+ cc.handle = cpu_to_le16(conn->handle);
}
cc.status = status;
@@ -4709,10 +4719,12 @@ static void le_conn_update(struct btdev *btdev, uint16_t handle,
le_meta_event(btdev, BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE, &ev,
sizeof(ev));
- if (conn)
+ if (conn) {
+ ev.handle = cpu_to_le16(conn->link->handle);
le_meta_event(conn->link->dev,
BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE,
&ev, sizeof(ev));
+ }
}
static void le_conn_param_req(struct btdev *btdev, uint16_t handle,
@@ -4729,7 +4741,7 @@ static void le_conn_param_req(struct btdev *btdev, uint16_t handle,
memset(&ev, 0, sizeof(ev));
- ev.handle = cpu_to_le16(handle);
+ ev.handle = cpu_to_le16(conn->link->handle);
ev.min_interval = cpu_to_le16(min_interval);
ev.max_interval = cpu_to_le16(max_interval);
ev.latency = cpu_to_le16(latency);
@@ -4845,7 +4857,7 @@ static int cmd_start_encrypt(struct btdev *dev, const void *data, uint8_t len)
memcpy(dev->le_ltk, cmd->ltk, 16);
- ev.handle = cpu_to_le16(conn->handle);
+ ev.handle = cpu_to_le16(conn->link->handle);
ev.ediv = cmd->ediv;
ev.rand = cmd->rand;
@@ -5003,7 +5015,7 @@ static int cmd_conn_param_neg_reply_complete(struct btdev *dev,
memset(&ev, 0, sizeof(ev));
- ev.handle = cpu_to_le16(cmd->handle);
+ ev.handle = cpu_to_le16(conn->link->handle);
ev.status = cpu_to_le16(cmd->reason);
le_meta_event(conn->link->dev, BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE, &ev,
@@ -6190,7 +6202,10 @@ static void le_ext_conn_complete(struct btdev *btdev,
memcpy(ev.peer_addr, btdev->bdaddr, 6);
ev.role = 0x01;
- ev.handle = cpu_to_le16(conn->handle);
+ /* Each device assigns its own handles, so the event of
+ * the receiving side carries its handle.
+ */
+ ev.handle = cpu_to_le16(conn->link->handle);
ev.interval = lecc->max_interval;
ev.latency = lecc->latency;
ev.supv_timeout = lecc->supv_timeout;
@@ -6205,7 +6220,10 @@ static void le_ext_conn_complete(struct btdev *btdev,
sizeof(ev));
/* Disable EXT ADV */
- queue_foreach(conn->link->dev->le_ext_adv, ext_adv_term, conn);
+ queue_foreach(conn->link->dev->le_ext_adv, ext_adv_term,
+ conn->link);
+
+ ev.handle = cpu_to_le16(conn->handle);
}
ev.status = status;
@@ -7063,9 +7081,11 @@ static void le_cis_estabilished(struct btdev *dev, struct btdev_conn *conn,
le_meta_event(dev, BT_HCI_EVT_LE_CIS_ESTABLISHED, &evt, sizeof(evt));
- if (conn)
+ if (conn) {
+ evt.conn_handle = cpu_to_le16(conn->link->handle);
le_meta_event(conn->link->dev, BT_HCI_EVT_LE_CIS_ESTABLISHED,
&evt, sizeof(evt));
+ }
}
static int cmd_create_cis_complete(struct btdev *dev, const void *data,
@@ -7110,8 +7130,11 @@ static int cmd_create_cis_complete(struct btdev *dev, const void *data,
}
}
- evt.acl_handle = cpu_to_le16(acl->handle);
- evt.cis_handle = cpu_to_le16(iso->handle);
+ /* Each device assigns its own handles, so the event of
+ * the receiving side carries its handles.
+ */
+ evt.acl_handle = cpu_to_le16(acl->link->handle);
+ evt.cis_handle = cpu_to_le16(iso->link->handle);
evt.cig_id = le_cig->params.cig_id;
evt.cis_id = le_cig->cis[cis_idx].cis_id;
@@ -8737,6 +8760,7 @@ static void send_acl(struct btdev *dev, const void *data, uint16_t len)
struct iovec iov[3];
struct btdev_conn *conn;
uint8_t pkt_type = BT_H4_ACL_PKT;
+ uint8_t flags;
/* Packet type */
iov[0].iov_base = &pkt_type;
@@ -8751,11 +8775,18 @@ static void send_acl(struct btdev *dev, const void *data, uint16_t len)
num_completed_packets(dev, conn);
+ flags = acl_flags(hdr.handle);
+
/* ACL_START_NO_FLUSH is only allowed from host to controller.
* From controller to host this should be converted to ACL_START.
*/
- if (acl_flags(hdr.handle) == ACL_START_NO_FLUSH)
- hdr.handle = acl_handle_pack(conn->handle, ACL_START);
+ if (flags == ACL_START_NO_FLUSH)
+ flags = ACL_START;
+
+ /* Each device assigns its own handles, so the one of the
+ * receiving side has to be used.
+ */
+ hdr.handle = acl_handle_pack(conn->link->handle, flags);
iov[1].iov_base = &hdr;
iov[1].iov_len = sizeof(hdr);
@@ -8794,8 +8825,8 @@ static void send_sco(struct btdev *dev, const void *data, uint16_t len)
static void send_iso(struct btdev *dev, const void *data, uint16_t len)
{
- struct bt_hci_acl_hdr *hdr;
- struct iovec iov[2];
+ struct bt_hci_acl_hdr hdr;
+ struct iovec iov[3];
struct btdev_conn *conn;
uint8_t pkt_type = BT_H4_ISO_PKT;
@@ -8803,18 +8834,31 @@ static void send_iso(struct btdev *dev, const void *data, uint16_t len)
iov[0].iov_base = &pkt_type;
iov[0].iov_len = sizeof(pkt_type);
- iov[1].iov_base = hdr = (void *) (data);
- iov[1].iov_len = len;
+ memcpy(&hdr, data, sizeof(hdr));
conn = queue_find(dev->conns, match_handle,
- UINT_TO_PTR(acl_handle(hdr->handle)));
+ UINT_TO_PTR(acl_handle(hdr.handle)));
if (!conn)
return;
num_completed_packets(dev, conn);
- if (conn->link)
- send_packet(conn->link->dev, iov, 2);
+ if (!conn->link)
+ return;
+
+ /* Each device assigns its own handles, so the one of the
+ * receiving side has to be used.
+ */
+ hdr.handle = acl_handle_pack(conn->link->handle,
+ acl_flags(hdr.handle));
+
+ iov[1].iov_base = &hdr;
+ iov[1].iov_len = sizeof(hdr);
+
+ iov[2].iov_base = (void *) (data + sizeof(hdr));
+ iov[2].iov_len = len - sizeof(hdr);
+
+ send_packet(conn->link->dev, iov, 3);
}
void btdev_receive_h4(struct btdev *btdev, const void *data, uint16_t len)
--
2.55.0
next prev parent reply other threads:[~2026-09-15 21:15 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 21:15 [PATCH BlueZ v1 00/11] Cover a BAP stream to a coordinated set Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 01/11] shared/bass: add a ready callback Luiz Augusto von Dentz
2026-09-15 21:58 ` Cover a BAP stream to a coordinated set bluez.test.bot
2026-09-16 0:55 ` bluez.test.bot
2026-09-15 21:15 ` [PATCH BlueZ v1 02/11] bass: wait for the session to be ready before pushing a source Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 03/11] test: functional: report what a test is waiting for Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 04/11] test: functional: answer the notification registered by the victim Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 05/11] doc: describe the BAP coordinated set test cases Luiz Augusto von Dentz
2026-09-15 21:15 ` Luiz Augusto von Dentz [this message]
2026-09-15 21:15 ` [PATCH BlueZ v1 07/11] emulator: allow the maximum number of CIS of a CIG Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 08/11] device: keep the long term key of both roles Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 09/11] client: allow a capability with the auto agent Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 10/11] test: functional: fail as soon as an operation fails Luiz Augusto von Dentz
2026-09-15 21:15 ` [PATCH BlueZ v1 11/11] test: functional: add the BAP coordinated set tests Luiz Augusto von Dentz
2026-09-16 18:30 ` [PATCH BlueZ v1 00/11] Cover a BAP stream to a coordinated set patchwork-bot+bluetooth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260915211528.1223784-7-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox