From 63dbc4c7f9cb0f651e4eba0e7e5b579e0340174d Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Mon, 28 Apr 2025 20:00:21 +0800 Subject: [PATCH] Bluetooth: Classic: L2CAP: Support zero-length SDU in none basic mode Support zero-length SDU sending if the L2CAP channel connection is not in basic mode. Flag the zero-length SDU buffer and clear it if it has been processed. Signed-off-by: Lyle Zhu --- subsys/bluetooth/host/classic/l2cap_br.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/subsys/bluetooth/host/classic/l2cap_br.c b/subsys/bluetooth/host/classic/l2cap_br.c index 66343aa512d..7680b715812 100644 --- a/subsys/bluetooth/host/classic/l2cap_br.c +++ b/subsys/bluetooth/host/classic/l2cap_br.c @@ -60,6 +60,11 @@ LOG_MODULE_REGISTER(bt_l2cap_br, CONFIG_BT_L2CAP_LOG_LEVEL); #define L2CAP_BR_PSM_SDP 0x0001 +#define L2CAP_BR_ZL_I_FRAME_FLAG_MASK 0xfffffeffU +#define L2CAP_BR_ZL_I_FRAME_UD_FLAG 0xfffffeff +#define L2CAP_BR_IS_ZERO_LEN_I_FRAME(flag) \ + ((POINTER_TO_UINT(flag) & L2CAP_BR_ZL_I_FRAME_FLAG_MASK) == L2CAP_BR_ZL_I_FRAME_UD_FLAG) + #define L2CAP_BR_S_FRAME_FLAG_MASK 0xffffff00U #define L2CAP_BR_S_FRAME_UD_FLAG 0xffffff00 #define L2CAP_BR_IS_S_FRAME(flag) \ @@ -892,6 +897,11 @@ int bt_l2cap_br_send_cb(struct bt_conn *conn, uint16_t cid, struct net_buf *buf, hdr = net_buf_push(buf, sizeof(*hdr)); hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr)); hdr->cid = sys_cpu_to_le16(cid); + } else { + if ((cb == NULL) && (user_data == NULL) && (buf->len == 0)) { + /* Mask it is a zero-length I-frame */ + user_data = UINT_TO_POINTER(L2CAP_BR_ZL_I_FRAME_UD_FLAG); + } } #else hdr = net_buf_push(buf, sizeof(*hdr)); @@ -1139,6 +1149,10 @@ static struct net_buf *l2cap_br_get_next_sdu(struct bt_l2cap_br_chan *br_chan) if (L2CAP_BR_IS_S_FRAME(closure_data(sdu->user_data))) { return sdu; } + + if (L2CAP_BR_IS_ZERO_LEN_I_FRAME(closure_data(sdu->user_data))) { + return sdu; + } } return NULL; @@ -1501,6 +1515,10 @@ send_i_frame: br_chan->next_tx_seq = bt_l2cap_br_update_seq(br_chan, br_chan->next_tx_seq + 1); + if (L2CAP_BR_IS_ZERO_LEN_I_FRAME(closure_data(pdu->user_data))) { + make_closure(pdu->user_data, NULL, NULL); + } + net_buf_pull(pdu, pdu_len); if (br_chan->rx.mode != BT_L2CAP_BR_LINK_MODE_STREAM) {