int bt_gatt_read_multiple(struct bt_conn *conn, const uint16_t *handles, size_t count, bt_gatt_read_func_t func) { struct net_buf *buf; uint8_t i; if (!conn || conn->state != BT_CONN_CONNECTED) { return -ENOTCONN; } if (!handles || count < 2 || !func) { return -EINVAL; } buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_MULT_REQ, count * sizeof(*handles)); if (!buf) { return -ENOMEM; } for (i = 0; i < count; i++) { net_buf_add_le16(buf, handles[i]); } return gatt_send(conn, buf, att_read_multiple_rsp, func, NULL); }
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch, struct net_buf *buf, size_t sdu_hdr_len) { struct net_buf *seg; uint16_t headroom; uint16_t len; /* Segment if data (+ data headroom) is bigger than MPS */ if (buf->len + sdu_hdr_len > ch->tx.mps) { goto segment; } /* Segment if there is no space in the user_data */ if (buf->pool->user_data_size < BT_BUF_USER_DATA_MIN) { BT_WARN("Too small buffer user_data_size %u", buf->pool->user_data_size); goto segment; } headroom = sizeof(struct bt_hci_acl_hdr) + sizeof(struct bt_l2cap_hdr) + sdu_hdr_len; /* Check if original buffer has enough headroom and don't have any * fragments. */ if (net_buf_headroom(buf) >= headroom && !buf->frags) { if (sdu_hdr_len) { /* Push SDU length if set */ net_buf_push_le16(buf, net_buf_frags_len(buf)); } return net_buf_ref(buf); } segment: seg = bt_l2cap_create_pdu(&le_data_pool, 0); if (sdu_hdr_len) { net_buf_add_le16(seg, net_buf_frags_len(buf)); } /* Don't send more that TX MPS including SDU length */ len = min(net_buf_tailroom(seg), ch->tx.mps - sdu_hdr_len); /* Limit if original buffer is smaller than the segment */ len = min(buf->len, len); net_buf_add_mem(seg, buf->data, len); net_buf_pull(buf, len); BT_DBG("ch %p seg %p len %u", ch, seg, seg->len); return seg; }
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch, struct net_buf *buf, size_t sdu_hdr_len) { struct net_buf *seg; uint16_t headroom; uint16_t len; /* Segment if data (+ data headroom) is bigger than MPS */ if (buf->len + sdu_hdr_len > ch->tx.mps) { goto segment; } headroom = sizeof(struct bt_hci_acl_hdr) + sizeof(struct bt_l2cap_hdr) + sdu_hdr_len; /* Check if original buffer has enough headroom */ if (net_buf_headroom(buf) >= headroom) { if (sdu_hdr_len) { /* Push SDU length if set */ net_buf_push_le16(buf, buf->len); } return net_buf_ref(buf); } segment: seg = bt_l2cap_create_pdu(&le_data); if (!seg) { return NULL; } if (sdu_hdr_len) { net_buf_add_le16(seg, buf->len); } len = min(min(buf->len, L2CAP_LE_MIN_MTU - sdu_hdr_len), ch->tx.mps); memcpy(net_buf_add(seg, len), buf->data, len); net_buf_pull(buf, len); BT_DBG("ch %p seg %p len %u", ch, seg, seg->len); return seg; }
static int att_find_type(struct bt_conn *conn, struct bt_gatt_discover_params *params) { struct net_buf *buf; struct bt_att_find_type_req *req; buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_TYPE_REQ, sizeof(*req)); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->start_handle = sys_cpu_to_le16(params->start_handle); req->end_handle = sys_cpu_to_le16(params->end_handle); if (params->type == BT_GATT_DISCOVER_PRIMARY) { req->type = sys_cpu_to_le16(BT_UUID_GATT_PRIMARY_VAL); } else { req->type = sys_cpu_to_le16(BT_UUID_GATT_SECONDARY_VAL); } BT_DBG("uuid %s start_handle 0x%04x end_handle 0x%04x", bt_uuid_str(params->uuid), params->start_handle, params->end_handle); switch (params->uuid->type) { case BT_UUID_TYPE_16: net_buf_add_le16(buf, BT_UUID_16(params->uuid)->val); break; case BT_UUID_TYPE_128: memcpy(net_buf_add(buf, 16), BT_UUID_128(params->uuid)->val, 16); break; default: BT_ERR("Unknown UUID type %u", params->uuid->type); net_buf_unref(buf); return -EINVAL; } return gatt_send(conn, buf, att_find_type_rsp, params, NULL); }
static int gatt_write_ccc(struct bt_conn *conn, uint16_t handle, uint16_t value, bt_att_func_t func, struct bt_gatt_subscribe_params *params) { struct net_buf *buf; struct bt_att_write_req *req; buf = bt_att_create_pdu(conn, BT_ATT_OP_WRITE_REQ, sizeof(*req) + sizeof(uint16_t)); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->handle = sys_cpu_to_le16(handle); net_buf_add_le16(buf, value); BT_DBG("handle 0x%04x value 0x%04x", handle, value); return gatt_send(conn, buf, func, params, NULL); }