Bluetooth: L2CAP: Add return to recv

This adds a int return to recv callback which can be used to notify the
stack about errors when receiving a packet. In addition to that the user
can return -EINPROGRESS to inform the stack the data will be processed
asynchronously which can be complete by calling
bt_l2cap_chan_recv_complete.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2018-08-22 13:16:14 +03:00 committed by Johan Hedberg
parent 0287a04340
commit 3151d26572
12 changed files with 190 additions and 76 deletions

View file

@ -203,8 +203,14 @@ struct bt_l2cap_chan_ops {
*
* @param chan The channel receiving data.
* @param buf Buffer containing incoming data.
*
* @return 0 in case of success or negative value in case of error.
* If -EINPROGRESS is returned user has to confirm once the data has
* been processed by calling bt_l2cap_chan_recv_complete passing back
* the buffer received with its original user_data which contains the
* number of segments/credits used by the packet.
*/
void (*recv)(struct bt_l2cap_chan *chan, struct net_buf *buf);
int (*recv)(struct bt_l2cap_chan *chan, struct net_buf *buf);
};
/** @def BT_L2CAP_CHAN_SEND_RESERVE
@ -324,6 +330,21 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan);
*/
int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf);
/** @brief Complete receiving L2CAP channel data
*
* Complete the reception of incoming data. This shall only be called if the
* channel recv callback has returned -EINPROGRESS to process some incoming
* data. The buffer shall contain the original user_data as that is used for
* storing the credits/segments used by the packet.
*
* @param chan Channel object.
* @param buf Buffer containing the data.
*
* @return 0 in case of success or negative value in case of error.
*/
int bt_l2cap_chan_recv_complete(struct bt_l2cap_chan *chan,
struct net_buf *buf);
#ifdef __cplusplus
}
#endif

View file

@ -1864,7 +1864,7 @@ static att_type_t att_op_get_type(u8_t op)
return ATT_UNKNOWN;
}
static void bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_att *att = ATT_CHAN(chan);
struct bt_att_hdr *hdr = (void *)buf->data;
@ -1874,7 +1874,7 @@ static void bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Too small ATT PDU received");
return;
return 0;
}
BT_DBG("Received ATT code 0x%02x len %u", hdr->code, buf->len);
@ -1894,19 +1894,19 @@ static void bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
send_err_rsp(chan->conn, hdr->code, 0,
BT_ATT_ERR_NOT_SUPPORTED);
}
return;
return 0;
}
if (IS_ENABLED(CONFIG_BT_ATT_ENFORCE_FLOW)) {
if (handler->type == ATT_REQUEST &&
atomic_test_and_set_bit(att->flags, ATT_PENDING_RSP)) {
BT_WARN("Ignoring unexpected request");
return;
return 0;
} else if (handler->type == ATT_INDICATION &&
atomic_test_and_set_bit(att->flags,
ATT_PENDING_CFM)) {
BT_WARN("Ignoring unexpected indication");
return;
return 0;
}
}
@ -1921,6 +1921,8 @@ static void bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
BT_DBG("ATT error 0x%02x", err);
send_err_rsp(chan->conn, hdr->code, 0, err);
}
return 0;
}
static struct bt_att *att_chan_get(struct bt_conn *conn)

View file

@ -142,7 +142,7 @@ void bt_avdtp_l2cap_encrypt_changed(struct bt_l2cap_chan *chan, u8_t status)
BT_DBG("");
}
void bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
int bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_avdtp_single_sig_hdr *hdr = (void *)buf->data;
struct bt_avdtp *session = AVDTP_CHAN(chan);
@ -150,7 +150,7 @@ void bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Recvd Wrong AVDTP Header");
return;
return 0;
}
msgtype = AVDTP_GET_MSG_TYPE(hdr->hdr);
@ -165,7 +165,7 @@ void bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (msgtype != BT_AVDTP_CMD) {
if (session->req == NULL) {
BT_DBG("Unexpected peer response");
return;
return 0;
}
if (session->req->sig != sigid ||
@ -173,16 +173,18 @@ void bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
BT_DBG("Peer mismatch resp, expected sig[0x%02x]"
"tid[0x%02x]", session->req->sig,
session->req->tid);
return;
return 0;
}
}
for (i = 0; i < ARRAY_SIZE(handler); i++) {
if (sigid == handler[i].sig_id) {
handler[i].func(session, buf, msgtype);
return;
return 0;
}
}
return 0;
}
/*A2DP Layer interface */

