diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2016-10-05 12:19:59 +0300 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2016-10-16 09:00:57 +0300 |
commit | 0817b052031752db383ed2b18bfbe6a4ce62600b (patch) | |
tree | d838b6839d5b0d652082eb0ce9b6421262f40b4e /net | |
parent | aca8700f92108857513885eaed19a6ee54440305 (diff) |
Bluetooth: L2CAP: Allow sending fragmented buffers
This enabled L2CAP CoC to send buffers that contains fragments.
Change-Id: I898b8375f634d3f0652ec1e7f5a206aa47dd232d
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/l2cap.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index e06dea006..a72f55377 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1379,7 +1379,7 @@ static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch, if (net_buf_headroom(buf) >= headroom) { if (sdu_hdr_len) { /* Push SDU length if set */ - net_buf_push_le16(buf, buf->len); + net_buf_push_le16(buf, net_buf_frags_len(buf)); } return net_buf_ref(buf); } @@ -1391,7 +1391,7 @@ segment: } if (sdu_hdr_len) { - net_buf_add_le16(seg, buf->len); + net_buf_add_le16(seg, net_buf_frags_len(buf)); } len = min(min(buf->len, L2CAP_LE_MIN_MTU - sdu_hdr_len), ch->tx.mps); @@ -1436,22 +1436,33 @@ static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch, struct net_buf *buf) { int ret, sent, total_len; + struct net_buf *frag; - if (buf->len > ch->tx.mtu) { + total_len = net_buf_frags_len(buf); + + if (total_len > ch->tx.mtu) { return -EMSGSIZE; } - total_len = buf->len; + frag = buf; + if (!frag->len && frag->frags) { + frag = frag->frags; + } /* Add SDU length for the first segment */ - ret = l2cap_chan_le_send(ch, buf, BT_L2CAP_SDU_HDR_LEN); + ret = l2cap_chan_le_send(ch, frag, BT_L2CAP_SDU_HDR_LEN); if (ret < 0) { return ret; } /* Send remaining segments */ for (sent = ret; sent < total_len; sent += ret) { - ret = l2cap_chan_le_send(ch, buf, 0); + /* Proceed to next fragment */ + if (!frag->len) { + frag = frag->frags; + } + + ret = l2cap_chan_le_send(ch, frag, 0); if (ret < 0) { return ret; } |