uint16_t start_handle; /*!< Service start handle */
uint16_t end_handle; /*!< Service end handle */
esp_gatt_id_t srvc_id; /*!< Service id, include service uuid and other information */
+ bool is_primary; /*!< True if this is the primary service */
} search_res; /*!< Gatt client callback param of ESP_GATTC_SEARCH_RES_EVT */
/**
osi_free(ptr);
}
+void bta_gattc_insert_sec_service_to_cache(list_t *services, tBTA_GATTC_SERVICE *p_new_srvc)
+{
+ // services/p_new_srvc is NULL
+ if (!services || !p_new_srvc) {
+ APPL_TRACE_ERROR("%s services/p_new_srvc is NULL", __func__);
+ return;
+ }
+ //list is empty
+ if (list_is_empty(services)) {
+ list_append(services, p_new_srvc);
+ } else {
+ //check the first service
+ list_node_t *sn = list_begin(services);
+ tBTA_GATTC_SERVICE *service = list_node(sn);
+ if(service && p_new_srvc->e_handle < service->s_handle) {
+ list_prepend(services, p_new_srvc);
+ } else {
+ for (list_node_t *sn = list_begin(services); sn != list_end(services); sn = list_next(sn)) {
+ list_node_t *next_sn = list_next(sn);
+ if(next_sn == list_end(services)) {
+ list_append(services, p_new_srvc);
+ return;
+ }
+ tBTA_GATTC_SERVICE *service = list_node(sn);
+ tBTA_GATTC_SERVICE *next_service = list_node(next_sn);
+ if (p_new_srvc->s_handle > service->e_handle && p_new_srvc->e_handle < next_service->s_handle) {
+ list_insert_after(services, sn, p_new_srvc);
+ return;
+ }
+ }
+ }
+ }
+}
+
/*******************************************************************************
**
** Function bta_gattc_add_srvc_to_cache
p_srvc_cb->p_srvc_cache = list_new(service_free);
}
- list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
+ if(is_primary) {
+ list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
+ } else {
+ //add secondary service into list
+ bta_gattc_insert_sec_service_to_cache(p_srvc_cb->p_srvc_cache, p_new_srvc);
+ }
return BTA_GATT_OK;
}
isvc->included_service = bta_gattc_find_matching_service(
p_srvc_cb->p_srvc_cache, incl_srvc_s_handle);
if (!isvc->included_service) {
- APPL_TRACE_ERROR("%s: Illegal action to add non-existing included service!", __func__);
- osi_free(isvc);
- return GATT_WRONG_STATE;
+ // if it is a secondary service, wait to update later
+ if(property == 0){
+ p_srvc_cb->update_sec_sev = true;
+ } else {
+ APPL_TRACE_ERROR("%s: Illegal action to add non-existing included service!", __func__);
+ osi_free(isvc);
+ return GATT_WRONG_STATE;
+ }
}
list_append(service->included_svc, isvc);
}
}
+
+void bta_gattc_update_include_service(const list_t *services) {
+ if (!services || list_is_empty(services)) {
+ return;
+ }
+ for (list_node_t *sn = list_begin(services); sn != list_end(services); sn = list_next(sn)) {
+ tBTA_GATTC_SERVICE *service = list_node(sn);
+ if(!service && list_is_empty(service->included_svc)) break;
+ for (list_node_t *sn = list_begin(service->included_svc); sn != list_end(service->included_svc); sn = list_next(sn)) {
+ tBTA_GATTC_INCLUDED_SVC *include_service = list_node(sn);
+ if(include_service && !include_service->included_service) {
+ //update
+ include_service->included_service = bta_gattc_find_matching_service(services, include_service->incl_srvc_s_handle);
+ if(!include_service->included_service) {
+ //not match, free it
+ list_remove(service->included_svc, include_service);
+ osi_free(include_service);
+ }
+ }
+ }
+
+ }
+}
+
/*******************************************************************************
**
** Function bta_gattc_explore_srvc
return;
}
}
+ //update include service when have secondary service
+ if(p_srvc_cb->update_sec_sev) {
+ bta_gattc_update_include_service(p_srvc_cb->p_srvc_cache);
+ p_srvc_cb->update_sec_sev = false;
+ }
/* no service found at all, the end of server discovery*/
LOG_DEBUG("%s no more services found", __func__);
cb_data.srvc_res.service_uuid.inst_id = p_cache->handle;
cb_data.srvc_res.start_handle = p_cache->s_handle;
cb_data.srvc_res.end_handle = p_cache->e_handle;
- memcpy(&cb_data.srvc_res.service_uuid.uuid, &p_cache->uuid, sizeof(tBTA_GATT_ID));
-
+ cb_data.srvc_res.is_primary = p_cache->is_primary;
+ memcpy(&cb_data.srvc_res.service_uuid.uuid, &p_cache->uuid, sizeof(tBT_UUID));
(* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
}
}
int *count)
{
const list_t* svc = bta_gattc_get_services(conn_id);
- if (svc == NULL) {
+ if(!svc) {
+ APPL_TRACE_WARNING("%s(), no service.", __func__);
*svc_db = NULL;
*count = 0;
return;
return;
}
- size_t db_size = ((end_handle - start_handle) < p_srcb->total_attr) ? (end_handle - start_handle) : p_srcb->total_attr;
-
+ size_t db_size = ((end_handle - start_handle + 1) < p_srcb->total_attr) ? (end_handle - start_handle + 1) : p_srcb->total_attr;
if (!db_size) {
APPL_TRACE_DEBUG("the db size is 0.");
*count = 0;
for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
-
- if (p_char->handle < start_handle) {
- continue;
+ if(op == GATT_OP_GET_ALL_CHAR || op == GATT_OP_GET_CHAR_BY_UUID) {
+ if (p_char->handle < start_handle) {
+ continue;
+ }
}
if (p_char->handle > end_handle) {
cb_data.create.status = BTA_GATT_OK;
cb_data.create.service_id = service_id;
-// btla-specific ++
+
cb_data.create.is_primary = p_msg->api_create_svc.is_pri;
-// btla-specific --
+
cb_data.create.server_if = p_cb->rcb[rcb_idx].gatt_if;
} else {
cb_data.status = BTA_GATT_ERROR;
memset(&p_cb->srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
APPL_TRACE_ERROR("service creation failed.");
}
-// btla-specific ++
+
memcpy(&cb_data.create.uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
cb_data.create.svc_instance = p_msg->api_create_svc.inst;
-// btla-specific --
+
}
if (p_cb->rcb[rcb_idx].p_cback) {
(* p_cb->rcb[rcb_idx].p_cback)(BTA_GATTS_CREATE_EVT, &cb_data);
UINT16 start_handle;
UINT16 end_handle;
tBTA_GATT_ID service_uuid;
+ bool is_primary;
}tBTA_GATTC_SRVC_RES;
typedef struct {
UINT16 attr_index; /* cahce NV saving/loading attribute index */
UINT16 mtu;
+ bool update_sec_sev;
} tBTA_GATTC_SERV;
#ifndef BTA_GATTC_NOTIF_REG_MAX
param.search_res.conn_id = BTC_GATT_GET_CONN_ID(srvc_res->conn_id);
param.search_res.start_handle = srvc_res->start_handle;
param.search_res.end_handle = srvc_res->end_handle;
+ param.search_res.is_primary = srvc_res->is_primary;
bta_to_btc_gatt_id(¶m.search_res.srvc_id, &srvc_res->service_uuid);
btc_gattc_cb_to_app(ESP_GATTC_SEARCH_RES_EVT, gattc_if, ¶m);
break;
esp_gatt_srvc_id_t esp_srvc_id;
esp_srvc_id.id.inst_id = srvc_inst_id;
- btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.uuid_length,
- gatts_attr_db[i].att_desc.uuid_p);
+ btc_gatts_uuid_format_convert(&esp_srvc_id.id.uuid,gatts_attr_db[i].att_desc.length,
+ gatts_attr_db[i].att_desc.value);
btc_to_bta_srvc_id(&srvc_id, &esp_srvc_id);
if (btc_creat_tab_env.is_use_svc != true) {
BTA_GATTS_CreateService(gatts_if, &srvc_id.id.uuid,
esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
break;
case ESP_GATTC_SEARCH_RES_EVT: {
- ESP_LOGI(GATTC_TAG, "ESP_GATTC_SEARCH_RES_EVT");
- esp_gatt_srvc_id_t *srvc_id =(esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
- if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
+ ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary);
+ ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.start_handle, p_data->search_res.srvc_id.inst_id);
+ if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && p_data->search_res.srvc_id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
ESP_LOGI(GATTC_TAG, "service found");
get_server = true;
gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;
gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;
- ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
+ ESP_LOGI(GATTC_TAG, "UUID16: %x", p_data->search_res.srvc_id.uuid.uuid.uuid16);
}
break;
}
if (ret_status != ESP_GATT_OK){
ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
}
-
/* Every char has only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */
if (count > 0 && descr_elem_result[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
ret_status = esp_ble_gattc_write_char_descr( gattc_if,
esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
break;
case ESP_GATTC_SEARCH_RES_EVT: {
- esp_gatt_srvc_id_t *srvc_id =(esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
- ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
- if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
- ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
+ ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary);
+ ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.start_handle, p_data->search_res.srvc_id.inst_id);
+ if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && p_data->search_res.srvc_id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
+ ESP_LOGI(GATTC_TAG, "UUID16: %x", p_data->search_res.srvc_id.uuid.uuid.uuid16);
get_service = true;
gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;
gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;
esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
break;
case ESP_GATTC_SEARCH_RES_EVT: {
- esp_gatt_srvc_id_t *srvc_id = (esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
- ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
- if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
- ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
+ ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary);
+ ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.start_handle, p_data->search_res.srvc_id.inst_id);
+ if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && p_data->search_res.srvc_id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
+ ESP_LOGI(GATTC_TAG, "UUID16: %x", p_data->search_res.srvc_id.uuid.uuid.uuid16);
get_service_a = true;
gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;
gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;
esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
break;
case ESP_GATTC_SEARCH_RES_EVT: {
- esp_gatt_srvc_id_t *srvc_id = (esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
- ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
- if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
- ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
+ ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary);
+ ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.start_handle, p_data->search_res.srvc_id.inst_id);
+ if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && p_data->search_res.srvc_id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
+ ESP_LOGI(GATTC_TAG, "UUID16: %x", p_data->search_res.srvc_id.uuid.uuid.uuid16);
get_service_b = true;
gl_profile_tab[PROFILE_B_APP_ID].service_start_handle = p_data->search_res.start_handle;
gl_profile_tab[PROFILE_B_APP_ID].service_end_handle = p_data->search_res.end_handle;
esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, &remote_filter_service_uuid);
break;
case ESP_GATTC_SEARCH_RES_EVT: {
- esp_gatt_srvc_id_t *srvc_id = (esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
- ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x", p_data->search_res.conn_id);
- if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
- ESP_LOGI(GATTC_TAG, "UUID16: %x", srvc_id->id.uuid.uuid.uuid16);
+ ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary);
+ ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.start_handle, p_data->search_res.srvc_id.inst_id);
+ if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16 && p_data->search_res.srvc_id.uuid.uuid.uuid16 == REMOTE_SERVICE_UUID) {
+ ESP_LOGI(GATTC_TAG, "UUID16: %x", p_data->search_res.srvc_id.uuid.uuid.uuid16);
get_service_c = true;
gl_profile_tab[PROFILE_C_APP_ID].service_start_handle = p_data->search_res.start_handle;
gl_profile_tab[PROFILE_C_APP_ID].service_end_handle = p_data->search_res.end_handle;