static uint8_t att_notify(struct bt_att *att, struct net_buf *buf) { struct bt_conn *conn = att->chan.conn; uint16_t handle; handle = net_buf_pull_le16(buf); BT_DBG("handle 0x%04x", handle); bt_gatt_notification(conn, handle, buf->data, buf->len); return 0; }
static bool uuid_create(struct bt_uuid *uuid, struct net_buf *buf) { switch (buf->len) { case 2: uuid->type = BT_UUID_TYPE_16; BT_UUID_16(uuid)->val = net_buf_pull_le16(buf); return true; case 16: uuid->type = BT_UUID_TYPE_128; memcpy(BT_UUID_128(uuid)->val, buf->data, buf->len); return true; } return false; }
static uint8_t att_read_mult_req(struct bt_att *att, struct net_buf *buf) { struct bt_conn *conn = att->chan.conn; struct read_data data; uint16_t handle; memset(&data, 0, sizeof(data)); data.buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_MULT_RSP, 0); if (!data.buf) { return BT_ATT_ERR_UNLIKELY; } data.att = att; while (buf->len >= sizeof(uint16_t)) { handle = net_buf_pull_le16(buf); BT_DBG("handle 0x%04x ", handle); /* An Error Response shall be sent by the server in response to * the Read Multiple Request [....] if a read operation is not * permitted on any of the Characteristic Values. * * If handle is not valid then return invalid handle error. * If handle is found error will be cleared by read_cb. */ data.err = BT_ATT_ERR_INVALID_HANDLE; bt_gatt_foreach_attr(handle, handle, read_cb, &data); /* Stop reading in case of error */ if (data.err) { net_buf_unref(data.buf); /* Respond here since handle is set */ send_err_rsp(conn, BT_ATT_OP_READ_MULT_REQ, handle, data.err); return 0; } } bt_l2cap_send(conn, BT_L2CAP_CID_ATT, data.buf); return 0; }
static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan, struct net_buf *buf) { uint16_t sdu_len; if (!nano_fiber_sem_take(&chan->rx.credits, TICKS_NONE)) { BT_ERR("No credits to receive packet"); bt_l2cap_chan_disconnect(&chan->chan); return; } /* Check if segments already exist */ if (chan->_sdu) { l2cap_chan_le_recv_sdu(chan, buf); return; } sdu_len = net_buf_pull_le16(buf); BT_DBG("chan %p len %u sdu_len %u", chan, buf->len, sdu_len); if (sdu_len > chan->rx.mtu) { BT_ERR("Invalid SDU length"); bt_l2cap_chan_disconnect(&chan->chan); return; } /* Always allocate buffer from the channel if supported. */ if (chan->chan.ops && chan->chan.ops->alloc_buf) { chan->_sdu = chan->chan.ops->alloc_buf(&chan->chan); if (!chan->_sdu) { BT_ERR("Unable to allocate buffer for SDU"); bt_l2cap_chan_disconnect(&chan->chan); return; } chan->_sdu_len = sdu_len; l2cap_chan_le_recv_sdu(chan, buf); return; } chan->chan.ops->recv(&chan->chan, buf); l2cap_chan_update_credits(chan); }
static uint8_t att_indicate(struct bt_att *att, struct net_buf *buf) { struct bt_conn *conn = att->chan.conn; uint16_t handle; handle = net_buf_pull_le16(buf); BT_DBG("handle 0x%04x", handle); bt_gatt_notification(conn, handle, buf->data, buf->len); buf = bt_att_create_pdu(conn, BT_ATT_OP_CONFIRM, 0); if (!buf) { return 0; } bt_l2cap_send(conn, BT_L2CAP_CID_ATT, buf); return 0; }