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:
parent
0287a04340
commit
3151d26572
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue