bool BLECharacteristicImp::discoverAttributes(BLEDevice* device) { int err; bt_conn_t* conn; bt_gatt_discover_params_t* temp = NULL; const bt_uuid_t* service_uuid = bt_uuid(); if (service_uuid->type == BT_UUID_TYPE_16) { uint16_t uuid_tmp ;//= ((bt_uuid_16_t*)service_uuid)->val; memcpy(&uuid_tmp, &((bt_uuid_16_t*)service_uuid)->val, sizeof(uuid_tmp)); if (BT_UUID_GAP_VAL == uuid_tmp || BT_UUID_GATT_VAL == uuid_tmp) { return false; } } conn = bt_conn_lookup_addr_le(device->bt_le_address()); if (NULL == conn) { // Link lost pr_debug(LOG_MODULE_BLE, "Can't find connection\n"); return false; } temp = &_discover_params; temp->start_handle = _value_handle + 1; temp->end_handle = _value_handle + 20; // TODO: the max descriptor is not more than 20 temp->uuid = NULL; temp->type = BT_GATT_DISCOVER_DESCRIPTOR; temp->func = profile_discover_process; pr_debug(LOG_MODULE_BLE, "%s-%d-charc",__FUNCTION__, __LINE__); err = bt_gatt_discover(conn, temp); bt_conn_unref(conn); if (err) { pr_debug(LOG_MODULE_BLE, "Discover failed(err %d)\n", err); return false; } return true; }
static void att_find_type_rsp(struct bt_conn *conn, uint8_t err, const void *pdu, uint16_t length, void *user_data) { const struct bt_att_find_type_rsp *rsp = pdu; struct bt_gatt_discover_params *params = user_data; struct bt_gatt_service value; uint8_t i; uint16_t end_handle = 0, start_handle; BT_DBG("err 0x%02x", err); if (err) { goto done; } /* Parse attributes found */ for (i = 0; length >= sizeof(rsp->list[i]); i++, length -= sizeof(rsp->list[i])) { struct bt_gatt_attr *attr; start_handle = sys_le16_to_cpu(rsp->list[i].start_handle); end_handle = sys_le16_to_cpu(rsp->list[i].end_handle); BT_DBG("start_handle 0x%04x end_handle 0x%04x", start_handle, end_handle); value.end_handle = end_handle; value.uuid = params->uuid; if (params->type == BT_GATT_DISCOVER_PRIMARY) { attr = (&(struct bt_gatt_attr) BT_GATT_PRIMARY_SERVICE(&value)); } else { attr = (&(struct bt_gatt_attr) BT_GATT_SECONDARY_SERVICE(&value)); } attr->handle = start_handle; if (params->func(conn, attr, params) == BT_GATT_ITER_STOP) { return; } } /* Stop if could not parse the whole PDU */ if (length > 0) { goto done; } /* Stop if over the range or the requests */ if (end_handle >= params->end_handle) { goto done; } /* Continue for the last found handle */ params->start_handle = end_handle; if (!bt_gatt_discover(conn, params)) { return; } done: params->func(conn, NULL, params); }
static void att_find_info_rsp(struct bt_conn *conn, uint8_t err, const void *pdu, uint16_t length, void *user_data) { const struct bt_att_find_info_rsp *rsp = pdu; struct bt_gatt_discover_params *params = user_data; uint16_t handle = 0; uint8_t len; union { const struct bt_att_info_16 *i16; const struct bt_att_info_128 *i128; } info; union { struct bt_uuid uuid; struct bt_uuid_16 u16; struct bt_uuid_128 u128; } u; BT_DBG("err 0x%02x", err); if (err) { goto done; } /* Data can be either in UUID16 or UUID128 */ switch (rsp->format) { case BT_ATT_INFO_16: u.uuid.type = BT_UUID_TYPE_16; len = sizeof(*info.i16); break; case BT_ATT_INFO_128: u.uuid.type = BT_UUID_TYPE_128; len = sizeof(*info.i128); break; default: BT_ERR("Invalid format %u", rsp->format); goto done; } /* Parse descriptors found */ for (length--, pdu = rsp->info; length >= len; length -= len, pdu += len) { struct bt_gatt_attr *attr; info.i16 = pdu; handle = sys_le16_to_cpu(info.i16->handle); switch (u.uuid.type) { case BT_UUID_TYPE_16: u.u16.val = sys_le16_to_cpu(info.i16->uuid); break; case BT_UUID_TYPE_128: memcpy(u.u128.val, info.i128->uuid, 16); break; } BT_DBG("handle 0x%04x uuid %s", handle, bt_uuid_str(&u.uuid)); /* Skip if UUID is set but doesn't match */ if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) { continue; } attr = (&(struct bt_gatt_attr) BT_GATT_DESCRIPTOR(&u.uuid, 0, NULL, NULL, NULL)); attr->handle = handle; if (params->func(conn, attr, params) == BT_GATT_ITER_STOP) { return; } } /* Stop if could not parse the whole PDU */ if (length > 0) { goto done; } /* Next characteristic shall be after current value handle */ params->start_handle = handle; if (params->start_handle < UINT16_MAX) { params->start_handle++; } /* Stop if over the requested range */ if (params->start_handle >= params->end_handle) { goto done; } /* Continue to the next range */ if (!bt_gatt_discover(conn, params)) { return; } done: params->func(conn, NULL, params); }