View file

@ -1257,7 +1257,7 @@ static void reject_cmd(struct bt_l2cap *l2cap, u8_t ident,
}
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
static void l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_l2cap *l2cap = CONTAINER_OF(chan, struct bt_l2cap, chan);
struct bt_l2cap_sig_hdr *hdr = (void *)buf->data;
@ -1265,7 +1265,7 @@ static void l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Too small L2CAP signaling PDU");
return;
return 0;
}
len = sys_le16_to_cpu(hdr->len);
@ -1276,12 +1276,12 @@ static void l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len != len) {
BT_ERR("L2CAP length mismatch (%u != %u)", buf->len, len);
return;
return 0;
}
if (!hdr->ident) {
BT_ERR("Invalid ident value in L2CAP PDU");
return;
return 0;
}
switch (hdr->code) {
@ -1323,23 +1323,21 @@ static void l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
BT_L2CAP_REJ_NOT_UNDERSTOOD, NULL, 0);
break;
}
return 0;
}
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
static void l2cap_chan_update_credits(struct bt_l2cap_le_chan *chan,
struct net_buf *buf)
static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
struct net_buf *buf, u16_t credits)
{
struct bt_l2cap_le_credits *ev;
u16_t credits;
/* Only give more credits if it went bellow the defined threshold */
if (k_sem_count_get(&chan->rx.credits) >
L2CAP_LE_CREDITS_THRESHOLD(chan->rx.init_credits)) {
goto done;
/* Cap the number of credits given */
if (credits > chan->rx.init_credits) {
credits = chan->rx.init_credits;
}
/* Restore credits */
credits = chan->rx.init_credits - k_sem_count_get(&chan->rx.credits);
l2cap_chan_rx_give_credits(chan, credits);
buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CREDITS, get_ident(),
@ -1351,10 +1349,38 @@ static void l2cap_chan_update_credits(struct bt_l2cap_le_chan *chan,
bt_l2cap_send(chan->chan.conn, BT_L2CAP_CID_LE_SIG, buf);
done:
BT_DBG("chan %p credits %u", chan, k_sem_count_get(&chan->rx.credits));
}
int bt_l2cap_chan_recv_complete(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
struct bt_conn *conn = chan->conn;
u16_t credits;
__ASSERT_NO_MSG(chan);
__ASSERT_NO_MSG(buf);
if (!conn) {
return -ENOTCONN;
}
if (conn->type != BT_CONN_TYPE_LE) {
return -ENOTSUP;
}
BT_DBG("chan %p buf %p", chan, buf);
/* Restore credits used by packet */
memcpy(&credits, net_buf_user_data(buf), sizeof(credits));
l2cap_chan_send_credits(ch, buf, credits);
net_buf_unref(buf);
return 0;
}
static struct net_buf *l2cap_alloc_frag(struct bt_l2cap_le_chan *chan)
{
struct net_buf *frag = NULL;
@ -1372,20 +1398,51 @@ static struct net_buf *l2cap_alloc_frag(struct bt_l2cap_le_chan *chan)
}
static void l2cap_chan_le_recv_sdu(struct bt_l2cap_le_chan *chan,
struct net_buf *buf, u16_t seg)
{
int err;
BT_DBG("chan %p len %zu", chan, net_buf_frags_len(buf));
/* Receiving complete SDU, notify channel and reset SDU buf */
err = chan->chan.ops->recv(&chan->chan, buf);
if (err < 0) {
if (err != -EINPROGRESS) {
BT_ERR("err %d", err);
bt_l2cap_chan_disconnect(&chan->chan);
net_buf_unref(buf);
}
return;
}
l2cap_chan_send_credits(chan, buf, seg);
net_buf_unref(buf);
}
static void l2cap_chan_le_recv_seg(struct bt_l2cap_le_chan *chan,
struct net_buf *buf)
{
struct net_buf *frag;
u16_t len;
u16_t seg = 0;
BT_DBG("chan %p len %u sdu %zu", chan, buf->len,
net_buf_frags_len(chan->_sdu));
len = net_buf_frags_len(chan->_sdu);
if (len) {
memcpy(&seg, net_buf_user_data(chan->_sdu), sizeof(seg));
}
if (net_buf_frags_len(chan->_sdu) + buf->len > chan->_sdu_len) {
if (len + buf->len > chan->_sdu_len) {
BT_ERR("SDU length mismatch");
bt_l2cap_chan_disconnect(&chan->chan);
return;
}
seg++;
/* Store received segments in user_data */
memcpy(net_buf_user_data(chan->_sdu), &seg, sizeof(seg));
BT_DBG("chan %p seg %d len %zu", chan, seg, net_buf_frags_len(buf));
/* Jump to last fragment */
frag = net_buf_frag_last(chan->_sdu);
@ -1407,21 +1464,22 @@ static void l2cap_chan_le_recv_sdu(struct bt_l2cap_le_chan *chan,
BT_DBG("frag %p len %u", frag, frag->len);
}
if (net_buf_frags_len(chan->_sdu) == chan->_sdu_len) {
/* Receiving complete SDU, notify channel and reset SDU buf */
chan->chan.ops->recv(&chan->chan, chan->_sdu);
net_buf_unref(chan->_sdu);
chan->_sdu = NULL;
chan->_sdu_len = 0;
if (net_buf_frags_len(chan->_sdu) < chan->_sdu_len) {
return;
}
l2cap_chan_update_credits(chan, buf);
buf = chan->_sdu;
chan->_sdu = NULL;
chan->_sdu_len = 0;
l2cap_chan_le_recv_sdu(chan, buf, seg);
}
static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
struct net_buf *buf)
{
u16_t sdu_len;
int err;
if (k_sem_take(&chan->rx.credits, K_NO_WAIT)) {
BT_ERR("No credits to receive packet");
@ -1431,7 +1489,7 @@ static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
/* Check if segments already exist */
if (chan->_sdu) {
l2cap_chan_le_recv_sdu(chan, buf);
l2cap_chan_le_recv_seg(chan, buf);
return;
}
@ -1454,13 +1512,20 @@ static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
return;
}
chan->_sdu_len = sdu_len;
l2cap_chan_le_recv_sdu(chan, buf);
l2cap_chan_le_recv_seg(chan, buf);
return;
}
chan->chan.ops->recv(&chan->chan, buf);
err = chan->chan.ops->recv(&chan->chan, buf);
if (err) {
if (err != -EINPROGRESS) {
BT_ERR("err %d", err);
bt_l2cap_chan_disconnect(&chan->chan);
}
return;
}
l2cap_chan_update_credits(chan, buf);
l2cap_chan_send_credits(chan, buf, 1);
}
#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */

View file

@ -1343,7 +1343,7 @@ int bt_l2cap_br_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
return buf->len;
}
static void l2cap_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int l2cap_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_l2cap_br *l2cap = CONTAINER_OF(chan, struct bt_l2cap_br, chan);
struct bt_l2cap_sig_hdr *hdr = (void *)buf->data;
@ -1351,7 +1351,7 @@ static void l2cap_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Too small L2CAP signaling PDU");
return;
return 0;
}
len = sys_le16_to_cpu(hdr->len);
@ -1362,12 +1362,12 @@ static void l2cap_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len != len) {
BT_ERR("L2CAP length mismatch (%u != %u)", buf->len, len);
return;
return 0;
}
if (!hdr->ident) {
BT_ERR("Invalid ident value in L2CAP PDU");
return;
return 0;
}
switch (hdr->code) {
@ -1401,6 +1401,8 @@ static void l2cap_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
BT_L2CAP_REJ_NOT_UNDERSTOOD, NULL, 0);
break;
}
return 0;
}
static void l2cap_br_conn_pend(struct bt_l2cap_chan *chan, u8_t status)

