Skip to content

Commit b3581fe

Browse files
lylezhu2012kartben
authored andcommitted
Bluetooth: Classic: L2CAP: Handle multi L2CAP packets of a HCI ACL
In current implementation, if the HCI ACL data length exceeds on L2CAP packet, the HCI ACL data will be discarded. Support the case if the transport is classic. Add a function `bt_br_acl_recv()` to handle the multi L2CAP packets one by one. Signed-off-by: Lyle Zhu <[email protected]>
1 parent 132f008 commit b3581fe

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

subsys/bluetooth/host/classic/conn_br.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,30 @@ const bt_addr_t *bt_conn_get_dst_br(const struct bt_conn *conn)
143143

144144
return &conn->br.dst;
145145
}
146+
147+
void bt_br_acl_recv(struct bt_conn *conn, struct net_buf *buf, bool complete)
148+
{
149+
uint16_t acl_total_len;
150+
struct bt_l2cap_hdr *hdr;
151+
struct net_buf_simple_state state;
152+
153+
do {
154+
net_buf_simple_save(&buf->b, &state);
155+
156+
hdr = (void *)buf->data;
157+
acl_total_len = sys_le16_to_cpu(hdr->len) + sizeof(*hdr);
158+
if (buf->len > acl_total_len) {
159+
LOG_DBG("Multiple L2CAP packet (%u > %u)", buf->len, acl_total_len);
160+
buf->len = acl_total_len;
161+
} else if (buf->len < acl_total_len) {
162+
LOG_ERR("Short packet (%u < %u)", buf->len, acl_total_len);
163+
break;
164+
}
165+
bt_l2cap_recv(conn, net_buf_ref(buf), complete);
166+
167+
net_buf_simple_restore(&buf->b, &state);
168+
net_buf_pull(buf, acl_total_len);
169+
} while (buf->len > 0);
170+
171+
net_buf_unref(buf);
172+
}

subsys/bluetooth/host/classic/conn_br_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@
1010
*/
1111

1212
int bt_hci_connect_br_cancel(struct bt_conn *conn);
13+
14+
void bt_br_acl_recv(struct bt_conn *conn, struct net_buf *buf, bool complete);

subsys/bluetooth/host/conn.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags
471471

472472
net_buf_unref(buf);
473473

474-
if (conn->rx->len > acl_total_len) {
474+
if ((conn->type != BT_CONN_TYPE_BR) && (conn->rx->len > acl_total_len)) {
475475
LOG_ERR("ACL len mismatch (%u > %u)", conn->rx->len, acl_total_len);
476476
bt_conn_reset_rx_state(conn);
477477
return;
@@ -484,7 +484,11 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags
484484
__ASSERT(buf->ref == 1, "buf->ref %d", buf->ref);
485485

486486
LOG_DBG("Successfully parsed %u byte L2CAP packet", buf->len);
487-
bt_l2cap_recv(conn, buf, true);
487+
if (IS_ENABLED(CONFIG_BT_CLASSIC) && (conn->type == BT_CONN_TYPE_BR)) {
488+
bt_br_acl_recv(conn, buf, true);
489+
} else {
490+
bt_l2cap_recv(conn, buf, true);
491+
}
488492
}
489493

490494
void bt_conn_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags)

0 commit comments

Comments
 (0)