Lines Matching +full:perm +full:- +full:secure

1 /* att.c - Attribute protocol handling */
4 * Copyright (c) 2015-2016 Intel Corporation
6 * SPDX-License-Identifier: Apache-2.0
79 /* Total number of flags - must be at the end of the enum */
120 return atomic_test_bit(chan->flags, ATT_ENHANCED); in bt_att_is_enhanced()
130 return MIN(chan->chan.rx.mtu, chan->chan.tx.mtu); in bt_att_mtu()
133 /* Descriptor of application-specific authorization callbacks that are used
175 * will block until a request-resource is available, and the callbacks run on
176 * the same thread as the ATT response handler that frees request-resources.
190 /* To mapping tables are used to avoid a big gap with NULL-entries. */ in bt_att_err_to_str()
192 #define ATT_ERR_SECOND(err) [err - BT_ATT_ERR_WRITE_REQ_REJECTED] = #err in bt_att_err_to_str()
228 const uint8_t second_index = att_err - BT_ATT_ERR_WRITE_REQ_REJECTED; in bt_att_err_to_str()
256 * "use-after-free"s. An initial memset is not necessary, as the in att_tx_destroy()
281 __ASSERT_NO_MSG(net_buf_pool_get(buf->pool_id) == &att_pool); in bt_att_get_tx_meta_data()
301 struct bt_att_chan *att_chan = data->att_chan; in att_sent()
302 struct bt_conn *conn = att_chan->att->conn; in att_sent()
303 struct bt_l2cap_chan *chan = &att_chan->chan.chan; in att_sent()
331 struct bt_att_chan *prev_chan = data->att_chan; in chan_send()
333 hdr = (void *)buf->data; in chan_send()
335 LOG_DBG("code 0x%02x", hdr->code); in chan_send()
337 if (!atomic_test_bit(chan->flags, ATT_CONNECTED)) { in chan_send()
339 return -EINVAL; in chan_send()
342 if (IS_ENABLED(CONFIG_BT_EATT) && hdr->code == BT_ATT_OP_MTU_REQ && in chan_send()
343 chan->chan.tx.cid != BT_L2CAP_CID_ATT) { in chan_send()
344 /* The Exchange MTU sub-procedure shall only be supported on in chan_send()
347 return -ENOTSUP; in chan_send()
350 __ASSERT_NO_MSG(buf->len >= sizeof(struct bt_att_hdr)); in chan_send()
351 data->opcode = buf->data[0]; in chan_send()
352 data->err = 0; in chan_send()
358 if (atomic_test_bit(chan->flags, ATT_PENDING_SENT)) { in chan_send()
359 return -EAGAIN; in chan_send()
362 if (hdr->code == BT_ATT_OP_SIGNED_WRITE_CMD) { in chan_send()
363 return -ENOTSUP; in chan_send()
367 if (att_op_get_type(hdr->code) == ATT_REQUEST && in chan_send()
368 !atomic_test_bit(chan->chan.chan.status, in chan_send()
370 return -EAGAIN; in chan_send()
373 atomic_set_bit(chan->flags, ATT_PENDING_SENT); in chan_send()
374 data->att_chan = chan; in chan_send()
379 err = bt_l2cap_chan_send(&chan->chan.chan, buf); in chan_send()
381 data->att_chan = prev_chan; in chan_send()
382 atomic_clear_bit(chan->flags, ATT_PENDING_SENT); in chan_send()
383 data->err = err; in chan_send()
398 if (hdr->code == BT_ATT_OP_SIGNED_WRITE_CMD) { in chan_send()
399 err = bt_smp_sign(chan->att->conn, buf); in chan_send()
407 net_buf_simple_save(&buf->b, &state); in chan_send()
409 data->att_chan = chan; in chan_send()
411 err = bt_l2cap_send_pdu(&chan->chan, buf, NULL, NULL); in chan_send()
413 if (err == -ENOBUFS) { in chan_send()
417 net_buf_simple_restore(&buf->b, &state); in chan_send()
418 data->att_chan = prev_chan; in chan_send()
419 data->err = err; in chan_send()
453 att_chan_matches_chan_opt(chan, meta->chan_opt)) { in get_first_buf_matching_chan()
481 meta = bt_att_get_tx_meta_data(ATT_REQ(curr)->buf); in get_first_req_matching_chan()
482 if (att_chan_matches_chan_opt(chan, meta->chan_opt)) { in get_first_req_matching_chan()
517 k_queue_prepend(&queue->_queue, buf); in process_queue()
524 return -ENOENT; in process_queue()
533 if (bt_att_mtu(chan) < net_buf_frags_len(req->buf)) { in chan_req_send()
534 return -EMSGSIZE; in chan_req_send()
537 LOG_DBG("chan %p req %p len %zu", chan, req, net_buf_frags_len(req->buf)); in chan_req_send()
539 chan->req = req; in chan_req_send()
542 buf = req->buf; in chan_req_send()
543 req->buf = NULL; in chan_req_send()
552 req->buf = buf; in chan_req_send()
553 chan->req = NULL; in chan_req_send()
565 struct bt_att *att = chan->att; in bt_att_sent()
570 atomic_clear_bit(chan->flags, ATT_PENDING_SENT); in bt_att_sent()
582 if (!chan->req && !sys_slist_is_empty(&att->reqs)) { in bt_att_sent()
583 sys_snode_t *node = sys_slist_get(&att->reqs); in bt_att_sent()
590 sys_slist_prepend(&att->reqs, node); in bt_att_sent()
594 err = process_queue(chan, &chan->tx_queue); in bt_att_sent()
600 (void)process_queue(chan, &att->tx_queue); in bt_att_sent()
606 struct bt_att_chan *chan = data->att_chan; in chan_rebegin_att_timeout()
608 LOG_DBG("chan %p chan->req %p", chan, chan->req); in chan_rebegin_att_timeout()
610 if (!atomic_test_bit(chan->flags, ATT_CONNECTED)) { in chan_rebegin_att_timeout()
616 * in-flight. in chan_rebegin_att_timeout()
618 if (chan->req) { in chan_rebegin_att_timeout()
619 k_work_reschedule(&chan->timeout_work, BT_ATT_TIMEOUT); in chan_rebegin_att_timeout()
626 struct bt_att_chan *chan = data->att_chan; in chan_req_notif_sent()
627 struct bt_conn *conn = chan->att->conn; in chan_req_notif_sent()
628 bt_gatt_complete_func_t func = data->func; in chan_req_notif_sent()
629 uint16_t attr_count = data->attr_count; in chan_req_notif_sent()
630 void *ud = data->user_data; in chan_req_notif_sent()
632 LOG_DBG("chan %p CID 0x%04X", chan, chan->chan.tx.cid); in chan_req_notif_sent()
634 if (!atomic_test_bit(chan->flags, ATT_CONNECTED)) { in chan_req_notif_sent()
648 const att_type_t op_type = att_op_get_type(meta->opcode); in att_on_sent_cb()
650 LOG_DBG("opcode 0x%x", meta->opcode); in att_on_sent_cb()
652 if (!meta->att_chan || in att_on_sent_cb()
653 !meta->att_chan->att || in att_on_sent_cb()
654 !meta->att_chan->att->conn) { in att_on_sent_cb()
659 if (meta->err) { in att_on_sent_cb()
660 LOG_ERR("Got err %d, not calling ATT cb", meta->err); in att_on_sent_cb()
664 if (!bt_att_is_enhanced(meta->att_chan)) { in att_on_sent_cb()
728 data->att_chan = chan; in bt_att_chan_create_pdu()
731 hdr->code = op; in bt_att_chan_create_pdu()
738 LOG_DBG("chan %p flags %lu code 0x%02x", chan, atomic_get(chan->flags), in bt_att_chan_send()
739 ((struct bt_att_hdr *)buf->data)->code); in bt_att_chan_send()
742 !att_chan_matches_chan_opt(chan, bt_att_get_tx_meta_data(buf)->chan_opt)) { in bt_att_chan_send()
743 return -EINVAL; in bt_att_chan_send()
754 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { in att_send_process()
755 if (err == -ENOENT && prev && in att_send_process()
764 err = process_queue(chan, &att->tx_queue); in att_send_process()
781 k_fifo_put(&chan->tx_queue, buf); in bt_att_chan_send_rsp()
802 rsp->request = req; in send_err_rsp()
803 rsp->handle = sys_cpu_to_le16(handle); in send_err_rsp()
804 rsp->error = err; in send_err_rsp()
816 /* Exchange MTU sub-procedure shall only be supported on the in att_mtu_req()
823 req = (void *)buf->data; in att_mtu_req()
825 mtu_client = sys_le16_to_cpu(req->mtu); in att_mtu_req()
844 rsp->mtu = sys_cpu_to_le16(mtu_server); in att_mtu_req()
851 chan->chan.rx.mtu = mtu_server; in att_mtu_req()
852 chan->chan.tx.mtu = mtu_client; in att_mtu_req()
863 atomic_set_bit(chan->att->conn->flags, BT_CONN_ATT_MTU_EXCHANGED); in att_mtu_req()
876 __ASSERT_NO_MSG(req->func); in bt_att_chan_req_send()
877 __ASSERT_NO_MSG(!chan->req); in bt_att_chan_req_send()
889 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { in att_req_send_process()
891 if (chan->req) { in att_req_send_process()
906 req = get_first_req_matching_chan(&att->reqs, chan); in att_req_send_process()
916 sys_slist_prepend(&att->reqs, &req->node); in att_req_send_process()
929 k_work_cancel_delayable(&chan->timeout_work); in att_handle_rsp()
931 if (!chan->req) { in att_handle_rsp()
937 if (chan->req == &cancel) { in att_handle_rsp()
938 chan->req = NULL; in att_handle_rsp()
943 func = chan->req->func; in att_handle_rsp()
944 chan->req->func = NULL; in att_handle_rsp()
945 params = chan->req->user_data; in att_handle_rsp()
948 bt_att_req_free(chan->req); in att_handle_rsp()
949 chan->req = NULL; in att_handle_rsp()
953 att_req_send_process(chan->att); in att_handle_rsp()
955 func(chan->att->conn, err, pdu, len, params); in att_handle_rsp()
967 rsp = (void *)buf->data; in att_mtu_rsp()
969 mtu = sys_le16_to_cpu(rsp->mtu); in att_mtu_rsp()
981 chan->chan.rx.mtu = BT_LOCAL_ATT_MTU_UATT; in att_mtu_rsp()
986 chan->chan.tx.mtu = mtu; in att_mtu_rsp()
992 return att_handle_rsp(chan, rsp, buf->len, 0); in att_mtu_rsp()
1031 struct bt_att_chan *chan = data->chan; in find_info_cb()
1036 if (!data->rsp) { in find_info_cb()
1037 data->rsp = net_buf_add(data->buf, sizeof(*data->rsp)); in find_info_cb()
1038 data->rsp->format = (attr->uuid->type == BT_UUID_TYPE_16) ? in find_info_cb()
1042 switch (data->rsp->format) { in find_info_cb()
1044 if (attr->uuid->type != BT_UUID_TYPE_16) { in find_info_cb()
1049 data->info16 = net_buf_add(data->buf, sizeof(*data->info16)); in find_info_cb()
1050 data->info16->handle = sys_cpu_to_le16(handle); in find_info_cb()
1051 data->info16->uuid = sys_cpu_to_le16(BT_UUID_16(attr->uuid)->val); in find_info_cb()
1053 if (bt_att_mtu(chan) - data->buf->len > in find_info_cb()
1054 sizeof(*data->info16)) { in find_info_cb()
1060 if (attr->uuid->type != BT_UUID_TYPE_128) { in find_info_cb()
1065 data->info128 = net_buf_add(data->buf, sizeof(*data->info128)); in find_info_cb()
1066 data->info128->handle = sys_cpu_to_le16(handle); in find_info_cb()
1067 memcpy(data->info128->uuid, BT_UUID_128(attr->uuid)->val, in find_info_cb()
1068 sizeof(data->info128->uuid)); in find_info_cb()
1070 if (bt_att_mtu(chan) - data->buf->len > in find_info_cb()
1071 sizeof(*data->info128)) { in find_info_cb()
1112 req = (void *)buf->data; in att_find_info_req()
1114 start_handle = sys_le16_to_cpu(req->start_handle); in att_find_info_req()
1115 end_handle = sys_le16_to_cpu(req->end_handle); in att_find_info_req()
1141 struct bt_att_chan *chan = data->chan; in find_type_cb()
1142 struct bt_conn *conn = chan->chan.chan.conn; in find_type_cb()
1149 if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) { in find_type_cb()
1154 if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY)) { in find_type_cb()
1155 if (data->group && in find_type_cb()
1156 handle > sys_le16_to_cpu(data->group->end_handle)) { in find_type_cb()
1157 data->group->end_handle = sys_cpu_to_le16(handle); in find_type_cb()
1165 if (bt_att_mtu(chan) - net_buf_frags_len(data->buf) < in find_type_cb()
1166 sizeof(*data->group)) { in find_type_cb()
1170 frag = net_buf_frag_last(data->buf); in find_type_cb()
1172 len = MIN(bt_att_mtu(chan) - net_buf_frags_len(data->buf), in find_type_cb()
1175 frag = net_buf_alloc(net_buf_pool_get(data->buf->pool_id), in find_type_cb()
1182 net_buf_frag_add(data->buf, frag); in find_type_cb()
1186 read = attr->read(conn, attr, uuid, sizeof(uuid), 0); in find_type_cb()
1196 if (read != data->value_len) { in find_type_cb()
1201 if (!bt_uuid_create(&recvd_uuid.uuid, data->value, data->value_len)) { in find_type_cb()
1202 LOG_WRN("Unable to create UUID: size %u", data->value_len); in find_type_cb()
1212 } else if (memcmp(data->value, uuid, read)) { in find_type_cb()
1217 data->err = 0x00; in find_type_cb()
1220 data->group = net_buf_add(frag, sizeof(*data->group)); in find_type_cb()
1221 data->group->start_handle = sys_cpu_to_le16(handle); in find_type_cb()
1222 data->group->end_handle = sys_cpu_to_le16(handle); in find_type_cb()
1228 data->group = NULL; in find_type_cb()
1250 /* Pre-set error in case no service will be found */ in att_find_type_rsp()
1277 start_handle = sys_le16_to_cpu(req->start_handle); in att_find_type_req()
1278 end_handle = sys_le16_to_cpu(req->end_handle); in att_find_type_req()
1279 type = sys_le16_to_cpu(req->type); in att_find_type_req()
1280 value = buf->data; in att_find_type_req()
1292 * and the Attribute Value set to the 16-bit Bluetooth UUID or 128-bit in att_find_type_req()
1302 buf->len); in att_find_type_req()
1309 if (err < 0 && err >= -0xff) { in err_to_att()
1310 return -err; in err_to_att()
1335 if (!authorization_cb || !authorization_cb->read_authorize) { in attr_read_authorize()
1339 return authorization_cb->read_authorize(conn, attr); in attr_read_authorize()
1347 if (!data->rsp->len) { in attr_read_type_cb()
1349 data->rsp->len = read + sizeof(*data->item); in attr_read_type_cb()
1350 } else if (data->rsp->len != read + sizeof(*data->item)) { in attr_read_type_cb()
1352 frag->len -= sizeof(*data->item); in attr_read_type_cb()
1353 data->item = NULL; in attr_read_type_cb()
1365 struct bt_conn *conn = chan->chan.chan.conn; in att_chan_read()
1380 len = MIN(bt_att_mtu(chan) - net_buf_frags_len(buf), in att_chan_read()
1383 frag = net_buf_alloc(net_buf_pool_get(buf->pool_id), in att_chan_read()
1392 len = MIN(bt_att_mtu(chan) - net_buf_frags_len(buf), in att_chan_read()
1396 read = attr->read(conn, attr, frag->data + frag->len, len, in att_chan_read()
1422 struct bt_att_chan *chan = data->chan; in read_type_cb()
1423 struct bt_conn *conn = chan->chan.chan.conn; in read_type_cb()
1427 if (bt_uuid_cmp(attr->uuid, data->uuid)) { in read_type_cb()
1443 data->err = bt_gatt_check_perm(conn, attr, BT_GATT_PERM_READ_MASK); in read_type_cb()
1444 if (data->err) { in read_type_cb()
1445 if (data->rsp->len) { in read_type_cb()
1446 data->err = 0x00; in read_type_cb()
1453 data->err = BT_ATT_ERR_AUTHORIZATION; in read_type_cb()
1459 * should be changed from pre-set: attr not found error to no error. in read_type_cb()
1461 data->err = 0x00; in read_type_cb()
1464 data->item = net_buf_add(net_buf_frag_last(data->buf), in read_type_cb()
1465 sizeof(*data->item)); in read_type_cb()
1466 data->item->handle = sys_cpu_to_le16(handle); in read_type_cb()
1468 read = att_chan_read(chan, attr, data->buf, 0, attr_read_type_cb, data); in read_type_cb()
1470 data->err = err_to_att(read); in read_type_cb()
1474 if (!data->item) { in read_type_cb()
1479 return bt_att_mtu(chan) - net_buf_frags_len(data->buf) > in read_type_cb()
1480 data->rsp->len ? BT_GATT_ITER_CONTINUE : BT_GATT_ITER_STOP; in read_type_cb()
1498 data.rsp->len = 0U; in att_read_type_rsp()
1500 /* Pre-set error if no attr will be found in handle */ in att_read_type_rsp()
1527 uint8_t uuid_len = buf->len - sizeof(*req); in att_read_type_req()
1536 start_handle = sys_le16_to_cpu(req->start_handle); in att_read_type_req()
1537 end_handle = sys_le16_to_cpu(req->end_handle); in att_read_type_req()
1538 if (!bt_uuid_create(&u.uuid, req->uuid, uuid_len)) { in att_read_type_req()
1552 * Caching bit in the Client Supported Features characteristic) is change-unaware in att_read_type_req()
1562 if (!bt_gatt_change_aware(chan->chan.chan.conn, true)) { in att_read_type_req()
1567 if (!atomic_test_and_set_bit(chan->flags, ATT_OUT_OF_SYNC_SENT)) { in att_read_type_req()
1589 struct bt_att_chan *chan = data->chan; in read_cb()
1590 struct bt_conn *conn = chan->chan.chan.conn; in read_cb()
1597 * should be changed from pre-set: invalid handle error to no error. in read_cb()
1599 data->err = 0x00; in read_cb()
1602 data->err = bt_gatt_check_perm(conn, attr, BT_GATT_PERM_READ_MASK); in read_cb()
1603 if (data->err) { in read_cb()
1609 data->err = BT_ATT_ERR_AUTHORIZATION; in read_cb()
1614 ret = att_chan_read(chan, attr, data->buf, data->offset, NULL, NULL); in read_cb()
1616 data->err = err_to_att(ret); in read_cb()
1628 if (!bt_gatt_change_aware(chan->att->conn, true)) { in att_read_rsp()
1629 if (!atomic_test_and_set_bit(chan->flags, ATT_OUT_OF_SYNC_SENT)) { in att_read_rsp()
1650 /* Pre-set error if no attr will be found in handle */ in att_read_rsp()
1673 req = (void *)buf->data; in att_read_req()
1675 handle = sys_le16_to_cpu(req->handle); in att_read_req()
1688 req = (void *)buf->data; in att_read_blob_req()
1690 handle = sys_le16_to_cpu(req->handle); in att_read_blob_req()
1691 offset = sys_le16_to_cpu(req->offset); in att_read_blob_req()
1705 if (!bt_gatt_change_aware(chan->att->conn, true)) { in att_read_mult_req()
1706 if (!atomic_test_and_set_bit(chan->flags, ATT_OUT_OF_SYNC_SENT)) { in att_read_mult_req()
1722 while (buf->len >= sizeof(uint16_t)) { in att_read_mult_req()
1759 struct bt_att_chan *chan = data->chan; in read_vl_cb()
1760 struct bt_conn *conn = chan->chan.chan.conn; in read_vl_cb()
1768 * should be changed from pre-set: invalid handle error to no error. in read_vl_cb()
1770 data->err = 0x00; in read_vl_cb()
1773 data->err = bt_gatt_check_perm(conn, attr, BT_GATT_PERM_READ_MASK); in read_vl_cb()
1774 if (data->err) { in read_vl_cb()
1780 data->err = BT_ATT_ERR_AUTHORIZATION; in read_vl_cb()
1787 if (bt_att_mtu(chan) - data->buf->len < 2) { in read_vl_cb()
1791 rsp = net_buf_add(data->buf, sizeof(*rsp)); in read_vl_cb()
1793 read = att_chan_read(chan, attr, data->buf, data->offset, NULL, NULL); in read_vl_cb()
1795 data->err = err_to_att(read); in read_vl_cb()
1799 rsp->len = read; in read_vl_cb()
1809 if (!bt_gatt_change_aware(chan->att->conn, true)) { in att_read_mult_vl_req()
1810 if (!atomic_test_and_set_bit(chan->flags, ATT_OUT_OF_SYNC_SENT)) { in att_read_mult_vl_req()
1826 while (buf->len >= sizeof(uint16_t)) { in att_read_mult_vl_req()
1867 if (!data->rsp->len) { in attr_read_group_cb()
1869 data->rsp->len = read + sizeof(*data->group); in attr_read_group_cb()
1870 } else if (data->rsp->len != read + sizeof(*data->group)) { in attr_read_group_cb()
1872 data->buf->len -= sizeof(*data->group); in attr_read_group_cb()
1873 data->group = NULL; in attr_read_group_cb()
1884 struct bt_att_chan *chan = data->chan; in read_group_cb()
1888 if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) && in read_group_cb()
1889 bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) { in read_group_cb()
1890 if (data->group && in read_group_cb()
1891 handle > sys_le16_to_cpu(data->group->end_handle)) { in read_group_cb()
1892 data->group->end_handle = sys_cpu_to_le16(handle); in read_group_cb()
1898 if (bt_uuid_cmp(attr->uuid, data->uuid)) { in read_group_cb()
1899 data->group = NULL; in read_group_cb()
1906 if (data->rsp->len && in read_group_cb()
1907 bt_att_mtu(chan) - data->buf->len < data->rsp->len) { in read_group_cb()
1912 data->group = net_buf_add(data->buf, sizeof(*data->group)); in read_group_cb()
1915 data->group->start_handle = sys_cpu_to_le16(handle); in read_group_cb()
1916 data->group->end_handle = sys_cpu_to_le16(handle); in read_group_cb()
1919 read = att_chan_read(chan, attr, data->buf, 0, attr_read_group_cb, in read_group_cb()
1926 if (!data->group) { in read_group_cb()
1949 data.rsp->len = 0U; in att_read_group_rsp()
1954 if (!data.rsp->len) { in att_read_group_rsp()
1976 uint8_t uuid_len = buf->len - sizeof(*req); in att_read_group_req()
1985 start_handle = sys_le16_to_cpu(req->start_handle); in att_read_group_req()
1986 end_handle = sys_le16_to_cpu(req->end_handle); in att_read_group_req()
1988 if (!bt_uuid_create(&u.uuid, req->uuid, uuid_len)) { in att_read_group_req()
2035 if (!authorization_cb || !authorization_cb->write_authorize) { in attr_write_authorize()
2039 return authorization_cb->write_authorize(conn, attr); in attr_write_authorize()
2049 LOG_DBG("handle 0x%04x offset %u", handle, data->offset); in write_cb()
2052 data->err = bt_gatt_check_perm(data->conn, attr, in write_cb()
2054 if (data->err) { in write_cb()
2059 if (!attr_write_authorize(data->conn, attr)) { in write_cb()
2060 data->err = BT_ATT_ERR_AUTHORIZATION; in write_cb()
2065 if (!data->req) { in write_cb()
2067 } else if (data->req == BT_ATT_OP_EXEC_WRITE_REQ) { in write_cb()
2072 write = attr->write(data->conn, attr, data->value, data->len, in write_cb()
2073 data->offset, flags); in write_cb()
2074 if (write < 0 || write != data->len) { in write_cb()
2075 data->err = err_to_att(write); in write_cb()
2079 data->err = 0U; in write_cb()
2090 if (!bt_gatt_change_aware(chan->att->conn, req ? true : false)) { in att_write_rsp()
2091 if (!atomic_test_and_set_bit(chan->flags, ATT_OUT_OF_SYNC_SENT)) { in att_write_rsp()
2112 data.conn = chan->att->conn; in att_write_rsp()
2147 handle, 0, buf->data, buf->len); in att_write_req()
2167 LOG_DBG("handle 0x%04x offset %u", handle, data->offset); in prep_write_cb()
2170 data->err = bt_gatt_check_perm(data->conn, attr, in prep_write_cb()
2172 if (data->err) { in prep_write_cb()
2177 if (!attr_write_authorize(data->conn, attr)) { in prep_write_cb()
2178 data->err = BT_ATT_ERR_AUTHORIZATION; in prep_write_cb()
2183 if (!(attr->perm & BT_GATT_PERM_PREPARE_WRITE)) { in prep_write_cb()
2188 write = attr->write(data->conn, attr, data->value, data->len, in prep_write_cb()
2189 data->offset, BT_GATT_WRITE_FLAG_PREPARE); in prep_write_cb()
2191 data->err = err_to_att(write); in prep_write_cb()
2197 data->buf = net_buf_alloc(&prep_pool, K_NO_WAIT); in prep_write_cb()
2198 if (!data->buf) { in prep_write_cb()
2199 data->err = BT_ATT_ERR_PREPARE_QUEUE_FULL; in prep_write_cb()
2203 attr_data = net_buf_user_data(data->buf); in prep_write_cb()
2204 attr_data->handle = handle; in prep_write_cb()
2205 attr_data->offset = data->offset; in prep_write_cb()
2207 net_buf_add_mem(data->buf, data->value, data->len); in prep_write_cb()
2209 data->err = 0U; in prep_write_cb()
2220 if (!bt_gatt_change_aware(chan->att->conn, true)) { in att_prep_write_rsp()
2221 if (!atomic_test_and_set_bit(chan->flags, ATT_OUT_OF_SYNC_SENT)) { in att_prep_write_rsp()
2234 data.conn = chan->att->conn; in att_prep_write_rsp()
2252 net_buf_slist_put(&chan->att->prep_queue, data.buf); in att_prep_write_rsp()
2261 rsp->handle = sys_cpu_to_le16(handle); in att_prep_write_rsp()
2262 rsp->offset = sys_cpu_to_le16(offset); in att_prep_write_rsp()
2264 memcpy(rsp->value, value, len); in att_prep_write_rsp()
2282 handle = sys_le16_to_cpu(req->handle); in att_prepare_write_req()
2283 offset = sys_le16_to_cpu(req->offset); in att_prepare_write_req()
2287 return att_prep_write_rsp(chan, handle, offset, buf->data, buf->len); in att_prepare_write_req()
2303 LOG_DBG("entry %p handle 0x%04x, offset %u", entry, tmp_data->handle, in exec_write_reassemble()
2304 tmp_data->offset); in exec_write_reassemble()
2306 if (tmp_data->handle == handle) { in exec_write_reassemble()
2307 if (tmp_data->offset == 0) { in exec_write_reassemble()
2315 LOG_DBG("tmp_data->offset == 0"); in exec_write_reassemble()
2319 if (tmp_data->offset != buf->len + offset) { in exec_write_reassemble()
2324 LOG_DBG("Bad offset %u (%u, %u)", tmp_data->offset, buf->len, in exec_write_reassemble()
2330 if (buf->len + entry->len > buf->size) { in exec_write_reassemble()
2334 net_buf_simple_add_mem(buf, entry->data, entry->len); in exec_write_reassemble()
2335 sys_slist_remove(list, prev, &entry->node); in exec_write_reassemble()
2338 prev = &entry->node; in exec_write_reassemble()
2355 while (!sys_slist_is_empty(&chan->att->prep_queue)) { in att_exec_write_rsp()
2363 buf = net_buf_slist_get(&chan->att->prep_queue); in att_exec_write_rsp()
2365 handle = data->handle; in att_exec_write_rsp()
2367 LOG_DBG("buf %p handle 0x%04x offset %u", buf, handle, data->offset); in att_exec_write_rsp()
2370 net_buf_simple_add_mem(&reassembled_data, buf->data, buf->len); in att_exec_write_rsp()
2372 err = exec_write_reassemble(handle, data->offset, in att_exec_write_rsp()
2373 &chan->att->prep_queue, in att_exec_write_rsp()
2384 handle, data->offset, in att_exec_write_rsp()
2390 data->handle, err); in att_exec_write_rsp()
2421 req = (void *)buf->data; in att_exec_write_req()
2423 LOG_DBG("flags 0x%02x", req->flags); in att_exec_write_req()
2425 return att_exec_write_rsp(chan, req->flags); in att_exec_write_req()
2437 return att_write_rsp(chan, 0, 0, handle, 0, buf->data, buf->len); in att_write_cmd()
2443 struct bt_conn *conn = chan->chan.chan.conn; in att_signed_write_cmd()
2448 /* The Signed Write Without Response sub-procedure shall only be supported in att_signed_write_cmd()
2456 req = (void *)buf->data; in att_signed_write_cmd()
2458 handle = sys_le16_to_cpu(req->handle); in att_signed_write_cmd()
2474 return att_write_rsp(chan, 0, 0, handle, 0, buf->data, in att_signed_write_cmd()
2475 buf->len - sizeof(struct bt_att_signature)); in att_signed_write_cmd()
2487 if (conn->sec_level >= BT_SECURITY_L2) { in att_change_security()
2488 return -EALREADY; in att_change_security()
2493 if (conn->sec_level < BT_SECURITY_L2) { in att_change_security()
2505 } else if (conn->sec_level < BT_SECURITY_L3) { in att_change_security()
2520 } else if (conn->sec_level < BT_SECURITY_L4) { in att_change_security()
2524 * If LE Secure Connections authenticated pairing is in att_change_security()
2532 return -EALREADY; in att_change_security()
2536 return -EINVAL; in att_change_security()
2548 rsp = (void *)buf->data; in att_error_rsp()
2550 LOG_DBG("request 0x%02x handle 0x%04x error 0x%02x", rsp->request, in att_error_rsp()
2551 sys_le16_to_cpu(rsp->handle), rsp->error); in att_error_rsp()
2564 if (!chan->req || chan->req == &cancel || !rsp->error) { in att_error_rsp()
2569 err = rsp->error; in att_error_rsp()
2575 ret = att_change_security(chan->chan.chan.conn, err); in att_error_rsp()
2576 if (ret == 0 || ret == -EBUSY) { in att_error_rsp()
2581 k_work_cancel_delayable(&chan->timeout_work); in att_error_rsp()
2583 chan->req->retrying = true; in att_error_rsp()
2597 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_find_info_rsp()
2605 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_find_type_rsp()
2613 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_read_type_rsp()
2621 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_read_rsp()
2629 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_read_blob_rsp()
2638 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_read_mult_rsp()
2649 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_read_mult_vl_rsp()
2658 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_read_group_rsp()
2666 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_write_rsp()
2674 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_prepare_write_rsp()
2682 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_handle_exec_write_rsp()
2693 bt_gatt_notification(chan->att->conn, handle, buf->data, buf->len); in att_notify()
2706 bt_gatt_notification(chan->att->conn, handle, buf->data, buf->len); in att_indicate()
2722 bt_gatt_mult_notification(chan->att->conn, buf->data, buf->len); in att_notify_mult()
2732 return att_handle_rsp(chan, buf->data, buf->len, 0); in att_confirm()
2931 return att_chan->chan.chan.conn; in get_conn()
2943 if (buf->len < sizeof(*hdr)) { in bt_att_recv()
2949 LOG_DBG("Received ATT chan %p code 0x%02x len %zu", att_chan, hdr->code, in bt_att_recv()
2952 if (conn->state != BT_CONN_CONNECTED) { in bt_att_recv()
2953 LOG_DBG("not connected: conn %p state %u", conn, conn->state); in bt_att_recv()
2957 if (!att_chan->att) { in bt_att_recv()
2963 if (hdr->code == handlers[i].op) { in bt_att_recv()
2970 LOG_WRN("Unhandled ATT code 0x%02x", hdr->code); in bt_att_recv()
2971 if (att_op_get_type(hdr->code) != ATT_COMMAND && in bt_att_recv()
2972 att_op_get_type(hdr->code) != ATT_INDICATION) { in bt_att_recv()
2973 send_err_rsp(att_chan, hdr->code, 0, in bt_att_recv()
2979 if (buf->len < handler->expect_len) { in bt_att_recv()
2980 LOG_ERR("Invalid len %u for code 0x%02x", buf->len, hdr->code); in bt_att_recv()
2983 err = handler->func(att_chan, buf); in bt_att_recv()
2986 if (handler->type == ATT_REQUEST && err) { in bt_att_recv()
2988 send_err_rsp(att_chan, hdr->code, 0, err); in bt_att_recv()
2999 if (conn->state != BT_CONN_CONNECTED) { in att_get()
3011 if (!atomic_test_bit(att_chan->flags, ATT_CONNECTED)) { in att_get()
3016 return att_chan->att; in att_get()
3030 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { in bt_att_create_pdu()
3065 data->att_chan = chan; in bt_att_create_rsp_pdu()
3068 hdr->code = op; in bt_att_create_rsp_pdu()
3079 while ((buf = net_buf_slist_get(&att->prep_queue))) { in att_reset()
3087 (void)k_work_cancel_delayable_sync(&att->eatt.connection_work, &sync); in att_reset()
3090 while ((buf = k_fifo_get(&att->tx_queue, K_NO_WAIT))) { in att_reset()
3095 while (!sys_slist_is_empty(&att->reqs)) { in att_reset()
3099 node = sys_slist_get_not_empty(&att->reqs); in att_reset()
3101 if (req->func) { in att_reset()
3102 req->func(att->conn, -ECONNRESET, NULL, 0, in att_reset()
3103 req->user_data); in att_reset()
3109 /* FIXME: `att->conn` is not reference counted. Consider using `bt_conn_ref` in att_reset()
3112 att->conn = NULL; in att_reset()
3122 sys_slist_find_and_remove(&chan->att->chans, &chan->node); in att_chan_detach()
3125 while ((buf = k_fifo_get(&chan->tx_queue, K_NO_WAIT))) { in att_chan_detach()
3129 if (chan->req) { in att_chan_detach()
3131 att_handle_rsp(chan, NULL, 0, -ECONNRESET); in att_chan_detach()
3134 chan->att = NULL; in att_chan_detach()
3135 atomic_clear_bit(chan->flags, ATT_CONNECTED); in att_chan_detach()
3146 bt_addr_le_to_str(bt_conn_get_dst(chan->att->conn), addr, sizeof(addr)); in att_timeout()
3157 bt_att_disconnected(&chan->chan.chan); in att_timeout()
3164 err = bt_conn_disconnect(chan->chan.chan.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); in att_timeout()
3182 LOG_DBG("att %p chan %p flags %lu", att, chan, atomic_get(chan->flags)); in att_chan_attach()
3184 if (sys_slist_is_empty(&att->chans)) { in att_chan_attach()
3186 k_fifo_init(&att->tx_queue); in att_chan_attach()
3188 sys_slist_init(&att->prep_queue); in att_chan_attach()
3192 sys_slist_prepend(&att->chans, &chan->node); in att_chan_attach()
3200 LOG_DBG("chan %p cid 0x%04x", le_chan, le_chan->tx.cid); in bt_att_connected()
3202 atomic_set_bit(att_chan->flags, ATT_CONNECTED); in bt_att_connected()
3206 k_work_init_delayable(&att_chan->timeout_work, att_timeout); in bt_att_connected()
3208 bt_gatt_connected(le_chan->chan.conn); in bt_att_connected()
3214 struct bt_att *att = att_chan->att; in bt_att_disconnected()
3217 LOG_DBG("chan %p cid 0x%04x", le_chan, le_chan->tx.cid); in bt_att_disconnected()
3219 if (!att_chan->att) { in bt_att_disconnected()
3227 if (!sys_slist_is_empty(&att->chans)) { in bt_att_disconnected()
3233 bt_gatt_disconnected(le_chan->chan.conn); in bt_att_disconnected()
3239 struct bt_att_req *req = att_chan->req; in att_req_retry()
3243 if (!req->encode) { in att_req_retry()
3249 buf = bt_att_chan_create_pdu(att_chan, req->att_op, req->len); in att_req_retry()
3254 if (req->encode(buf, req->len, req->user_data)) { in att_req_retry()
3272 struct bt_conn *conn = le_chan->chan.conn; in bt_att_encrypt_change()
3276 conn->handle, conn->sec_level, hci_status, bt_hci_err_to_str(hci_status)); in bt_att_encrypt_change()
3278 if (!att_chan->att) { in bt_att_encrypt_change()
3284 * If status (HCI status of security procedure) is non-zero, notify in bt_att_encrypt_change()
3288 if (att_chan->req && att_chan->req->retrying) { in bt_att_encrypt_change()
3298 if (conn->sec_level == BT_SECURITY_L1) { in bt_att_encrypt_change()
3302 if (!(att_chan->req && att_chan->req->retrying)) { in bt_att_encrypt_change()
3327 if (!chan->att) { in bt_att_status()
3333 if (chan->req) { in bt_att_status()
3338 node = sys_slist_get(&chan->att->reqs); in bt_att_status()
3348 sys_slist_prepend(&chan->att->reqs, node); in bt_att_status()
3390 SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { in att_chan_new()
3391 if (chan->att == att) { in att_chan_new()
3402 LOG_WRN("No available ATT channel for conn %p", att->conn); in att_chan_new()
3407 chan->chan.chan.ops = &ops; in att_chan_new()
3408 k_fifo_init(&chan->tx_queue); in att_chan_new()
3409 atomic_set(chan->flags, flags); in att_chan_new()
3410 chan->att = att; in att_chan_new()
3415 * TX MTU is received on L2CAP-level. in att_chan_new()
3417 chan->chan.rx.mtu = BT_LOCAL_ATT_MTU_EATT; in att_chan_new()
3423 chan->chan.tx.mtu = BT_ATT_DEFAULT_LE_MTU; in att_chan_new()
3424 chan->chan.rx.mtu = BT_ATT_DEFAULT_LE_MTU; in att_chan_new()
3446 SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { in bt_eatt_count()
3448 atomic_test_bit(chan->flags, ATT_CONNECTED)) { in bt_eatt_count()
3460 const int err = bt_eatt_connect(att->conn, att->eatt.chans_to_connect); in att_enhanced_connection_work_handler()
3462 if (err == -ENOMEM) { in att_enhanced_connection_work_handler()
3465 att->eatt.chans_to_connect); in att_enhanced_connection_work_handler()
3467 LOG_WRN("Failed to connect %d EATT channels (err: %d)", att->eatt.chans_to_connect, in att_enhanced_connection_work_handler()
3479 LOG_DBG("conn %p handle %u", conn, conn->handle); in bt_att_accept()
3483 return -ENOMEM; in bt_att_accept()
3489 att->conn = conn; in bt_att_accept()
3490 sys_slist_init(&att->reqs); in bt_att_accept()
3491 sys_slist_init(&att->chans); in bt_att_accept()
3494 k_work_init_delayable(&att->eatt.connection_work, in bt_att_accept()
3500 return -ENOMEM; in bt_att_accept()
3503 *ch = &chan->chan.chan; in bt_att_accept()
3525 if (IS_ENABLED(CONFIG_BT_CENTRAL) && conn->role == BT_CONN_ROLE_CENTRAL) { in credit_based_connection_delay()
3539 * 4000000000 which can be stored in 32-bits, so this won't in credit_based_connection_delay()
3543 2 * (conn->le.latency + 1) * BT_CONN_INTERVAL_TO_US(conn->le.interval); in credit_based_connection_delay()
3559 return -ENOTCONN; in att_schedule_eatt_connect()
3562 att->eatt.chans_to_connect = chans_to_connect; in att_schedule_eatt_connect()
3564 return k_work_reschedule(&att->eatt.connection_work, in att_schedule_eatt_connect()
3573 size_t to_connect = att->eatt.prev_conn_req_missing_chans; in handle_potential_collision()
3575 if (att->eatt.prev_conn_rsp_result == BT_L2CAP_LE_ERR_NO_RESOURCES && in handle_potential_collision()
3576 att->eatt.prev_conn_req_result == BT_L2CAP_LE_ERR_NO_RESOURCES) { in handle_potential_collision()
3580 att->eatt.prev_conn_rsp_result = 0; in handle_potential_collision()
3581 att->eatt.prev_conn_req_result = 0; in handle_potential_collision()
3582 att->eatt.prev_conn_req_missing_chans = 0; in handle_potential_collision()
3588 err = att_schedule_eatt_connect(att->conn, to_connect); in handle_potential_collision()
3608 att->eatt.prev_conn_rsp_result = result; in ecred_connect_req_cb()
3628 att->eatt.prev_conn_req_result = result; in ecred_connect_rsp_cb()
3629 att->eatt.prev_conn_req_missing_chans = in ecred_connect_rsp_cb()
3630 attempted_to_connect - succeeded_to_connect; in ecred_connect_rsp_cb()
3645 return -EINVAL; in bt_eatt_connect()
3653 return -EPERM; in bt_eatt_connect()
3657 return -EINVAL; in bt_eatt_connect()
3661 att = att_chan->att; in bt_eatt_connect()
3663 while (num_channels--) { in bt_eatt_connect()
3669 chan[i] = &att_chan->chan.chan; in bt_eatt_connect()
3674 return -ENOMEM; in bt_eatt_connect()
3679 * elements of the array or until a null-terminator is reached. in bt_eatt_connect()
3720 int err = -ENOTCONN; in bt_eatt_disconnect()
3723 return -EINVAL; in bt_eatt_disconnect()
3727 att = chan->att; in bt_eatt_disconnect()
3729 SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { in bt_eatt_disconnect()
3731 err = bt_l2cap_chan_disconnect(&chan->chan.chan); in bt_eatt_disconnect()
3745 return -EINVAL; in bt_eatt_disconnect_one()
3749 att = chan->att; in bt_eatt_disconnect_one()
3751 SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { in bt_eatt_disconnect_one()
3753 return bt_l2cap_chan_disconnect(&chan->chan.chan); in bt_eatt_disconnect_one()
3757 return -ENOTCONN; in bt_eatt_disconnect_one()
3763 struct bt_att *att = att_chan->att; in bt_eatt_reconfigure()
3769 SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, att_chan, node) { in bt_eatt_reconfigure()
3771 chans[i] = &att_chan->chan.chan; in bt_eatt_reconfigure()
3778 * elements of the array or until a null-terminator is reached. in bt_eatt_reconfigure()
3797 struct bt_att *att = att_chan->att; in bt_eatt_accept()
3799 LOG_DBG("conn %p handle %u", conn, conn->handle); in bt_eatt_accept()
3803 *chan = &att_chan->chan.chan; in bt_eatt_accept()
3807 return -ENOMEM; in bt_eatt_accept()
3861 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { in bt_att_get_mtu()
3880 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { in bt_att_get_uatt_mtu()
3893 struct bt_att *att = updated_chan->att; in att_chan_mtu_updated()
3898 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { in att_chan_mtu_updated()
3902 max_tx = MAX(max_tx, chan->chan.tx.mtu); in att_chan_mtu_updated()
3903 max_rx = MAX(max_rx, chan->chan.rx.mtu); in att_chan_mtu_updated()
3907 if ((updated_chan->chan.tx.mtu > max_tx) || in att_chan_mtu_updated()
3908 (updated_chan->chan.rx.mtu > max_rx)) { in att_chan_mtu_updated()
3909 max_tx = MAX(max_tx, updated_chan->chan.tx.mtu); in att_chan_mtu_updated()
3910 max_rx = MAX(max_rx, updated_chan->chan.rx.mtu); in att_chan_mtu_updated()
3911 bt_gatt_att_max_mtu_changed(att->conn, max_tx, max_rx); in att_chan_mtu_updated()
3944 if (req->buf) { in bt_att_req_free()
3945 net_buf_unref(req->buf); in bt_att_req_free()
3946 req->buf = NULL; in bt_att_req_free()
3962 return -ENOTCONN; in bt_att_send()
3965 k_fifo_put(&att->tx_queue, buf); in bt_att_send()
3985 return -ENOTCONN; in bt_att_req_send()
3988 sys_slist_append(&att->reqs, &req->node); in bt_att_req_send()
3999 if (chan->req != req) { in bt_att_chan_req_cancel()
4003 chan->req = &cancel; in bt_att_chan_req_cancel()
4026 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) { in bt_att_req_cancel()
4034 sys_slist_find_and_remove(&att->reqs, &req->node); in bt_att_req_cancel()
4050 SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { in bt_att_find_req_by_user_data()
4051 if (chan->req->user_data == user_data) { in bt_att_find_req_by_user_data()
4052 return chan->req; in bt_att_find_req_by_user_data()
4056 SYS_SLIST_FOR_EACH_CONTAINER(&att->reqs, req, node) { in bt_att_find_req_by_user_data()
4057 if (req->user_data == user_data) { in bt_att_find_req_by_user_data()
4083 SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) { in bt_att_clear_out_of_sync_sent()
4084 atomic_clear_bit(chan->flags, ATT_OUT_OF_SYNC_SENT); in bt_att_clear_out_of_sync_sent()
4099 return atomic_test_bit(att_chan->flags, ATT_OUT_OF_SYNC_SENT); in bt_att_out_of_sync_sent_on_fixed()
4107 data->func = func; in bt_att_set_tx_meta_data()
4108 data->user_data = user_data; in bt_att_set_tx_meta_data()
4109 data->attr_count = 1; in bt_att_set_tx_meta_data()
4110 data->chan_opt = chan_opt; in bt_att_set_tx_meta_data()
4117 data->attr_count += attr_count; in bt_att_increment_tx_meta_data_attr_count()
4125 return ((meta->func == func) && in bt_att_tx_meta_data_match()
4126 (meta->user_data == user_data) && in bt_att_tx_meta_data_match()
4127 (meta->chan_opt == chan_opt)); in bt_att_tx_meta_data_match()
4150 return -ENOSYS; in bt_gatt_authorization_cb_register()
4159 return -EALREADY; in bt_gatt_authorization_cb_register()