Lines Matching +full:- +full:sc

1 /* gatt.c - Generic Attribute Profile handling */
4 * Copyright (c) 2015-2016 Intel Corporation
7 * SPDX-License-Identifier: Apache-2.0
287 SC_RANGE_CHANGED, /* SC range changed */
288 SC_INDICATE_PENDING, /* SC indicate pending */
289 SC_LOAD, /* SC has been loaded from settings */
295 /* Total number of flags - must be at the end of the enum */
339 err = bt_settings_store_sc(cfg->id, &cfg->peer, &cfg->data, sizeof(cfg->data)); in sc_store()
341 LOG_ERR("failed to store SC (err %d)", err); in sc_store()
345 LOG_DBG("stored SC for %s (0x%04x-0x%04x)", bt_addr_le_str(&cfg->peer), cfg->data.start, in sc_store()
346 cfg->data.end); in sc_store()
367 err = bt_settings_delete_sc(cfg->id, &cfg->peer); in bt_gatt_clear_sc()
369 LOG_ERR("failed to delete SC (err %d)", err); in bt_gatt_clear_sc()
371 LOG_DBG("deleted SC for %s", bt_addr_le_str(&cfg->peer)); in bt_gatt_clear_sc()
382 if (bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { in sc_clear()
385 err = bt_gatt_clear_sc(conn->id, &conn->le.dst); in sc_clear()
387 LOG_ERR("Failed to clear SC %d", err); in sc_clear()
392 cfg = find_sc_cfg(conn->id, &conn->le.dst); in sc_clear()
401 LOG_DBG("peer %s", bt_addr_le_str(&cfg->peer)); in sc_reset()
403 memset(&cfg->data, 0, sizeof(cfg->data)); in sc_reset()
445 LOG_ERR("unable to save SC: no cfg left"); in sc_save()
449 cfg->id = id; in sc_save()
450 bt_addr_le_copy(&cfg->peer, peer); in sc_save()
454 if (!(cfg->data.start || cfg->data.end)) { in sc_save()
455 cfg->data.start = start; in sc_save()
456 cfg->data.end = end; in sc_save()
461 modified = update_range(&cfg->data.start, &cfg->data.end, start, end); in sc_save()
465 modified && bt_addr_le_is_bonded(cfg->id, &cfg->peer)) { in sc_save()
476 /* Create a new SC configuration entry if subscribed */ in sc_ccc_cfg_write()
477 sc_save(conn->id, &conn->le.dst, 0, 0); in sc_ccc_cfg_write()
496 /* Total number of flags - must be at the end of the enum */
509 #define CF_ROBUST_CACHING(_cfg) (_cfg->data[0] & BIT(CF_BIT_ROBUST_CACHING))
510 #define CF_EATT(_cfg) (_cfg->data[0] & BIT(CF_BIT_EATT))
511 #define CF_NOTIFY_MULTI(_cfg) (_cfg->data[0] & BIT(CF_BIT_NOTIFY_MULTI))
530 bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY); in clear_cf_cfg()
531 memset(cfg->data, 0, sizeof(cfg->data)); in clear_cf_cfg()
532 atomic_set(cfg->flags, 0); in clear_cf_cfg()
552 changed = !atomic_test_and_set_bit(cfg->flags, CF_CHANGE_AWARE); in set_change_aware_no_store()
554 changed = atomic_test_and_clear_bit(cfg->flags, CF_CHANGE_AWARE); in set_change_aware_no_store()
557 LOG_DBG("peer is now change-%saware", aware ? "" : "un"); in set_change_aware_no_store()
568 gatt_delayed_store_enqueue(cfg->id, &cfg->peer, DELAYED_STORE_CF); in set_change_aware()
580 /* Mark all bonded peers as change-unaware. in set_all_change_unaware()
581 * - Can be called when not in a connection with said peers in set_all_change_unaware()
582 * - Doesn't have any effect when no bonds are in memory. This is the in set_all_change_unaware()
585 * - Expensive to call, as it will write the new status to settings in set_all_change_unaware()
591 if (!bt_addr_le_eq(&cfg->peer, BT_ADDR_LE_ANY)) { in set_all_change_unaware()
593 bt_gatt_store_cf(cfg->id, &cfg->peer); in set_all_change_unaware()
607 if (bt_addr_le_eq(&cfg->peer, BT_ADDR_LE_ANY)) { in find_cf_cfg()
610 } else if (bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) { in find_cf_cfg()
626 memcpy(data, cfg->data, sizeof(data)); in cf_read()
639 if ((cfg->data[i / 8] & BIT(i % 8)) && in cf_set_value()
648 if (i == (CF_NUM_BYTES - 1)) { in cf_set_value()
649 cfg->data[i] |= value[i] & BIT_MASK(CF_NUM_BITS % BITS_PER_BYTE); in cf_set_value()
651 cfg->data[i] |= value[i]; in cf_set_value()
654 LOG_DBG("byte %u: data 0x%02x value 0x%02x", i, cfg->data[i], value[i]); in cf_set_value()
666 if (offset > sizeof(cfg->data)) { in cf_write()
670 if (offset + len > sizeof(cfg->data)) { in cf_write()
684 LOG_DBG("handle 0x%04x len %u", attr->handle, len); in cf_write()
690 bt_addr_le_copy(&cfg->peer, &conn->le.dst); in cf_write()
691 cfg->id = conn->id; in cf_write()
712 if (psa_import_key(&key_attr, key, 16, &(state->key)) != PSA_SUCCESS) { in db_hash_setup()
714 return -EIO; in db_hash_setup()
716 state->operation = psa_mac_operation_init(); in db_hash_setup()
717 if (psa_mac_sign_setup(&(state->operation), state->key, in db_hash_setup()
720 return -EIO; in db_hash_setup()
727 if (psa_mac_update(&(state->operation), data, len) != PSA_SUCCESS) { in db_hash_update()
729 return -EIO; in db_hash_update()
738 if (psa_mac_sign_finish(&(state->operation), db_hash.hash, 16, in db_hash_finish()
741 return -EIO; in db_hash_finish()
790 if (attr->uuid->type != BT_UUID_TYPE_16) { in gen_hash_m()
794 u16 = (struct bt_uuid_16 *)attr->uuid; in gen_hash_m()
796 switch (u16->val) { in gen_hash_m()
806 state->err = -EINVAL; in gen_hash_m()
810 value = sys_cpu_to_le16(u16->val); in gen_hash_m()
812 sizeof(u16->val)) != 0) { in gen_hash_m()
813 state->err = -EINVAL; in gen_hash_m()
817 len = attr->read(NULL, attr, data, sizeof(data), 0); in gen_hash_m()
819 state->err = len; in gen_hash_m()
824 state->err = -EINVAL; in gen_hash_m()
838 state->err = -EINVAL; in gen_hash_m()
842 value = sys_cpu_to_le16(u16->val); in gen_hash_m()
844 sizeof(u16->val)) != 0) { in gen_hash_m()
845 state->err = -EINVAL; in gen_hash_m()
888 * However Vol 3, Part F, 3.3.1 says that multi-octet Characteristic in db_hash_gen()
938 /* Check if hash matches then skip SC update */ in do_db_hash()
951 * re-registered on boot. in do_db_hash()
953 * database range to invalidate client-side cache and force in do_db_hash()
960 * change-unaware. in do_db_hash()
993 * A connected client becomes change-aware when... in db_hash_read()
1000 !atomic_test_bit(cfg->flags, CF_CHANGE_AWARE)) { in db_hash_read()
1001 atomic_set_bit(cfg->flags, CF_DB_HASH_READ); in db_hash_read()
1023 if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { in remove_cf_cfg()
1027 bt_addr_le_copy(&cfg->peer, &conn->le.dst); in remove_cf_cfg()
1065 str = (char *)cfg->data; in bt_gatt_store_cf()
1066 len = sizeof(cfg->data); in bt_gatt_store_cf()
1071 /* add the change-aware flag */ in bt_gatt_store_cf()
1072 bool is_change_aware = atomic_test_bit(cfg->flags, CF_CHANGE_AWARE); in bt_gatt_store_cf()
1096 return (attr->write == bt_gatt_attr_write_ccc); in is_host_managed_ccc()
1119 ccc = attr->user_data; in convert_to_id_on_match()
1124 for (size_t i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in convert_to_id_on_match()
1125 if (bt_addr_le_eq(&ccc->cfg[i].peer, match->private_addr)) { in convert_to_id_on_match()
1126 bt_addr_le_copy(&ccc->cfg[i].peer, match->id_addr); in convert_to_id_on_match()
1141 bool is_bonded = bt_addr_le_is_bonded(conn->id, &conn->le.dst); in bt_gatt_identity_resolved()
1147 bt_gatt_store_ccc(conn->id, &conn->le.dst); in bt_gatt_identity_resolved()
1151 struct gatt_cf_cfg *cfg = find_cf_cfg_by_addr(conn->id, private_addr); in bt_gatt_identity_resolved()
1154 bt_addr_le_copy(&cfg->peer, id_addr); in bt_gatt_identity_resolved()
1156 bt_gatt_store_cf(conn->id, &conn->le.dst); in bt_gatt_identity_resolved()
1165 bt_gatt_store_ccc(conn->id, &(conn->le.dst)); in bt_gatt_pairing_complete()
1166 bt_gatt_store_cf(conn->id, &conn->le.dst); in bt_gatt_pairing_complete()
1223 if (last_handle == 0 || svc->attrs[0].handle > last_handle) { in gatt_insert()
1224 sys_slist_append(&db, &svc->node); in gatt_insert()
1230 if (tmp->attrs[0].handle > svc->attrs[0].handle) { in gatt_insert()
1232 sys_slist_insert(&db, &prev->node, &svc->node); in gatt_insert()
1234 sys_slist_prepend(&db, &svc->node); in gatt_insert()
1247 struct bt_gatt_attr *attrs = svc->attrs; in gatt_register()
1248 uint16_t count = svc->attr_count; in gatt_register()
1257 handle = last->attrs[last->attr_count - 1].handle; in gatt_register()
1262 for (; attrs && count; attrs++, count--) { in gatt_register()
1263 attrs->_auto_assigned_handle = 0; in gatt_register()
1264 if (!attrs->handle) { in gatt_register()
1266 attrs->handle = ++handle; in gatt_register()
1267 attrs->_auto_assigned_handle = 1; in gatt_register()
1268 } else if (attrs->handle > handle) { in gatt_register()
1270 handle = attrs->handle; in gatt_register()
1271 } else if (find_attr(attrs->handle)) { in gatt_register()
1273 LOG_ERR("Unable to register handle 0x%04x", attrs->handle); in gatt_register()
1274 return -EINVAL; in gatt_register()
1277 LOG_DBG("attr %p handle 0x%04x uuid %s perm 0x%02x", attrs, attrs->handle, in gatt_register()
1278 bt_uuid_str(attrs->uuid), attrs->perm); in gatt_register()
1315 * ... a change-unaware connected client using exactly one ATT bearer in sc_indicate_rsp()
1316 * becomes change-aware when ... in sc_indicate_rsp()
1332 struct gatt_sc *sc = CONTAINER_OF(dwork, struct gatt_sc, work); in sc_process() local
1335 __ASSERT(!atomic_test_bit(sc->flags, SC_INDICATE_PENDING), in sc_process()
1338 LOG_DBG("start 0x%04x end 0x%04x", sc->start, sc->end); in sc_process()
1340 sc_range[0] = sys_cpu_to_le16(sc->start); in sc_process()
1341 sc_range[1] = sys_cpu_to_le16(sc->end); in sc_process()
1343 atomic_clear_bit(sc->flags, SC_RANGE_CHANGED); in sc_process()
1344 sc->start = 0U; in sc_process()
1345 sc->end = 0U; in sc_process()
1347 sc->params.attr = &_1_gatt_svc.attrs[2]; in sc_process()
1348 sc->params.func = sc_indicate_rsp; in sc_process()
1349 sc->params.data = &sc_range[0]; in sc_process()
1350 sc->params.len = sizeof(sc_range); in sc_process()
1352 sc->params.chan_opt = BT_ATT_CHAN_OPT_NONE; in sc_process()
1355 if (bt_gatt_indicate(NULL, &sc->params)) { in sc_process()
1360 atomic_set_bit(sc->flags, SC_INDICATE_PENDING); in sc_process()
1366 bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY); in clear_ccc_cfg()
1367 cfg->id = 0U; in clear_ccc_cfg()
1368 cfg->value = 0U; in clear_ccc_cfg()
1395 if (el->id == id && in gatt_delayed_store_find()
1396 bt_addr_le_eq(peer_addr, &el->peer)) { in gatt_delayed_store_find()
1408 el->id = 0; in gatt_delayed_store_free()
1409 memset(&el->peer, 0, sizeof(el->peer)); in gatt_delayed_store_free()
1410 atomic_set(el->flags, 0); in gatt_delayed_store_free()
1427 if (atomic_get(el->flags) == 0) { in gatt_delayed_store_alloc()
1428 bt_addr_le_copy(&el->peer, peer_addr); in gatt_delayed_store_alloc()
1429 el->id = id; in gatt_delayed_store_alloc()
1450 atomic_set_bit(el->flags, flag); in gatt_delayed_store_enqueue()
1465 el = &store->peer_list[i]; in delayed_store()
1467 gatt_store_ccc_cf(el->id, &el->peer); in delayed_store()
1479 atomic_test_and_clear_bit(el->flags, DELAYED_STORE_CCC))) { in gatt_store_ccc_cf()
1485 atomic_test_and_clear_bit(el->flags, DELAYED_STORE_CF))) { in gatt_store_ccc_cf()
1489 if (el && atomic_get(el->flags) == 0) { in gatt_store_ccc_cf()
1502 last_static_handle += svc->attr_count; in bt_gatt_service_init()
1530 /* Make sure to not send SC indications until SC in bt_gatt_init()
1559 * brand-new peer. in bt_gatt_init()
1594 sys_slist_append(&callback_list, &cb->node); in bt_gatt_cb_register()
1615 if (bt_addr_le_eq(&cfg->peer, BT_ADDR_LE_ANY)) { in db_changed()
1622 * becomes change-aware in which case the error response in db_changed()
1625 conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cfg->peer); in db_changed()
1631 atomic_clear_bit(cfg->flags, CF_DB_HASH_READ); in db_changed()
1640 ccc->value = 0; in gatt_unregister_ccc()
1642 for (size_t i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in gatt_unregister_ccc()
1643 struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; in gatt_unregister_ccc()
1645 if (!bt_addr_le_eq(&cfg->peer, BT_ADDR_LE_ANY)) { in gatt_unregister_ccc()
1649 conn = bt_conn_lookup_addr_le(cfg->id, &cfg->peer); in gatt_unregister_ccc()
1651 if (conn->state == BT_CONN_CONNECTED) { in gatt_unregister_ccc()
1653 gatt_delayed_store_enqueue(conn->id, in gatt_unregister_ccc()
1654 &conn->le.dst, in gatt_unregister_ccc()
1664 bt_addr_le_is_bonded(cfg->id, &cfg->peer)) { in gatt_unregister_ccc()
1665 bt_gatt_store_ccc(cfg->id, &cfg->peer); in gatt_unregister_ccc()
1675 if (!sys_slist_find_and_remove(&db, &svc->node)) { in gatt_unregister()
1676 return -ENOENT; in gatt_unregister()
1679 for (uint16_t i = 0; i < svc->attr_count; i++) { in gatt_unregister()
1680 struct bt_gatt_attr *attr = &svc->attrs[i]; in gatt_unregister()
1683 gatt_unregister_ccc(attr->user_data); in gatt_unregister()
1687 if (attr->_auto_assigned_handle) { in gatt_unregister()
1688 attr->handle = 0; in gatt_unregister()
1689 attr->_auto_assigned_handle = 0; in gatt_unregister()
1701 __ASSERT(svc->attrs, "invalid parameters\n"); in bt_gatt_service_register()
1702 __ASSERT(svc->attr_count, "invalid parameters\n"); in bt_gatt_service_register()
1708 return -EINVAL; in bt_gatt_service_register()
1715 if (!bt_uuid_cmp(svc->attrs[0].uuid, BT_UUID_GAP) || in bt_gatt_service_register()
1716 !bt_uuid_cmp(svc->attrs[0].uuid, BT_UUID_GATT)) { in bt_gatt_service_register()
1717 return -EALREADY; in bt_gatt_service_register()
1734 sc_indicate(svc->attrs[0].handle, in bt_gatt_service_register()
1735 svc->attrs[svc->attr_count - 1].handle); in bt_gatt_service_register()
1752 /* gatt_unregister() clears handles when those were auto-assigned in bt_gatt_service_unregister()
1755 sc_start_handle = svc->attrs[0].handle; in bt_gatt_service_unregister()
1756 sc_end_handle = svc->attrs[svc->attr_count - 1].handle; in bt_gatt_service_unregister()
1788 if (&svc->node == node) { in bt_gatt_service_is_registered()
1819 len = MIN(buf_len, value_len - offset); in bt_gatt_attr_read()
1823 LOG_DBG("handle 0x%04x offset %u length %u", attr->handle, offset, len); in bt_gatt_attr_read()
1832 const struct bt_uuid *uuid = attr->user_data; in bt_gatt_attr_read_service()
1834 if (uuid->type == BT_UUID_TYPE_16) { in bt_gatt_attr_read_service()
1835 uint16_t uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); in bt_gatt_attr_read_service()
1842 BT_UUID_128(uuid)->val, 16); in bt_gatt_attr_read_service()
1857 if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) || in get_service_handles()
1858 !bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) { in get_service_handles()
1862 include->end_handle = sys_cpu_to_le16(handle); in get_service_handles()
1875 if (attr->handle) { in bt_gatt_attr_get_handle()
1876 return attr->handle; in bt_gatt_attr_get_handle()
1881 if ((attr < &static_svc->attrs[0]) || in bt_gatt_attr_get_handle()
1882 (attr > &static_svc->attrs[static_svc->attr_count - 1])) { in bt_gatt_attr_get_handle()
1883 handle += static_svc->attr_count; in bt_gatt_attr_get_handle()
1887 for (size_t i = 0; i < static_svc->attr_count; i++, handle++) { in bt_gatt_attr_get_handle()
1888 if (attr == &static_svc->attrs[i]) { in bt_gatt_attr_get_handle()
1901 struct bt_gatt_attr *incl = attr->user_data; in bt_gatt_attr_read_included()
1903 struct bt_uuid *uuid = incl->user_data; in bt_gatt_attr_read_included()
1914 * 16-bit Bluetooth UUID. in bt_gatt_attr_read_included()
1916 if (uuid->type == BT_UUID_TYPE_16) { in bt_gatt_attr_read_included()
1917 pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); in bt_gatt_attr_read_included()
1940 if (attr != NULL && bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC) == 0) { in bt_gatt_attr_value_handle()
1941 struct bt_gatt_chrc *chrc = attr->user_data; in bt_gatt_attr_value_handle()
1943 handle = chrc->value_handle; in bt_gatt_attr_value_handle()
1957 struct bt_gatt_chrc *chrc = attr->user_data; in bt_gatt_attr_read_chrc()
1961 pdu.properties = chrc->properties; in bt_gatt_attr_read_chrc()
1973 if (chrc->uuid->type == BT_UUID_TYPE_16) { in bt_gatt_attr_read_chrc()
1974 pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(chrc->uuid)->val); in bt_gatt_attr_read_chrc()
1977 memcpy(pdu.uuid, BT_UUID_128(chrc->uuid)->val, 16); in bt_gatt_attr_read_chrc()
2004 if (uuid && bt_uuid_cmp(uuid, attr->uuid)) { in gatt_foreach_iter()
2009 if (attr_data && attr_data != attr->user_data) { in gatt_foreach_iter()
2013 *num_matches -= 1; in gatt_foreach_iter()
2039 if (next->attrs[0].handle <= start_handle) { in foreach_attr_type_dyndb()
2044 for (i = 0; i < svc->attr_count; i++) { in foreach_attr_type_dyndb()
2045 struct bt_gatt_attr *attr = &svc->attrs[i]; in foreach_attr_type_dyndb()
2047 if (gatt_foreach_iter(attr, attr->handle, in foreach_attr_type_dyndb()
2077 if (handle + static_svc->attr_count < start_handle) { in bt_gatt_foreach_attr_type()
2078 handle += static_svc->attr_count; in bt_gatt_foreach_attr_type()
2082 for (i = 0; i < static_svc->attr_count; i++, handle++) { in bt_gatt_foreach_attr_type()
2083 if (gatt_foreach_iter(&static_svc->attrs[i], in bt_gatt_foreach_attr_type()
2123 for (size_t i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in find_ccc_cfg()
2124 struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; in find_ccc_cfg()
2127 if (bt_conn_is_peer_addr_le(conn, cfg->id, in find_ccc_cfg()
2128 &cfg->peer)) { in find_ccc_cfg()
2131 } else if (bt_addr_le_eq(&cfg->peer, BT_ADDR_LE_ANY)) { in find_ccc_cfg()
2143 struct _bt_gatt_ccc *ccc = attr->user_data; in bt_gatt_attr_read_ccc()
2149 value = sys_cpu_to_le16(cfg->value); in bt_gatt_attr_read_ccc()
2165 for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in gatt_ccc_changed()
2166 /* `ccc->value` shall be a summary of connected peers' CCC values, but in gatt_ccc_changed()
2167 * `ccc->cfg` can contain entries for bonded but not connected peers. in gatt_ccc_changed()
2169 struct bt_conn *conn = bt_conn_lookup_addr_le(ccc->cfg[i].id, &ccc->cfg[i].peer); in gatt_ccc_changed()
2172 if (ccc->cfg[i].value > value) { in gatt_ccc_changed()
2173 value = ccc->cfg[i].value; in gatt_ccc_changed()
2182 if (value != ccc->value) { in gatt_ccc_changed()
2183 ccc->value = value; in gatt_ccc_changed()
2184 if (ccc->cfg_changed) { in gatt_ccc_changed()
2185 ccc->cfg_changed(attr, value); in gatt_ccc_changed()
2194 struct _bt_gatt_ccc *ccc = attr->user_data; in bt_gatt_attr_write_ccc()
2229 bt_addr_le_copy(&cfg->peer, &conn->le.dst); in bt_gatt_attr_write_ccc()
2230 cfg->id = conn->id; in bt_gatt_attr_write_ccc()
2234 if (ccc->cfg_write) { in bt_gatt_attr_write_ccc()
2235 ssize_t write = ccc->cfg_write(conn, attr, value); in bt_gatt_attr_write_ccc()
2247 value_changed = cfg->value != value; in bt_gatt_attr_write_ccc()
2248 cfg->value = value; in bt_gatt_attr_write_ccc()
2250 LOG_DBG("handle 0x%04x value %u", attr->handle, cfg->value); in bt_gatt_attr_write_ccc()
2253 if (cfg->value != ccc->value) { in bt_gatt_attr_write_ccc()
2260 gatt_delayed_store_enqueue(conn->id, &conn->le.dst, DELAYED_STORE_CCC); in bt_gatt_attr_write_ccc()
2276 const struct bt_gatt_cep *value = attr->user_data; in bt_gatt_attr_read_cep()
2277 uint16_t props = sys_cpu_to_le16(value->properties); in bt_gatt_attr_read_cep()
2287 const char *value = attr->user_data; in bt_gatt_attr_read_cud()
2305 const struct bt_gatt_cpf *cpf = attr->user_data; in bt_gatt_attr_read_cpf()
2308 value.format = cpf->format; in bt_gatt_attr_read_cpf()
2309 value.exponent = cpf->exponent; in bt_gatt_attr_read_cpf()
2310 value.unit = sys_cpu_to_le16(cpf->unit); in bt_gatt_attr_read_cpf()
2311 value.name_space = cpf->name_space; in bt_gatt_attr_read_cpf()
2312 value.description = sys_cpu_to_le16(cpf->description); in bt_gatt_attr_read_cpf()
2336 uint8_t *pdu = buf->data; in gatt_notify_mult_send()
2341 if (buf->len == in gatt_notify_mult_send()
2427 nfy = net_buf_add(buf, sizeof(*nfy) + params->len); in gatt_add_nfy_to_buf()
2428 nfy->handle = sys_cpu_to_le16(handle); in gatt_add_nfy_to_buf()
2429 nfy->len = sys_cpu_to_le16(params->len); in gatt_add_nfy_to_buf()
2430 (void)memcpy(nfy->value, params->data, params->len); in gatt_add_nfy_to_buf()
2442 if (*buf && ((net_buf_tailroom(*buf) < sizeof(struct bt_att_notify_mult) + params->len) || in gatt_notify_mult()
2443 !bt_att_tx_meta_data_match(*buf, params->func, params->user_data, in gatt_notify_mult()
2456 sizeof(struct bt_att_notify_mult) + params->len); in gatt_notify_mult()
2458 return -ENOMEM; in gatt_notify_mult()
2461 bt_att_set_tx_meta_data(*buf, params->func, params->user_data, in gatt_notify_mult()
2470 LOG_DBG("handle 0x%04x len %u", handle, params->len); in gatt_notify_mult()
2474 * re-setting the timeout whenever a new notification is appended. in gatt_notify_mult()
2496 * indications to such a client until it becomes change-aware. in gatt_notify()
2499 return -EAGAIN; in gatt_notify()
2504 if (bt_gatt_check_perm(conn, params->attr, BT_GATT_PERM_READ_ENCRYPT_MASK)) { in gatt_notify()
2506 return -EPERM; in gatt_notify()
2514 if (!bt_gatt_is_subscribed(conn, params->attr, BT_GATT_CCC_NOTIFY)) { in gatt_notify()
2516 return -EINVAL; in gatt_notify()
2522 return -EINVAL; in gatt_notify()
2532 sizeof(*nfy) + params->len); in gatt_notify()
2535 return -ENOMEM; in gatt_notify()
2540 nfy = net_buf_add(buf, sizeof(*nfy) + params->len); in gatt_notify()
2541 nfy->handle = sys_cpu_to_le16(handle); in gatt_notify()
2542 memcpy(nfy->value, params->data, params->len); in gatt_notify()
2544 bt_att_set_tx_meta_data(buf, params->func, params->user_data, BT_ATT_CHAN_OPT(params)); in gatt_notify()
2566 if (params->func) { in gatt_indicate_rsp()
2567 params->func(conn, params, att_err_from_int(err)); in gatt_indicate_rsp()
2570 params->_ref--; in gatt_indicate_rsp()
2571 if (params->destroy && (params->_ref == 0)) { in gatt_indicate_rsp()
2572 params->destroy(params); in gatt_indicate_rsp()
2590 req->att_op = op; in gatt_req_alloc()
2591 req->len = len; in gatt_req_alloc()
2592 req->encode = encode; in gatt_req_alloc()
2594 req->func = func; in gatt_req_alloc()
2595 req->user_data = params; in gatt_req_alloc()
2612 return -EINVAL; in gatt_req_send()
2617 return -ENOMEM; in gatt_req_send()
2623 return -ENOMEM; in gatt_req_send()
2628 req->buf = buf; in gatt_req_send()
2658 * change-aware. in gatt_indicate()
2660 if (!(params->func && (params->func == sc_indicate_rsp || in gatt_indicate()
2661 params->func == sc_restore_rsp)) && in gatt_indicate()
2663 return -EAGAIN; in gatt_indicate()
2668 if (bt_gatt_check_perm(conn, params->attr, BT_GATT_PERM_READ_ENCRYPT_MASK)) { in gatt_indicate()
2670 return -EPERM; in gatt_indicate()
2678 if (!bt_gatt_is_subscribed(conn, params->attr, BT_GATT_CCC_INDICATE)) { in gatt_indicate()
2680 return -EINVAL; in gatt_indicate()
2686 return -EINVAL; in gatt_indicate()
2689 len = sizeof(*ind) + params->len; in gatt_indicate()
2694 return -ENOMEM; in gatt_indicate()
2701 return -ENOMEM; in gatt_indicate()
2706 ind = net_buf_add(buf, sizeof(*ind) + params->len); in gatt_indicate()
2707 ind->handle = sys_cpu_to_le16(handle); in gatt_indicate()
2708 memcpy(ind->value, params->data, params->len); in gatt_indicate()
2712 req->buf = buf; in gatt_indicate()
2733 ccc = attr->user_data; in notify_cb()
2741 if (bt_addr_le_eq(&cfg->peer, BT_ADDR_LE_ANY)) { in notify_cb()
2745 conn = bt_conn_lookup_state_le(cfg->id, &cfg->peer, in notify_cb()
2748 struct sc_data *sc; in notify_cb() local
2750 sc = (struct sc_data *)data->ind_params->data; in notify_cb()
2751 sc_save(cfg->id, &cfg->peer, in notify_cb()
2752 sys_le16_to_cpu(sc->start), in notify_cb()
2753 sys_le16_to_cpu(sc->end)); in notify_cb()
2762 for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in notify_cb()
2763 struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; in notify_cb()
2770 if (cfg->value != data->type) { in notify_cb()
2774 conn = bt_conn_lookup_addr_le(cfg->id, &cfg->peer); in notify_cb()
2779 if (conn->state != BT_CONN_CONNECTED) { in notify_cb()
2785 if (ccc->cfg_match && !ccc->cfg_match(conn, attr)) { in notify_cb()
2803 if ((data->type == BT_GATT_CCC_INDICATE) && in notify_cb()
2804 (cfg->value & BT_GATT_CCC_INDICATE)) { in notify_cb()
2805 err = gatt_indicate(conn, data->handle, data->ind_params); in notify_cb()
2807 data->ind_params->_ref++; in notify_cb()
2809 } else if ((data->type == BT_GATT_CCC_NOTIFY) && in notify_cb()
2810 (cfg->value & BT_GATT_CCC_NOTIFY)) { in notify_cb()
2811 err = gatt_notify(conn, data->handle, data->nfy_params); in notify_cb()
2818 data->err = err; in notify_cb()
2833 data->attr = attr; in match_uuid()
2834 data->handle = handle; in match_uuid()
2842 found->attr = NULL; in gatt_find_by_uuid()
2844 bt_gatt_foreach_attr_type(found->handle, 0xffff, uuid, NULL, 1, in gatt_find_by_uuid()
2847 return found->attr ? true : false; in gatt_find_by_uuid()
2871 __ASSERT(params->attr || params->uuid, "invalid parameters\n"); in bt_gatt_notify_cb()
2874 return -EAGAIN; in bt_gatt_notify_cb()
2877 if (conn && conn->state != BT_CONN_CONNECTED) { in bt_gatt_notify_cb()
2878 return -ENOTCONN; in bt_gatt_notify_cb()
2881 data.attr = params->attr; in bt_gatt_notify_cb()
2885 if (params->uuid) { in bt_gatt_notify_cb()
2886 if (!gatt_find_by_uuid(&data, params->uuid)) { in bt_gatt_notify_cb()
2887 return -ENOENT; in bt_gatt_notify_cb()
2890 params->attr = data.attr; in bt_gatt_notify_cb()
2893 return -ENOENT; in bt_gatt_notify_cb()
2898 if (!bt_uuid_cmp(data.attr->uuid, BT_UUID_GATT_CHRC)) { in bt_gatt_notify_cb()
2899 struct bt_gatt_chrc *chrc = data.attr->user_data; in bt_gatt_notify_cb()
2901 if (!(chrc->properties & BT_GATT_CHRC_NOTIFY)) { in bt_gatt_notify_cb()
2902 return -EINVAL; in bt_gatt_notify_cb()
2912 data.err = -ENOTCONN; in bt_gatt_notify_cb()
2928 __ASSERT(params->attr, "invalid parameters\n"); in gatt_notify_multiple_verify_args()
2934 return -EINVAL; in gatt_notify_multiple_verify_args()
2941 return -EINVAL; in gatt_notify_multiple_verify_args()
2945 return -EAGAIN; in gatt_notify_multiple_verify_args()
2948 if (conn->state != BT_CONN_CONNECTED) { in gatt_notify_multiple_verify_args()
2949 return -ENOTCONN; in gatt_notify_multiple_verify_args()
2958 * indications to such a client until it becomes change-aware. in gatt_notify_multiple_verify_args()
2961 return -EAGAIN; in gatt_notify_multiple_verify_args()
2967 return -EOPNOTSUPP; in gatt_notify_multiple_verify_args()
2986 return -EPERM; in gatt_notify_multiple_verify_params()
2994 return -EINVAL; in gatt_notify_multiple_verify_params()
2999 return -EINVAL; in gatt_notify_multiple_verify_params()
3004 return -EINVAL; in gatt_notify_multiple_verify_params()
3012 return -EINVAL; in gatt_notify_multiple_verify_params()
3016 /* PDU length is specified with a 16-bit value. */ in gatt_notify_multiple_verify_params()
3018 return -ERANGE; in gatt_notify_multiple_verify_params()
3024 return -ERANGE; in gatt_notify_multiple_verify_params()
3045 * Also gets us the total length of the PDU as a side-effect. in bt_gatt_notify_multiple()
3061 return -ENOMEM; in bt_gatt_notify_multiple()
3065 bt_att_set_tx_meta_data(buf, params->func, params->user_data, BT_ATT_CHAN_OPT(params)); in bt_gatt_notify_multiple()
3066 bt_att_increment_tx_meta_data_attr_count(buf, num_params - 1); in bt_gatt_notify_multiple()
3077 if (!bt_uuid_cmp(data.attr->uuid, BT_UUID_GATT_CHRC)) { in bt_gatt_notify_multiple()
3096 __ASSERT(params->attr || params->uuid, "invalid parameters\n"); in bt_gatt_indicate()
3099 return -EAGAIN; in bt_gatt_indicate()
3102 if (conn && conn->state != BT_CONN_CONNECTED) { in bt_gatt_indicate()
3103 return -ENOTCONN; in bt_gatt_indicate()
3106 data.attr = params->attr; in bt_gatt_indicate()
3110 if (params->uuid) { in bt_gatt_indicate()
3111 if (!gatt_find_by_uuid(&data, params->uuid)) { in bt_gatt_indicate()
3112 return -ENOENT; in bt_gatt_indicate()
3115 params->attr = data.attr; in bt_gatt_indicate()
3118 return -ENOENT; in bt_gatt_indicate()
3123 if (!bt_uuid_cmp(data.attr->uuid, BT_UUID_GATT_CHRC)) { in bt_gatt_indicate()
3124 struct bt_gatt_chrc *chrc = data.attr->user_data; in bt_gatt_indicate()
3126 if (!(chrc->properties & BT_GATT_CHRC_INDICATE)) { in bt_gatt_indicate()
3127 return -EINVAL; in bt_gatt_indicate()
3134 params->_ref = 1; in bt_gatt_indicate()
3138 data.err = -ENOTCONN; in bt_gatt_indicate()
3142 params->_ref = 0; in bt_gatt_indicate()
3163 (!(attr->perm & BT_GATT_PERM_READ_MASK) || !attr->read)) { in bt_gatt_check_perm()
3168 (!(attr->perm & BT_GATT_PERM_WRITE_MASK) || !attr->write)) { in bt_gatt_check_perm()
3176 mask &= attr->perm; in bt_gatt_check_perm()
3197 if (!conn->encrypt) { in bt_gatt_check_perm()
3212 const struct bt_keys *keys = conn->le.keys; in bt_gatt_check_perm()
3214 if (!keys || (keys->flags & BT_KEYS_SC) == 0) { in bt_gatt_check_perm()
3238 * ... a change-unaware connected client using exactly one ATT bearer in sc_restore_rsp()
3239 * becomes change-aware when ... in sc_restore_rsp()
3253 struct gatt_sc_cfg *gsc_cfg = find_sc_cfg(conn->id, &conn->le.dst); in sc_restore_rsp()
3269 cfg = find_sc_cfg(conn->id, &conn->le.dst); in sc_restore()
3271 LOG_DBG("no SC data found"); in sc_restore()
3275 if (!(cfg->data.start || cfg->data.end)) { in sc_restore()
3279 LOG_DBG("peer %s start 0x%04x end 0x%04x", bt_addr_le_str(&cfg->peer), cfg->data.start, in sc_restore()
3280 cfg->data.end); in sc_restore()
3284 sc_range[index][0] = sys_cpu_to_le16(cfg->data.start); in sc_restore()
3285 sc_range[index][1] = sys_cpu_to_le16(cfg->data.end); in sc_restore()
3293 LOG_ERR("SC restore indication failed"); in sc_restore()
3306 struct bt_conn *conn = data->conn; in update_ccc()
3315 ccc = attr->user_data; in update_ccc()
3317 for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in update_ccc()
3318 struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; in update_ccc()
3321 if (!cfg->value || in update_ccc()
3322 !bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) { in update_ccc()
3345 if (data->sec < sec) { in update_ccc()
3346 data->sec = sec; in update_ccc()
3377 ccc = attr->user_data; in disconnected_cb()
3380 if (!ccc->value) { in disconnected_cb()
3387 for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in disconnected_cb()
3388 struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i]; in disconnected_cb()
3391 if (!cfg->value) { in disconnected_cb()
3395 if (!bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) { in disconnected_cb()
3399 tmp = bt_conn_lookup_addr_le(cfg->id, &cfg->peer); in disconnected_cb()
3401 if (tmp->state == BT_CONN_CONNECTED) { in disconnected_cb()
3409 if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { in disconnected_cb()
3417 bt_addr_le_copy(&cfg->peer, &conn->le.dst); in disconnected_cb()
3424 ccc->value = 0U; in disconnected_cb()
3425 if (ccc->cfg_changed) { in disconnected_cb()
3426 ccc->cfg_changed(attr, ccc->value); in disconnected_cb()
3445 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_is_subscribed()
3450 if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) { in bt_gatt_is_subscribed()
3453 if (!attr->read) { in bt_gatt_is_subscribed()
3458 len = attr->read(NULL, attr, &properties, sizeof(properties), 0); in bt_gatt_is_subscribed()
3477 if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) != 0) { in bt_gatt_is_subscribed()
3483 while (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) && in bt_gatt_is_subscribed()
3485 bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC) && in bt_gatt_is_subscribed()
3486 bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) && in bt_gatt_is_subscribed()
3487 bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) { in bt_gatt_is_subscribed()
3494 if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) != 0) { in bt_gatt_is_subscribed()
3498 if (!attr->read) { in bt_gatt_is_subscribed()
3503 len = attr->read(conn, attr, ccc_bits_encoded, sizeof(ccc_bits_encoded), 0); in bt_gatt_is_subscribed()
3524 return sys_slist_is_empty(&sub->list); in gatt_sub_is_empty()
3532 bt_addr_le_copy(&sub->peer, BT_ADDR_LE_ANY); in gatt_sub_free()
3541 sys_slist_remove(&sub->list, prev, &params->node); in gatt_sub_remove()
3543 params->notify(conn, params, NULL, 0); in gatt_sub_remove()
3558 if (bt_addr_le_eq(&sub->peer, BT_ADDR_LE_ANY)) { in gatt_sub_find()
3561 } else if (bt_conn_is_peer_addr_le(conn, sub->id, &sub->peer)) { in gatt_sub_find()
3577 bt_addr_le_copy(&sub->peer, &conn->le.dst); in gatt_sub_add()
3578 sub->id = conn->id; in gatt_sub_add()
3591 if (id == sub->id && bt_addr_le_eq(&sub->peer, addr)) { in gatt_sub_find_by_addr()
3608 bt_addr_le_copy(&sub->peer, addr); in gatt_sub_add_by_addr()
3609 sub->id = id; in gatt_sub_add_by_addr()
3620 return conn->sec_level >= params->min_security; in check_subscribe_security_level()
3631 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, params, tmp, node) { in call_notify_cb_and_maybe_unsubscribe()
3632 if (handle != params->value_handle) { in call_notify_cb_and_maybe_unsubscribe()
3637 if (params->notify(conn, params, data, length) == BT_GATT_ITER_STOP) { in call_notify_cb_and_maybe_unsubscribe()
3684 handle = sys_cpu_to_le16(nfy->handle); in bt_gatt_mult_notification()
3685 len = sys_cpu_to_le16(nfy->len); in bt_gatt_mult_notification()
3694 call_notify_cb_and_maybe_unsubscribe(conn, sub, handle, nfy->value, len); in bt_gatt_mult_notification()
3702 if (sub->peer.type == BT_ADDR_LE_PUBLIC) { in gatt_sub_update()
3707 bt_addr_le_copy(&sub->peer, &conn->le.dst); in gatt_sub_update()
3722 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, params, tmp, node) { in remove_subscriptions()
3723 atomic_clear_bit(params->flags, BT_GATT_SUBSCRIBE_FLAG_SENT); in remove_subscriptions()
3725 if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst) || in remove_subscriptions()
3726 (atomic_test_bit(params->flags, in remove_subscriptions()
3729 params->value = 0U; in remove_subscriptions()
3733 prev = &params->node; in remove_subscriptions()
3743 params->func(conn, att_err_from_int(err), params); in gatt_mtu_rsp()
3757 req->mtu = sys_cpu_to_le16(mtu); in gatt_exchange_mtu_encode()
3768 __ASSERT(params && params->func, "invalid parameters\n"); in bt_gatt_exchange_mtu()
3770 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_exchange_mtu()
3771 return -ENOTCONN; in bt_gatt_exchange_mtu()
3775 if (atomic_test_and_set_bit(conn->flags, BT_CONN_ATT_MTU_EXCHANGED)) { in bt_gatt_exchange_mtu()
3776 return -EALREADY; in bt_gatt_exchange_mtu()
3784 atomic_clear_bit(conn->flags, BT_CONN_ATT_MTU_EXCHANGED); in bt_gatt_exchange_mtu()
3799 params->start_handle = last_handle; in gatt_discover_next()
3800 if (params->start_handle < UINT16_MAX) { in gatt_discover_next()
3801 params->start_handle++; in gatt_discover_next()
3807 if (params->start_handle > params->end_handle) { in gatt_discover_next()
3818 params->func(conn, NULL, params); in gatt_discover_next()
3850 if (params->type == BT_GATT_DISCOVER_PRIMARY) { in gatt_find_type_rsp()
3857 value.uuid = params->uuid; in gatt_find_type_rsp()
3865 if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) { in gatt_find_type_rsp()
3874 params->func(conn, NULL, params); in gatt_find_type_rsp()
3885 req->start_handle = sys_cpu_to_le16(params->start_handle); in gatt_find_type_encode()
3886 req->end_handle = sys_cpu_to_le16(params->end_handle); in gatt_find_type_encode()
3888 if (params->type == BT_GATT_DISCOVER_PRIMARY) { in gatt_find_type_encode()
3894 req->type = sys_cpu_to_le16(uuid_val); in gatt_find_type_encode()
3896 LOG_DBG("uuid %s start_handle 0x%04x end_handle 0x%04x", bt_uuid_str(params->uuid), in gatt_find_type_encode()
3897 params->start_handle, params->end_handle); in gatt_find_type_encode()
3899 switch (params->uuid->type) { in gatt_find_type_encode()
3901 net_buf_add_le16(buf, BT_UUID_16(params->uuid)->val); in gatt_find_type_encode()
3904 net_buf_add_mem(buf, BT_UUID_128(params->uuid)->val, 16); in gatt_find_type_encode()
3918 switch (params->uuid->type) { in gatt_find_type()
3926 LOG_ERR("Unknown UUID type %u", params->uuid->type); in gatt_find_type()
3927 return -EINVAL; in gatt_find_type()
3950 params->func(conn, NULL, params); in read_included_uuid_cb()
3954 handle = params->_included.attr_handle; in read_included_uuid_cb()
3955 value.start_handle = params->_included.start_handle; in read_included_uuid_cb()
3956 value.end_handle = params->_included.end_handle; in read_included_uuid_cb()
3962 "end_handle 0x%04x\n", params->_included.attr_handle, in read_included_uuid_cb()
3966 if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) { in read_included_uuid_cb()
3976 if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) { in read_included_uuid_cb()
3980 gatt_discover_next(conn, params->start_handle, params); in read_included_uuid_cb()
3992 req->handle = sys_cpu_to_le16(params->_included.start_handle); in read_included_uuid_encode()
4000 LOG_DBG("handle 0x%04x", params->_included.start_handle); in read_included_uuid()
4028 switch (rsp->len) { in parse_include()
4035 * uses a 128-bit UUID, the Read Request is used. in parse_include()
4040 LOG_ERR("Invalid data len %u", rsp->len); in parse_include()
4045 for (length--, pdu = rsp->data; length >= rsp->len; in parse_include()
4046 length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) { in parse_include()
4049 struct gatt_incl *incl = (void *)data->value; in parse_include()
4051 handle = sys_le16_to_cpu(data->handle); in parse_include()
4061 value.start_handle = sys_le16_to_cpu(incl->start_handle); in parse_include()
4062 value.end_handle = sys_le16_to_cpu(incl->end_handle); in parse_include()
4067 u.u16.val = sys_le16_to_cpu(incl->uuid16); in parse_include()
4070 params->_included.attr_handle = handle; in parse_include()
4071 params->_included.start_handle = value.start_handle; in parse_include()
4072 params->_included.end_handle = value.end_handle; in parse_include()
4082 if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) { in parse_include()
4092 if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) { in parse_include()
4103 params->func(conn, NULL, params); in parse_include()
4127 switch (rsp->len) { in parse_characteristic()
4135 LOG_ERR("Invalid data len %u", rsp->len); in parse_characteristic()
4140 for (length--, pdu = rsp->data; length >= rsp->len; in parse_characteristic()
4141 length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) { in parse_characteristic()
4145 struct gatt_chrc *chrc = (void *)data->value; in parse_characteristic()
4147 handle = sys_le16_to_cpu(data->handle); in parse_characteristic()
4155 u.u16.val = sys_le16_to_cpu(chrc->uuid16); in parse_characteristic()
4158 memcpy(u.u128.val, chrc->uuid, sizeof(chrc->uuid)); in parse_characteristic()
4163 chrc->properties); in parse_characteristic()
4166 if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) { in parse_characteristic()
4171 &u.uuid, sys_le16_to_cpu(chrc->value_handle), in parse_characteristic()
4172 chrc->properties); in parse_characteristic()
4180 if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) { in parse_characteristic()
4191 params->func(conn, NULL, params); in parse_characteristic()
4203 if (params->uuid->type != BT_UUID_TYPE_16) { in parse_read_std_char_desc()
4207 uuid_val = BT_UUID_16(params->uuid)->val; in parse_read_std_char_desc()
4217 for (length--, pdu = rsp->data; length >= rsp->len; in parse_read_std_char_desc()
4218 length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) { in parse_read_std_char_desc()
4235 handle = sys_le16_to_cpu(data->handle); in parse_read_std_char_desc()
4248 value.cep.properties = sys_get_le16(data->value); in parse_read_std_char_desc()
4256 value.ccc.flags = sys_get_le16(data->value); in parse_read_std_char_desc()
4264 value.scc.flags = sys_get_le16(data->value); in parse_read_std_char_desc()
4275 cpf = (void *)data->value; in parse_read_std_char_desc()
4277 value.cpf.format = cpf->format; in parse_read_std_char_desc()
4278 value.cpf.exponent = cpf->exponent; in parse_read_std_char_desc()
4279 value.cpf.unit = sys_le16_to_cpu(cpf->unit); in parse_read_std_char_desc()
4280 value.cpf.name_space = cpf->name_space; in parse_read_std_char_desc()
4281 value.cpf.description = sys_le16_to_cpu(cpf->description); in parse_read_std_char_desc()
4289 .uuid = params->uuid, in parse_read_std_char_desc()
4294 if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) { in parse_read_std_char_desc()
4305 params->func(conn, NULL, params); in parse_read_std_char_desc()
4319 params->func(conn, NULL, params); in gatt_read_type_rsp()
4323 if (params->type == BT_GATT_DISCOVER_INCLUDE) { in gatt_read_type_rsp()
4325 } else if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) { in gatt_read_type_rsp()
4345 req->start_handle = sys_cpu_to_le16(params->start_handle); in gatt_read_type_encode()
4346 req->end_handle = sys_cpu_to_le16(params->end_handle); in gatt_read_type_encode()
4348 switch (params->type) { in gatt_read_type_encode()
4356 /* Only 16-bit UUIDs supported */ in gatt_read_type_encode()
4357 net_buf_add_le16(buf, BT_UUID_16(params->uuid)->val); in gatt_read_type_encode()
4367 LOG_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle, params->end_handle); in gatt_read_type()
4394 switch (rsp->len) { in parse_service()
4402 LOG_ERR("Invalid data len %u", rsp->len); in parse_service()
4407 for (length--, pdu = rsp->data; length >= rsp->len; in parse_service()
4408 length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) { in parse_service()
4414 start_handle = sys_le16_to_cpu(data->start_handle); in parse_service()
4419 end_handle = sys_le16_to_cpu(data->end_handle); in parse_service()
4426 memcpy(&u.u16.val, data->value, sizeof(u.u16.val)); in parse_service()
4430 memcpy(u.u128.val, data->value, sizeof(u.u128.val)); in parse_service()
4438 if (params->type == BT_GATT_DISCOVER_PRIMARY) { in parse_service()
4451 if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) { in parse_service()
4462 params->func(conn, NULL, params); in parse_service()
4476 params->func(conn, NULL, params); in gatt_read_group_rsp()
4495 req->start_handle = sys_cpu_to_le16(params->start_handle); in gatt_read_group_encode()
4496 req->end_handle = sys_cpu_to_le16(params->end_handle); in gatt_read_group_encode()
4498 if (params->type == BT_GATT_DISCOVER_PRIMARY) { in gatt_read_group_encode()
4510 LOG_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle, params->end_handle); in gatt_read_group()
4553 switch (rsp->format) { in gatt_find_info_rsp()
4563 LOG_ERR("Invalid format %u", rsp->format); in gatt_find_info_rsp()
4567 length--; in gatt_find_info_rsp()
4575 for (i = length / len, pdu = rsp->info; i != 0; in gatt_find_info_rsp()
4576 i--, pdu = (const uint8_t *)pdu + len) { in gatt_find_info_rsp()
4580 handle = sys_le16_to_cpu(info.i16->handle); in gatt_find_info_rsp()
4589 u.u16.val = sys_le16_to_cpu(info.i16->uuid); in gatt_find_info_rsp()
4592 memcpy(u.u128.val, info.i128->uuid, 16); in gatt_find_info_rsp()
4599 if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) { in gatt_find_info_rsp()
4603 if (params->type == BT_GATT_DISCOVER_DESCRIPTOR) { in gatt_find_info_rsp()
4628 if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) { in gatt_find_info_rsp()
4638 params->func(conn, NULL, params); in gatt_find_info_rsp()
4648 req->start_handle = sys_cpu_to_le16(params->start_handle); in gatt_find_info_encode()
4649 req->end_handle = sys_cpu_to_le16(params->end_handle); in gatt_find_info_encode()
4657 LOG_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle, params->end_handle); in gatt_find_info()
4669 __ASSERT(params && params->func, "invalid parameters\n"); in bt_gatt_discover()
4670 __ASSERT((params->start_handle && params->end_handle), in bt_gatt_discover()
4672 __ASSERT((params->start_handle <= params->end_handle), in bt_gatt_discover()
4675 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_discover()
4676 return -ENOTCONN; in bt_gatt_discover()
4679 switch (params->type) { in bt_gatt_discover()
4682 if (params->uuid) { in bt_gatt_discover()
4688 if (!(params->uuid && params->uuid->type == BT_UUID_TYPE_16 && in bt_gatt_discover()
4689 (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_CEP) || in bt_gatt_discover()
4690 !bt_uuid_cmp(params->uuid, BT_UUID_GATT_CCC) || in bt_gatt_discover()
4691 !bt_uuid_cmp(params->uuid, BT_UUID_GATT_SCC) || in bt_gatt_discover()
4692 !bt_uuid_cmp(params->uuid, BT_UUID_GATT_CPF)))) { in bt_gatt_discover()
4693 return -EINVAL; in bt_gatt_discover()
4701 if (params->uuid && in bt_gatt_discover()
4702 (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_PRIMARY) || in bt_gatt_discover()
4703 !bt_uuid_cmp(params->uuid, BT_UUID_GATT_SECONDARY) || in bt_gatt_discover()
4704 !bt_uuid_cmp(params->uuid, BT_UUID_GATT_INCLUDE) || in bt_gatt_discover()
4705 !bt_uuid_cmp(params->uuid, BT_UUID_GATT_CHRC))) { in bt_gatt_discover()
4706 return -EINVAL; in bt_gatt_discover()
4712 LOG_ERR("Invalid discovery type: %u", params->type); in bt_gatt_discover()
4715 return -EINVAL; in bt_gatt_discover()
4724 const uint16_t req_start_handle = params->by_uuid.start_handle; in parse_read_by_uuid()
4725 const uint16_t req_end_handle = params->by_uuid.end_handle; in parse_read_by_uuid()
4728 for (length--, pdu = rsp->data; length; in parse_read_by_uuid()
4729 length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) { in parse_read_by_uuid()
4734 handle = sys_le16_to_cpu(data->handle); in parse_read_by_uuid()
4742 len = rsp->len > length ? length - 2 : rsp->len - 2; in parse_read_by_uuid()
4744 LOG_DBG("handle 0x%04x len %u value %u", handle, rsp->len, len); in parse_read_by_uuid()
4747 LOG_WRN("Bad peer: ATT read-by-uuid rsp: " in parse_read_by_uuid()
4748 "Handle 0x%04x is outside requested range 0x%04x-0x%04x. " in parse_read_by_uuid()
4751 params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0); in parse_read_by_uuid()
4756 params->by_uuid.start_handle = handle; in parse_read_by_uuid()
4758 if (params->func(conn, 0, params, data->value, len) == in parse_read_by_uuid()
4764 if (rsp->len > length) { in parse_read_by_uuid()
4769 if (params->by_uuid.start_handle == params->by_uuid.end_handle) { in parse_read_by_uuid()
4770 params->func(conn, 0, params, NULL, 0); in parse_read_by_uuid()
4774 params->by_uuid.start_handle++; in parse_read_by_uuid()
4779 params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0); in parse_read_by_uuid()
4791 params->func(conn, att_err_from_int(err), params, NULL, 0); in gatt_read_rsp()
4795 if (!params->handle_count) { in gatt_read_rsp()
4800 if (params->func(conn, 0, params, pdu, length) == BT_GATT_ITER_STOP) { in gatt_read_rsp()
4806 * If the Characteristic Value is greater than (ATT_MTU - 1) octets in gatt_read_rsp()
4813 if (length < (params->_att_mtu - 1)) { in gatt_read_rsp()
4814 params->func(conn, 0, params, NULL, 0); in gatt_read_rsp()
4818 params->single.offset += length; in gatt_read_rsp()
4822 params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0); in gatt_read_rsp()
4833 req->handle = sys_cpu_to_le16(params->single.handle); in gatt_read_blob_encode()
4834 req->offset = sys_cpu_to_le16(params->single.offset); in gatt_read_blob_encode()
4842 LOG_DBG("handle 0x%04x offset 0x%04x", params->single.handle, params->single.offset); in gatt_read_blob()
4857 req->start_handle = sys_cpu_to_le16(params->by_uuid.start_handle); in gatt_read_uuid_encode()
4858 req->end_handle = sys_cpu_to_le16(params->by_uuid.end_handle); in gatt_read_uuid_encode()
4860 if (params->by_uuid.uuid->type == BT_UUID_TYPE_16) { in gatt_read_uuid_encode()
4861 net_buf_add_le16(buf, BT_UUID_16(params->by_uuid.uuid)->val); in gatt_read_uuid_encode()
4863 net_buf_add_mem(buf, BT_UUID_128(params->by_uuid.uuid)->val, 16); in gatt_read_uuid_encode()
4872 LOG_DBG("start_handle 0x%04x end_handle 0x%04x uuid %s", params->by_uuid.start_handle, in gatt_read_uuid()
4873 params->by_uuid.end_handle, bt_uuid_str(params->by_uuid.uuid)); in gatt_read_uuid()
4890 params->func(conn, att_err_from_int(err), params, NULL, 0); in gatt_read_mult_rsp()
4894 params->func(conn, 0, params, pdu, length); in gatt_read_mult_rsp()
4897 params->func(conn, 0, params, NULL, 0); in gatt_read_mult_rsp()
4906 for (i = 0U; i < params->handle_count; i++) { in gatt_read_mult_encode()
4907 net_buf_add_le16(buf, params->multiple.handles[i]); in gatt_read_mult_encode()
4916 LOG_DBG("handle_count %zu", params->handle_count); in gatt_read_mult()
4920 params->handle_count * sizeof(uint16_t), in gatt_read_mult()
4928 return -ENOTSUP; in gatt_read_mult()
4944 params->func(conn, att_err_from_int(err), params, NULL, 0); in gatt_read_mult_vl_rsp()
4954 len = sys_le16_to_cpu(rsp->len); in gatt_read_mult_vl_rsp()
4964 params->func(conn, 0, params, rsp->value, len); in gatt_read_mult_vl_rsp()
4970 params->func(conn, 0, params, NULL, 0); in gatt_read_mult_vl_rsp()
4979 for (i = 0U; i < params->handle_count; i++) { in gatt_read_mult_vl_encode()
4980 net_buf_add_le16(buf, params->multiple.handles[i]); in gatt_read_mult_vl_encode()
4989 LOG_DBG("handle_count %zu", params->handle_count); in gatt_read_mult_vl()
4994 params->handle_count * sizeof(uint16_t), in gatt_read_mult_vl()
5002 return -ENOTSUP; in gatt_read_mult_vl()
5012 req->handle = sys_cpu_to_le16(params->single.handle); in gatt_read_encode()
5020 __ASSERT(params && params->func, "invalid parameters\n"); in bt_gatt_read()
5022 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_read()
5023 return -ENOTCONN; in bt_gatt_read()
5026 if (params->handle_count == 0) { in bt_gatt_read()
5030 if (params->handle_count > 1) { in bt_gatt_read()
5031 if (params->multiple.variable) { in bt_gatt_read()
5038 if (params->single.offset) { in bt_gatt_read()
5042 LOG_DBG("handle 0x%04x", params->single.handle); in bt_gatt_read()
5056 params->func(conn, att_err_from_int(err), params); in gatt_write_rsp()
5071 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_write_without_response_cb()
5072 return -ENOTCONN; in bt_gatt_write_without_response_cb()
5076 if (conn->encrypt) { in bt_gatt_write_without_response_cb()
5090 return -ENOMEM; in bt_gatt_write_without_response_cb()
5094 cmd->handle = sys_cpu_to_le16(handle); in bt_gatt_write_without_response_cb()
5100 return -ENOMEM; in bt_gatt_write_without_response_cb()
5115 req->flags = BT_ATT_FLAG_EXEC; in gatt_exec_encode()
5136 req->flags = BT_ATT_FLAG_CANCEL; in gatt_cancel_encode()
5165 params->func(conn, att_err_from_int(err), params); in gatt_prepare_write_rsp()
5176 len = length - sizeof(*rsp); in gatt_prepare_write_rsp()
5177 if (len > params->length) { in gatt_prepare_write_rsp()
5186 data_valid = memcmp(params->data, rsp->value, len) == 0; in gatt_prepare_write_rsp()
5187 if (params->offset != rsp->offset || !data_valid) { in gatt_prepare_write_rsp()
5197 params->offset += len; in gatt_prepare_write_rsp()
5198 params->data = (const uint8_t *)params->data + len; in gatt_prepare_write_rsp()
5199 params->length -= len; in gatt_prepare_write_rsp()
5202 if (!params->length) { in gatt_prepare_write_rsp()
5218 params->func(conn, BT_ATT_ERR_UNLIKELY, params); in gatt_prepare_write_rsp()
5229 req->handle = sys_cpu_to_le16(params->handle); in gatt_prepare_write_encode()
5230 req->offset = sys_cpu_to_le16(params->offset); in gatt_prepare_write_encode()
5232 write = net_buf_append_bytes(buf, len - sizeof(*req), in gatt_prepare_write_encode()
5233 (uint8_t *)params->data, K_NO_WAIT, NULL, in gatt_prepare_write_encode()
5235 if (write != (len - sizeof(*req))) { in gatt_prepare_write_encode()
5236 return -ENOMEM; in gatt_prepare_write_encode()
5249 len = bt_att_get_mtu(conn) - req_len - 1; in gatt_prepare_write()
5250 len = MIN(params->length, len); in gatt_prepare_write()
5266 req->handle = sys_cpu_to_le16(params->handle); in gatt_write_encode()
5268 write = net_buf_append_bytes(buf, params->length, params->data, in gatt_write_encode()
5270 if (write != params->length) { in gatt_write_encode()
5271 return -ENOMEM; in gatt_write_encode()
5282 __ASSERT(params && params->func, "invalid parameters\n"); in bt_gatt_write()
5283 __ASSERT(params->handle, "invalid parameters\n"); in bt_gatt_write()
5285 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_write()
5286 return -ENOTCONN; in bt_gatt_write()
5289 len = sizeof(struct bt_att_write_req) + params->length; in bt_gatt_write()
5292 if (params->offset || len > (bt_att_get_mtu(conn) - 1)) { in bt_gatt_write()
5296 LOG_DBG("handle 0x%04x length %u", params->handle, params->length); in bt_gatt_write()
5311 atomic_clear_bit(params->flags, BT_GATT_SUBSCRIBE_FLAG_WRITE_PENDING); in gatt_write_ccc_rsp()
5325 SYS_SLIST_FOR_EACH_NODE_SAFE(&sub->list, node, tmp) { in gatt_write_ccc_rsp()
5326 if (node == &params->node) { in gatt_write_ccc_rsp()
5332 } else if (!params->value) { in gatt_write_ccc_rsp()
5334 params->notify(conn, params, NULL, 0); in gatt_write_ccc_rsp()
5339 if (params->subscribe) { in gatt_write_ccc_rsp()
5340 params->subscribe(conn, att_err, params); in gatt_write_ccc_rsp()
5351 write_req->handle = sys_cpu_to_le16(params->ccc_handle); in gatt_write_ccc_buf()
5352 net_buf_add_le16(buf, params->value); in gatt_write_ccc_buf()
5354 atomic_set_bit(params->flags, BT_GATT_SUBSCRIBE_FLAG_WRITE_PENDING); in gatt_write_ccc_buf()
5365 LOG_DBG("handle 0x%04x value 0x%04x", params->ccc_handle, params->value); in gatt_write_ccc()
5370 atomic_set_bit(params->flags, BT_GATT_SUBSCRIBE_FLAG_SENT); in gatt_write_ccc()
5382 struct bt_gatt_subscribe_params *sub_params = params->sub_params; in gatt_ccc_discover_cb()
5386 sub_params->notify(conn, sub_params, NULL, 0); in gatt_ccc_discover_cb()
5390 if (params->type == BT_GATT_DISCOVER_DESCRIPTOR) { in gatt_ccc_discover_cb()
5392 sub_params->ccc_handle = attr->handle; in gatt_ccc_discover_cb()
5395 sub_params->notify(conn, sub_params, NULL, 0); in gatt_ccc_discover_cb()
5414 memset(params->disc_params, 0, sizeof(*params->disc_params)); in gatt_ccc_discover()
5416 params->disc_params->sub_params = params; in gatt_ccc_discover()
5417 params->disc_params->uuid = &ccc_uuid.uuid; in gatt_ccc_discover()
5418 params->disc_params->type = BT_GATT_DISCOVER_DESCRIPTOR; in gatt_ccc_discover()
5419 params->disc_params->start_handle = params->value_handle; in gatt_ccc_discover()
5420 params->disc_params->end_handle = params->end_handle; in gatt_ccc_discover()
5421 params->disc_params->func = gatt_ccc_discover_cb; in gatt_ccc_discover()
5423 params->disc_params->chan_opt = params->chan_opt; in gatt_ccc_discover()
5426 err = bt_gatt_discover(conn, params->disc_params); in gatt_ccc_discover()
5444 __ASSERT(params && params->notify, "invalid parameters\n"); in bt_gatt_subscribe()
5445 __ASSERT(params->value, "invalid parameters\n"); in bt_gatt_subscribe()
5447 __ASSERT(params->ccc_handle || in bt_gatt_subscribe()
5448 (params->end_handle && params->disc_params), in bt_gatt_subscribe()
5451 __ASSERT(params->ccc_handle, "invalid parameters\n"); in bt_gatt_subscribe()
5454 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_subscribe()
5455 return -ENOTCONN; in bt_gatt_subscribe()
5460 return -ENOMEM; in bt_gatt_subscribe()
5464 if (params->disc_params != NULL && params->disc_params->func == gatt_ccc_discover_cb) { in bt_gatt_subscribe()
5466 return -EBUSY; in bt_gatt_subscribe()
5471 SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, tmp, node) { in bt_gatt_subscribe()
5475 return -EALREADY; in bt_gatt_subscribe()
5479 if (tmp->value_handle == params->value_handle && in bt_gatt_subscribe()
5480 tmp->value >= params->value) { in bt_gatt_subscribe()
5490 if (params->ccc_handle == BT_GATT_AUTO_DISCOVER_CCC_HANDLE) { in bt_gatt_subscribe()
5505 sys_slist_prepend(&sub->list, &params->node); in bt_gatt_subscribe()
5516 __ASSERT(params && params->notify, "invalid parameters\n"); in bt_gatt_resubscribe()
5517 __ASSERT(params->value, "invalid parameters\n"); in bt_gatt_resubscribe()
5518 __ASSERT(params->ccc_handle, "invalid parameters\n"); in bt_gatt_resubscribe()
5522 return -ENOMEM; in bt_gatt_resubscribe()
5526 SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, tmp, node) { in bt_gatt_resubscribe()
5530 return -EALREADY; in bt_gatt_resubscribe()
5534 sys_slist_prepend(&sub->list, &params->node); in bt_gatt_resubscribe()
5548 if (conn->state != BT_CONN_CONNECTED) { in bt_gatt_unsubscribe()
5549 return -ENOTCONN; in bt_gatt_unsubscribe()
5554 return -EINVAL; in bt_gatt_unsubscribe()
5558 SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, tmp, node) { in bt_gatt_unsubscribe()
5565 if (tmp->value_handle == params->value_handle) { in bt_gatt_unsubscribe()
5571 return -EINVAL; in bt_gatt_unsubscribe()
5575 if (atomic_test_bit(params->flags, BT_GATT_SUBSCRIBE_FLAG_WRITE_PENDING)) { in bt_gatt_unsubscribe()
5582 params->value = 0x0000; in bt_gatt_unsubscribe()
5589 sys_slist_find_and_remove(&sub->list, &params->node); in bt_gatt_unsubscribe()
5597 params->notify(conn, params, NULL, 0); in bt_gatt_unsubscribe()
5612 func = req->func; in bt_gatt_cancel()
5630 if (err == -ECONNRESET) { in gatt_resub_ccc_rsp()
5652 if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { in add_subscriptions()
5662 SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, params, node) { in add_subscriptions()
5663 if (!atomic_test_bit(params->flags, in add_subscriptions()
5665 !atomic_test_bit(params->flags, in add_subscriptions()
5707 for (size_t i = 0; i < ARRAY_SIZE(ccc->cfg); i++) { in ccc_find_cfg()
5708 if (id == ccc->cfg[i].id && in ccc_find_cfg()
5709 bt_addr_le_eq(&ccc->cfg[i].peer, addr)) { in ccc_find_cfg()
5710 return &ccc->cfg[i]; in ccc_find_cfg()
5754 ccc = attr->user_data; in ccc_load()
5757 if (!load->entry) { in ccc_load()
5758 ccc_clear(ccc, load->addr_with_id.addr, load->addr_with_id.id); in ccc_load()
5760 } else if (!load->count) { in ccc_load()
5765 if (load->entry->handle != handle) { in ccc_load()
5770 if (load->entry->handle < handle) { in ccc_load()
5772 " found", load->entry->handle); in ccc_load()
5778 LOG_DBG("Restoring CCC: handle 0x%04x value 0x%04x", load->entry->handle, in ccc_load()
5779 load->entry->value); in ccc_load()
5781 cfg = ccc_find_cfg(ccc, load->addr_with_id.addr, load->addr_with_id.id); in ccc_load()
5788 bt_addr_le_copy(&cfg->peer, load->addr_with_id.addr); in ccc_load()
5789 cfg->id = load->addr_with_id.id; in ccc_load()
5792 cfg->value = load->entry->value; in ccc_load()
5795 load->entry++; in ccc_load()
5796 load->count--; in ccc_load()
5798 return load->count ? BT_GATT_ITER_CONTINUE : BT_GATT_ITER_STOP; in ccc_load()
5816 return -EINVAL; in ccc_set()
5824 return -EINVAL; in ccc_set()
5833 return -EINVAL; in ccc_set()
5891 return -EINVAL; in ccc_set_direct()
5910 bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { in bt_gatt_connected()
5913 if (conn->id) { in bt_gatt_connected()
5916 u8_to_dec(id_str, sizeof(id_str), conn->id); in bt_gatt_connected()
5918 &conn->le.dst, id_str); in bt_gatt_connected()
5921 &conn->le.dst, NULL); in bt_gatt_connected()
5946 (conn->role == BT_HCI_ROLE_CENTRAL || in bt_gatt_connected()
5971 if (cb->att_mtu_updated) { in bt_gatt_att_max_mtu_changed()
5972 cb->att_mtu_updated(conn, tx, rx); in bt_gatt_att_max_mtu_changed()
5994 * marked as change-unaware. in bt_gatt_encrypt_change()
6010 if (atomic_test_bit(cfg->flags, CF_CHANGE_AWARE)) { in bt_gatt_change_aware()
6015 * If a change-unaware client sends an ATT command, the server shall in bt_gatt_change_aware()
6024 * A change-unaware connected client becomes change-aware when it reads in bt_gatt_change_aware()
6028 if (atomic_test_and_clear_bit(cfg->flags, CF_DB_HASH_READ)) { in bt_gatt_change_aware()
6036 * ... a change-unaware connected client using exactly one ATT bearer in bt_gatt_change_aware()
6037 * becomes change-aware when ... in bt_gatt_change_aware()
6043 atomic_clear_bit(cfg->flags, CF_DB_HASH_READ); in bt_gatt_change_aware()
6091 ccc = attr->user_data; in ccc_save()
6094 cfg = ccc_find_cfg(ccc, save->addr_with_id.addr, save->addr_with_id.id); in ccc_save()
6099 LOG_DBG("Storing CCCs handle 0x%04x value 0x%04x", handle, cfg->value); in ccc_save()
6101 CHECKIF(save->count >= CCC_STORE_MAX) { in ccc_save()
6107 save->store[save->count].handle = handle; in ccc_save()
6108 save->store[save->count].value = cfg->value; in ccc_save()
6109 save->count++; in ccc_save()
6168 return -EINVAL; in sc_set()
6174 return -EINVAL; in sc_set()
6186 return -EINVAL; in sc_set()
6197 LOG_ERR("Unable to restore SC: no cfg left"); in sc_set()
6198 return -ENOMEM; in sc_set()
6201 cfg->id = id; in sc_set()
6202 bt_addr_le_copy(&cfg->peer, &addr); in sc_set()
6206 len = read_cb(cb_arg, &cfg->data, sizeof(cfg->data)); in sc_set()
6212 LOG_DBG("Read SC: len %zd", len); in sc_set()
6214 LOG_DBG("Restored SC for %s", bt_addr_le_str(&addr)); in sc_set()
6219 LOG_DBG("Removed SC for %s", bt_addr_le_str(&addr)); in sc_set()
6231 /* Schedule SC indication since the range has changed */ in sc_commit()
6238 BT_SETTINGS_DEFINE(sc, "sc", sc_set, sc_commit);
6254 return -EINVAL; in cf_set()
6260 return -EINVAL; in cf_set()
6272 return -EINVAL; in cf_set()
6283 return -ENOMEM; in cf_set()
6286 cfg->id = id; in cf_set()
6287 bt_addr_le_copy(&cfg->peer, &addr); in cf_set()
6299 memcpy(cfg->data, dst, sizeof(cfg->data)); in cf_set()
6303 LOG_WRN("Change-aware status not found in settings, " in cf_set()
6304 "defaulting peer status to change-unaware"); in cf_set()
6307 /* change-aware byte is present in NVS */ in cf_set()
6308 uint8_t change_aware = dst[sizeof(cfg->data)]; in cf_set()
6311 LOG_WRN("Read back bad change-aware value: 0x%x, " in cf_set()
6312 "defaulting peer status to change-unaware", in cf_set()
6374 ccc = attr->user_data; in remove_peer_from_attr()
6377 cfg = ccc_find_cfg(ccc, addr_with_id->addr, addr_with_id->id); in remove_peer_from_attr()
6425 if (id == sub->id && in find_gatt_sub()
6426 bt_addr_le_eq(addr, &sub->peer)) { in find_gatt_sub()
6445 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, params, tmp, in bt_gatt_clear_subscriptions()
6447 params->value = 0U; in bt_gatt_clear_subscriptions()
6493 gatt_store_ccc_cf(conn->id, &conn->le.dst); in bt_gatt_disconnected()
6498 bt_addr_le_is_bonded(conn->id, &conn->le.dst)) { in bt_gatt_disconnected()
6500 .addr = &conn->le.dst, in bt_gatt_disconnected()
6501 .id = conn->id, in bt_gatt_disconnected()
6520 if (req->func == gatt_read_rsp) { in bt_gatt_req_set_mtu()
6521 struct bt_gatt_read_params *params = req->user_data; in bt_gatt_req_set_mtu()
6524 params->_att_mtu = mtu; in bt_gatt_req_set_mtu()