static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params) { int err; if (!attr) { printk("Discover complete\n"); memset(params, 0, sizeof(*params)); return BT_GATT_ITER_STOP; } printk("[ATTRIBUTE] handle %u\n", attr->handle); if (BT_UUID_16(discover_params.uuid)->val == BT_UUID_HRS_VAL) { uuid.val = BT_UUID_HRS_MEASUREMENT_VAL; discover_params.uuid = &uuid.uuid; discover_params.start_handle = attr->handle + 1; discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; err = bt_gatt_discover(conn, &discover_params); if (err) { printk("Discover failed (err %d)\n", err); } } else if (BT_UUID_16(discover_params.uuid)->val == BT_UUID_HRS_MEASUREMENT_VAL) { uuid.val = BT_UUID_GATT_CCC_VAL; discover_params.uuid = &uuid.uuid; discover_params.start_handle = attr->handle + 2; discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR; subscribe_params.value_handle = attr->handle + 1; err = bt_gatt_discover(conn, &discover_params); if (err) { printk("Discover failed (err %d)\n", err); } } else { subscribe_params.notify = notify_func; subscribe_params.value = BT_GATT_CCC_NOTIFY; subscribe_params.ccc_handle = attr->handle; err = bt_gatt_subscribe(conn, &subscribe_params); if (err && err != -EALREADY) { printk("Subscribe failed (err %d)\n", err); } else { printk("[SUBSCRIBED]\n"); } return BT_GATT_ITER_STOP; } return BT_GATT_ITER_STOP; }
int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2) { /* Convert to 128 bit if types don't match */ if (u1->type != u2->type) return uuid128_cmp(u1, u2); switch (u1->type) { case BT_UUID_TYPE_16: return (int)BT_UUID_16(u1)->val - (int)BT_UUID_16(u2)->val; case BT_UUID_TYPE_128: return memcmp(BT_UUID_128(u1)->val, BT_UUID_128(u2)->val, 16); } return -EINVAL; }
void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len) { uint32_t tmp1, tmp5; uint16_t tmp0, tmp2, tmp3, tmp4; switch (uuid->type) { case BT_UUID_TYPE_16: snprintf(str, len, "%.4x", BT_UUID_16(uuid)->val); break; case BT_UUID_TYPE_128: memcpy(&tmp0, &BT_UUID_128(uuid)->val[0], sizeof(tmp0)); memcpy(&tmp1, &BT_UUID_128(uuid)->val[2], sizeof(tmp1)); memcpy(&tmp2, &BT_UUID_128(uuid)->val[6], sizeof(tmp2)); memcpy(&tmp3, &BT_UUID_128(uuid)->val[8], sizeof(tmp3)); memcpy(&tmp4, &BT_UUID_128(uuid)->val[10], sizeof(tmp4)); memcpy(&tmp5, &BT_UUID_128(uuid)->val[12], sizeof(tmp5)); snprintf(str, len, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", tmp5, tmp4, tmp3, tmp2, tmp1, tmp0); break; default: memset(str, 0, len); return; } }
bool BLECharacteristicImp::isClientCharacteristicConfigurationDescriptor(const bt_uuid_t* uuid) { bool ret = false; uint16_t cccd_uuid = BT_UUID_GATT_CCC_VAL; if (uuid->type == BT_UUID_TYPE_16) { if (0 == memcmp(&BT_UUID_16(uuid)->val, &cccd_uuid, sizeof(uint16_t))) { ret = true; } } return ret; }
static void uuid_to_uuid128(const struct bt_uuid *src, struct bt_uuid_128 *dst) { switch (src->type) { case BT_UUID_TYPE_16: *dst = uuid128_base; u16_to_uuid128(&dst->val[UUID_16_BASE_OFFSET], BT_UUID_16(src)->val); return; case BT_UUID_TYPE_128: memcpy(dst, src, sizeof(*dst)); return; } }
static uint8_t find_info_cb(const struct bt_gatt_attr *attr, void *user_data) { struct find_info_data *data = user_data; struct bt_att *att = data->att; BT_DBG("handle 0x%04x", attr->handle); /* Initialize rsp at first entry */ if (!data->rsp) { data->rsp = net_buf_add(data->buf, sizeof(*data->rsp)); data->rsp->format = (attr->uuid->type == BT_UUID_TYPE_16) ? BT_ATT_INFO_16 : BT_ATT_INFO_128; } switch (data->rsp->format) { case BT_ATT_INFO_16: if (attr->uuid->type != BT_UUID_TYPE_16) { return BT_GATT_ITER_STOP; } /* Fast foward to next item position */ data->info16 = net_buf_add(data->buf, sizeof(*data->info16)); data->info16->handle = sys_cpu_to_le16(attr->handle); data->info16->uuid = sys_cpu_to_le16(BT_UUID_16(attr->uuid)->val); if (att->chan.tx.mtu - data->buf->len > sizeof(*data->info16)) { return BT_GATT_ITER_CONTINUE; } break; case BT_ATT_INFO_128: if (attr->uuid->type != BT_UUID_TYPE_128) { return BT_GATT_ITER_STOP; } /* Fast foward to next item position */ data->info128 = net_buf_add(data->buf, sizeof(*data->info128)); data->info128->handle = sys_cpu_to_le16(attr->handle); memcpy(data->info128->uuid, BT_UUID_128(attr->uuid)->val, sizeof(data->info128->uuid)); if (att->chan.tx.mtu - data->buf->len > sizeof(*data->info128)) { return BT_GATT_ITER_CONTINUE; } } return BT_GATT_ITER_STOP; }
static bool uuid_create(struct bt_uuid *uuid, struct net_buf *buf) { switch (buf->len) { case 2: uuid->type = BT_UUID_TYPE_16; BT_UUID_16(uuid)->val = net_buf_pull_le16(buf); return true; case 16: uuid->type = BT_UUID_TYPE_128; memcpy(BT_UUID_128(uuid)->val, buf->data, buf->len); return true; } return false; }
int bt_gatt_attr_read_service(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { struct bt_uuid *uuid = attr->user_data; if (uuid->type == BT_UUID_TYPE_16) { uint16_t uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val); return bt_gatt_attr_read(conn, attr, buf, len, offset, &uuid16, 2); } return bt_gatt_attr_read(conn, attr, buf, len, offset, BT_UUID_128(uuid)->val, 16); }
static int att_find_type(struct bt_conn *conn, struct bt_gatt_discover_params *params) { struct net_buf *buf; struct bt_att_find_type_req *req; buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_TYPE_REQ, sizeof(*req)); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->start_handle = sys_cpu_to_le16(params->start_handle); req->end_handle = sys_cpu_to_le16(params->end_handle); if (params->type == BT_GATT_DISCOVER_PRIMARY) { req->type = sys_cpu_to_le16(BT_UUID_GATT_PRIMARY_VAL); } else { req->type = sys_cpu_to_le16(BT_UUID_GATT_SECONDARY_VAL); } BT_DBG("uuid %s start_handle 0x%04x end_handle 0x%04x", bt_uuid_str(params->uuid), params->start_handle, params->end_handle); switch (params->uuid->type) { case BT_UUID_TYPE_16: net_buf_add_le16(buf, BT_UUID_16(params->uuid)->val); break; case BT_UUID_TYPE_128: memcpy(net_buf_add(buf, 16), BT_UUID_128(params->uuid)->val, 16); break; default: BT_ERR("Unknown UUID type %u", params->uuid->type); net_buf_unref(buf); return -EINVAL; } return gatt_send(conn, buf, att_find_type_rsp, params, NULL); }
int bt_gatt_attr_read_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { struct bt_gatt_chrc *chrc = attr->user_data; struct gatt_chrc pdu; const struct bt_gatt_attr *next; uint8_t value_len; pdu.properties = chrc->properties; /* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] page 534: * 3.3.2 Characteristic Value Declaration * The Characteristic Value declaration contains the value of the * characteristic. It is the first Attribute after the characteristic * declaration. All characteristic definitions shall have a * Characteristic Value declaration. */ next = bt_gatt_attr_next(attr); if (!next) { BT_WARN("No value for characteristic at 0x%04x", attr->handle); pdu.value_handle = 0x0000; } else { pdu.value_handle = sys_cpu_to_le16(next->handle); } value_len = sizeof(pdu.properties) + sizeof(pdu.value_handle); if (chrc->uuid->type == BT_UUID_TYPE_16) { pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(chrc->uuid)->val); value_len += 2; } else { memcpy(pdu.uuid, BT_UUID_128(chrc->uuid)->val, 16); value_len += 16; } return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); }
int bt_gatt_attr_read_included(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { struct bt_gatt_include *incl = attr->user_data; struct gatt_incl pdu; uint8_t value_len; pdu.start_handle = sys_cpu_to_le16(incl->start_handle); pdu.end_handle = sys_cpu_to_le16(incl->end_handle); value_len = sizeof(pdu.start_handle) + sizeof(pdu.end_handle); /* * Core 4.2, Vol 3, Part G, 3.2, * The Service UUID shall only be present when the UUID is a 16-bit * Bluetooth UUID. */ if (incl->uuid->type == BT_UUID_TYPE_16) { pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(incl->uuid)->val); value_len += sizeof(pdu.uuid16); } return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len); }