static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch, struct net_buf *buf, size_t sdu_hdr_len) { struct net_buf *seg; uint16_t headroom; uint16_t len; /* Segment if data (+ data headroom) is bigger than MPS */ if (buf->len + sdu_hdr_len > ch->tx.mps) { goto segment; } /* Segment if there is no space in the user_data */ if (buf->pool->user_data_size < BT_BUF_USER_DATA_MIN) { BT_WARN("Too small buffer user_data_size %u", buf->pool->user_data_size); goto segment; } headroom = sizeof(struct bt_hci_acl_hdr) + sizeof(struct bt_l2cap_hdr) + sdu_hdr_len; /* Check if original buffer has enough headroom and don't have any * fragments. */ if (net_buf_headroom(buf) >= headroom && !buf->frags) { if (sdu_hdr_len) { /* Push SDU length if set */ net_buf_push_le16(buf, net_buf_frags_len(buf)); } return net_buf_ref(buf); } segment: seg = bt_l2cap_create_pdu(&le_data_pool, 0); if (sdu_hdr_len) { net_buf_add_le16(seg, net_buf_frags_len(buf)); } /* Don't send more that TX MPS including SDU length */ len = min(net_buf_tailroom(seg), ch->tx.mps - sdu_hdr_len); /* Limit if original buffer is smaller than the segment */ len = min(buf->len, len); net_buf_add_mem(seg, buf->data, len); net_buf_pull(buf, len); BT_DBG("ch %p seg %p len %u", ch, seg, seg->len); return seg; }
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch, struct net_buf *buf, size_t sdu_hdr_len) { struct net_buf *seg; uint16_t headroom; uint16_t len; /* Segment if data (+ data headroom) is bigger than MPS */ if (buf->len + sdu_hdr_len > ch->tx.mps) { goto segment; } headroom = sizeof(struct bt_hci_acl_hdr) + sizeof(struct bt_l2cap_hdr) + sdu_hdr_len; /* Check if original buffer has enough headroom */ if (net_buf_headroom(buf) >= headroom) { if (sdu_hdr_len) { /* Push SDU length if set */ net_buf_push_le16(buf, buf->len); } return net_buf_ref(buf); } segment: seg = bt_l2cap_create_pdu(&le_data); if (!seg) { return NULL; } if (sdu_hdr_len) { net_buf_add_le16(seg, buf->len); } len = min(min(buf->len, L2CAP_LE_MIN_MTU - sdu_hdr_len), ch->tx.mps); memcpy(net_buf_add(seg, len), buf->data, len); net_buf_pull(buf, len); BT_DBG("ch %p seg %p len %u", ch, seg, seg->len); return seg; }