From be107320f78d6b00298c43e6e6c57a7bc0a11377 Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Tue, 20 Mar 2018 19:27:50 +0800 Subject: [PATCH] Component/bt: fix gatt cache error - fix sev == NULL error - fix start_handle == end_handle --- .../bt/bluedroid/api/include/esp_gattc_api.h | 1 + .../bt/bluedroid/bta/gatt/bta_gattc_cache.c | 98 ++++++++++++++++--- .../bt/bluedroid/bta/gatt/bta_gatts_act.c | 8 +- .../bt/bluedroid/bta/include/bta_gatt_api.h | 1 + .../bt/bluedroid/bta/include/bta_gattc_int.h | 1 + .../btc/profile/std/gatt/btc_gattc.c | 1 + .../btc/profile/std/gatt/btc_gatts.c | 4 +- .../bluetooth/gatt_client/main/gattc_demo.c | 9 +- .../main/example_ble_sec_gattc_demo.c | 8 +- .../main/gattc_multi_connect.c | 24 ++--- 10 files changed, 116 insertions(+), 39 deletions(-) diff --git a/components/bt/bluedroid/api/include/esp_gattc_api.h b/components/bt/bluedroid/api/include/esp_gattc_api.h index 025cc4472f..44c013d5ee 100644 --- a/components/bt/bluedroid/api/include/esp_gattc_api.h +++ b/components/bt/bluedroid/api/include/esp_gattc_api.h @@ -127,6 +127,7 @@ typedef union { 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 */ /** diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c index 2108fbcd05..c43a2d4911 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c @@ -214,6 +214,40 @@ static void bta_gattc_free(void *ptr) 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 @@ -251,7 +285,12 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb, 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; } @@ -336,9 +375,14 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb, 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); @@ -502,6 +546,30 @@ void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) } } + +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 @@ -537,6 +605,11 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 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__); @@ -1022,8 +1095,8 @@ void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid) 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); } } @@ -1141,7 +1214,8 @@ void bta_gattc_get_service_with_uuid(UINT16 conn_id, tBT_UUID *svc_uuid, 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; @@ -1227,8 +1301,7 @@ void bta_gattc_get_db_with_opration(UINT16 conn_id, 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; @@ -1298,9 +1371,10 @@ void bta_gattc_get_db_with_opration(UINT16 conn_id, 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) { diff --git a/components/bt/bluedroid/bta/gatt/bta_gatts_act.c b/components/bt/bluedroid/bta/gatt/bta_gatts_act.c index 923803b83c..c93fbe0e05 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gatts_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gatts_act.c @@ -335,19 +335,19 @@ void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg) 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); diff --git a/components/bt/bluedroid/bta/include/bta_gatt_api.h b/components/bt/bluedroid/bta/include/bta_gatt_api.h index 226a9e6d6f..936cb3b420 100644 --- a/components/bt/bluedroid/bta/include/bta_gatt_api.h +++ b/components/bt/bluedroid/bta/include/bta_gatt_api.h @@ -321,6 +321,7 @@ typedef struct { UINT16 start_handle; UINT16 end_handle; tBTA_GATT_ID service_uuid; + bool is_primary; }tBTA_GATTC_SRVC_RES; typedef struct { diff --git a/components/bt/bluedroid/bta/include/bta_gattc_int.h b/components/bt/bluedroid/bta/include/bta_gattc_int.h index ad52ada53d..6df2529f77 100644 --- a/components/bt/bluedroid/bta/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/include/bta_gattc_int.h @@ -300,6 +300,7 @@ 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 diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index 32f5e39ffc..24017aece1 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -827,6 +827,7 @@ void btc_gattc_cb_handler(btc_msg_t *msg) 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; diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c index ca11213823..ae74c5ad38 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c @@ -284,8 +284,8 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, 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, diff --git a/examples/bluetooth/gatt_client/main/gattc_demo.c b/examples/bluetooth/gatt_client/main/gattc_demo.c index a2f8899f4f..31704c0948 100644 --- a/examples/bluetooth/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/gatt_client/main/gattc_demo.c @@ -132,14 +132,14 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_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_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; } @@ -222,7 +222,6 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ 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, diff --git a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c index 5294c344da..2090c8bc00 100644 --- a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c +++ b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c @@ -156,10 +156,10 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_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; diff --git a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c index 2eca1a8f1c..e5b44868e6 100644 --- a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c +++ b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c @@ -175,10 +175,10 @@ static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_i 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; @@ -375,10 +375,10 @@ static void gattc_profile_b_event_handler(esp_gattc_cb_event_t event, esp_gatt_i 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; @@ -574,10 +574,10 @@ static void gattc_profile_c_event_handler(esp_gattc_cb_event_t event, esp_gatt_i 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; -- 2.40.0