View file

@ -1443,7 +1443,7 @@ int bt_rfcomm_dlc_send(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
return buf->len;
}
static void rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
struct bt_rfcomm_hdr *hdr = (void *)buf->data;
@ -1452,7 +1452,7 @@ static void rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
/* Need to consider FCS also*/
if (buf->len < (sizeof(*hdr) + 1)) {
BT_ERR("Too small RFCOMM Frame");
return;
return 0;
}
dlci = BT_RFCOMM_GET_DLCI(hdr->address);
@ -1465,7 +1465,7 @@ static void rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
fcs = *(net_buf_tail(buf) - 1);
if (!rfcomm_check_fcs(fcs_len, buf->data, fcs)) {
BT_ERR("FCS check failed");
return;
return 0;
}
if (BT_RFCOMM_LEN_EXTENDED(hdr->length)) {
@ -1500,6 +1500,8 @@ static void rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
frame_type);
break;
}
return 0;
}
static void rfcomm_encrypt_change(struct bt_l2cap_chan *chan,

View file

@ -1333,7 +1333,7 @@ static const struct {
*
* @return None
*/
static void bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
struct bt_l2cap_br_chan, chan);
@ -1348,7 +1348,7 @@ static void bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Too small SDP PDU received");
return;
return 0;
}
BT_DBG("Received SDP code 0x%02x len %u", hdr->op_code, buf->len);
@ -1372,6 +1372,8 @@ static void bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
BT_WARN("SDP error 0x%02x", err);
send_err_rsp(chan, err, hdr->tid);
}
return 0;
}
/* @brief Callback for SDP connection accept
@ -1713,7 +1715,7 @@ static void sdp_client_notify_result(struct bt_sdp_client *session,
}
}
static void sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
struct bt_sdp_hdr *hdr = (void *)buf->data;
@ -1725,12 +1727,12 @@ static void sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Too small SDP PDU");
return;
return 0;
}
if (hdr->op_code == BT_SDP_ERROR_RSP) {
BT_INFO("Error SDP PDU response");
return;
return 0;
}
len = sys_be16_to_cpu(hdr->param_len);
@ -1741,12 +1743,12 @@ static void sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len != len) {
BT_ERR("SDP PDU length mismatch (%u != %u)", buf->len, len);
return;
return 0;
}
if (tid != session->tid) {
BT_ERR("Mismatch transaction ID value in SDP PDU");
return;
return 0;
}
switch (hdr->op_code) {
@ -1756,12 +1758,12 @@ static void sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
/* Check valid buf len for attribute list and cont state */
if (buf->len < frame_len + SDP_CONT_STATE_LEN_SIZE) {
BT_ERR("Invalid frame payload length");
return;
return 0;
}
/* Check valid range of attributes length */
if (frame_len < 2) {
BT_ERR("Invalid attributes data length");
return;
return 0;
}
/* Get PDU continuation state */
@ -1770,13 +1772,13 @@ static void sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (cstate->length > BT_SDP_MAX_PDU_CSTATE_LEN) {
BT_ERR("Invalid SDP PDU Continuation State length %u",
cstate->length);
return;
return 0;
}
if ((frame_len + SDP_CONT_STATE_LEN_SIZE + cstate->length) >
buf->len) {
BT_ERR("Invalid frame payload length");
return;
return 0;
}
/*
@ -1834,6 +1836,8 @@ iterate:
BT_DBG("PDU 0x%0x response not handled", hdr->op_code);
break;
}
return 0;
}
static int sdp_client_chan_connect(struct bt_sdp_client *session)

View file

@ -1295,7 +1295,7 @@ static int smp_br_error(struct bt_smp_br *smp, u8_t reason)
return 0;
}
static void bt_smp_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int bt_smp_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_smp_br *smp = CONTAINER_OF(chan, struct bt_smp_br, chan);
struct bt_smp_hdr *hdr = (void *)buf->data;
@ -1303,7 +1303,7 @@ static void bt_smp_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Too small SMP PDU received");
return;
return 0;
}
BT_DBG("Received SMP code 0x%02x len %u", hdr->code, buf->len);
@ -1318,32 +1318,34 @@ static void bt_smp_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
BT_WARN("SMP command (code 0x%02x) received after timeout",
hdr->code);
return;
return 0;
}
if (hdr->code >= ARRAY_SIZE(br_handlers) ||
!br_handlers[hdr->code].func) {
BT_WARN("Unhandled SMP code 0x%02x", hdr->code);
smp_br_error(smp, BT_SMP_ERR_CMD_NOTSUPP);
return;
return 0;
}
if (!atomic_test_and_clear_bit(&smp->allowed_cmds, hdr->code)) {
BT_WARN("Unexpected SMP code 0x%02x", hdr->code);
smp_br_error(smp, BT_SMP_ERR_UNSPECIFIED);
return;
return 0;
}
if (buf->len != br_handlers[hdr->code].expect_len) {
BT_ERR("Invalid len %u for code 0x%02x", buf->len, hdr->code);
smp_br_error(smp, BT_SMP_ERR_INVALID_PARAMS);
return;
return 0;
}
err = br_handlers[hdr->code].func(smp, buf);
if (err) {
smp_br_error(smp, err);
}
return 0;
}
static int bt_smp_br_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
@ -3489,7 +3491,7 @@ static const struct {
{ smp_dhkey_check, sizeof(struct bt_smp_dhkey_check) },
};
static void bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_smp *smp = CONTAINER_OF(chan, struct bt_smp, chan);
struct bt_smp_hdr *hdr = (void *)buf->data;
@ -3497,7 +3499,7 @@ static void bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (buf->len < sizeof(*hdr)) {
BT_ERR("Too small SMP PDU received");
return;
return 0;
}
BT_DBG("Received SMP code 0x%02x len %u", hdr->code, buf->len);
@ -3512,13 +3514,13 @@ static void bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
BT_WARN("SMP command (code 0x%02x) received after timeout",
hdr->code);
return;
return 0;
}
if (hdr->code >= ARRAY_SIZE(handlers) || !handlers[hdr->code].func) {
BT_WARN("Unhandled SMP code 0x%02x", hdr->code);
smp_error(smp, BT_SMP_ERR_CMD_NOTSUPP);
return;
return 0;
}
if (!atomic_test_and_clear_bit(&smp->allowed_cmds, hdr->code)) {
@ -3527,19 +3529,21 @@ static void bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
if (hdr->code != BT_SMP_CMD_PAIRING_FAIL) {
smp_error(smp, BT_SMP_ERR_UNSPECIFIED);
}
return;
return 0;
}
if (buf->len != handlers[hdr->code].expect_len) {
BT_ERR("Invalid len %u for code 0x%02x", buf->len, hdr->code);
smp_error(smp, BT_SMP_ERR_INVALID_PARAMS);
return;
return 0;
}
err = handlers[hdr->code].func(smp, buf);
if (err) {
smp_error(smp, err);
}
return 0;
}
static void bt_smp_pkey_ready(const u8_t *pkey)

View file

@ -38,7 +38,7 @@ int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf)
return -ENOTSUP;
}
static void bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_conn *conn = chan->conn;
struct bt_smp_pairing_fail *rsp;
@ -60,6 +60,8 @@ static void bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
rsp->reason = BT_SMP_ERR_PAIRING_NOTSUPP;
bt_l2cap_send(conn, BT_L2CAP_CID_SMP, buf);
return 0;
}
static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)

View file

@ -1699,7 +1699,7 @@ static int cmd_bredr_discovery(int argc, char *argv[])
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
static u32_t l2cap_rate;
static void l2cap_recv_metrics(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int l2cap_recv_metrics(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
static u32_t len;
static u32_t cycle_stamp;
@ -1719,15 +1719,19 @@ static void l2cap_recv_metrics(struct bt_l2cap_chan *chan, struct net_buf *buf)
len += buf->len;
l2cap_rate = ((u64_t)len << 3) * 1000000000 / delta;
}
return 0;
}
static void l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
printk("Incoming data channel %p len %u\n", chan, buf->len);
if (buf->len) {
hexdump(buf->data, buf->len);
}
return 0;
}
static void l2cap_connected(struct bt_l2cap_chan *chan)
@ -1907,9 +1911,11 @@ static int cmd_l2cap_metrics(int argc, char *argv[])
#endif
#if defined(CONFIG_BT_BREDR)
static void l2cap_bredr_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int l2cap_bredr_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
printk("Incoming data channel %p len %u\n", chan, buf->len);
return 0;
}
static void l2cap_bredr_connected(struct bt_l2cap_chan *chan)

View file

@ -183,7 +183,7 @@ static void ipsp_disconnected(struct bt_l2cap_chan *chan)
#endif
}
static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
static int ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_context *ctxt = CHAN_CTXT(chan);
struct net_pkt *pkt;
@ -194,7 +194,7 @@ static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
/* Get packet for bearer / protocol related data */
pkt = net_pkt_get_reserve_rx(0, BUF_TIMEOUT);
if (!pkt) {
return;
return -ENOMEM;
}
/* Set destination address */
@ -216,6 +216,8 @@ static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
NET_DBG("Packet dropped by NET stack");
net_pkt_unref(pkt);
}
return 0;
}
static struct net_buf *ipsp_alloc_buf(struct bt_l2cap_chan *chan)

View file

@ -35,7 +35,7 @@ static struct net_buf *alloc_buf_cb(struct bt_l2cap_chan *chan)
static u8_t recv_cb_buf[DATA_MTU + sizeof(struct l2cap_data_received_ev)];
static void recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
static int recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
{
struct l2cap_data_received_ev *ev = (void *) recv_cb_buf;
struct channel *chan = CONTAINER_OF(l2cap_chan, struct channel, le);
@ -46,6 +46,8 @@ static void recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + buf->len);
return 0;
}
static void connected_cb(struct bt_l2cap_chan *l2cap_chan)