diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index 0117da5ebb9..cdd162f9889 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -349,6 +349,11 @@ struct bt_l2cap_chan_ops { * @kconfig{CONFIG_BT_L2CAP_SEG_RECV} is enabled and seg_recv is * supplied. * + * If the application returns @c -EINPROGRESS, the application takes + * ownership of the reference in @p buf. (I.e. This pointer value can + * simply be given to @ref bt_l2cap_chan_recv_complete without any + * calls @ref net_buf_ref or @ref net_buf_unref.) + * * @return 0 in case of success or negative value in case of error. * @return -EINPROGRESS in case where user has to confirm once the data * has been processed by calling diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 3b5cfe82864..8012706bc45 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -2566,6 +2567,7 @@ static void l2cap_chan_le_recv_seg_direct(struct bt_l2cap_le_chan *chan, struct static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan, struct net_buf *buf) { + struct net_buf *owned_ref; uint16_t sdu_len; int err; @@ -2639,7 +2641,13 @@ static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan, return; } - err = chan->chan.ops->recv(&chan->chan, buf); + owned_ref = net_buf_ref(buf); + err = chan->chan.ops->recv(&chan->chan, owned_ref); + if (err != -EINPROGRESS) { + net_buf_unref(owned_ref); + owned_ref = NULL; + } + if (err < 0) { if (err != -EINPROGRESS) { LOG_ERR("err %d", err);