From 552e630435a68d8f51d458dccf8697c625cf1510 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Tue, 14 Jun 2016 12:23:44 -0700 Subject: [PATCH] Fix missing GATT Characteristic from last service GATT Service is contained between start and end handle. If characteristic definition is at end handle, and it's value definition is after end handle, it will not be properly discovered. That's because we use value_handle instead of attribute_handle to identify characteristics. As a workaround, increase service boundary if value is defined after it's definition. Bug: 29253825 Change-Id: Ib145aea4f5cf38a1fbb977c301136e16f8f900f7 --- bta/gatt/bta_gattc_cache.c | 76 +++++++++++++++++++++++++++++++++------------- bta/gatt/bta_gattc_int.h | 2 ++ 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c index aaff813cf..a3ccc4096 100644 --- a/bta/gatt/bta_gattc_cache.c +++ b/bta/gatt/bta_gattc_cache.c @@ -224,6 +224,44 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb, list_append(p_srvc_cb->p_srvc_cache, p_new_srvc); return BTA_GATT_OK; } + +static tBTA_GATT_STATUS bta_gattc_add_char_to_cache(tBTA_GATTC_SERV *p_srvc_cb, + UINT16 attr_handle, + UINT16 value_handle, + tBT_UUID *p_uuid, + UINT8 property) +{ +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG("%s: Add a characteristic into Service", __func__); + APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x", + value_handle, p_uuid->uu.uuid16, property); +#endif + + tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, attr_handle); + if (!service) { + APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!"); + return GATT_WRONG_STATE; + } + + /* TODO(jpawlowski): We should use attribute handle, not value handle to refer to characteristic. + This is just a temporary workaround. + */ + if (service->e_handle < value_handle) + service->e_handle = value_handle; + + tBTA_GATTC_CHARACTERISTIC *characteristic = osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC)); + + characteristic->handle = value_handle; + characteristic->properties = property; + characteristic->descriptors = list_new(osi_free); + memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID)); + + characteristic->service = service; + list_append(service->characteristics, characteristic); + + return BTA_GATT_OK; +} + /******************************************************************************* ** ** Function bta_gattc_add_attr_to_cache @@ -252,18 +290,7 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb, return GATT_WRONG_STATE; } - if (type == BTA_GATTC_ATTR_TYPE_CHAR) { - tBTA_GATTC_CHARACTERISTIC *characteristic = - osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC)); - - characteristic->handle = handle; - characteristic->properties = property; - characteristic->descriptors = list_new(osi_free); - memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID)); - - characteristic->service = service; - list_append(service->characteristics, characteristic); - } else if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) { + if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) { tBTA_GATTC_INCLUDED_SVC *isvc = osi_malloc(sizeof(tBTA_GATTC_INCLUDED_SVC)); @@ -525,12 +552,11 @@ static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) if (p_srvc_cb->total_char > 0) { /* add the first characteristic into cache */ - bta_gattc_add_attr_to_cache (p_srvc_cb, + bta_gattc_add_char_to_cache (p_srvc_cb, + p_rec->char_decl_handle, p_rec->s_handle, &p_rec->uuid, - p_rec->property, - 0 /* incl_srvc_handle */, - BTA_GATTC_ATTR_TYPE_CHAR); + p_rec->property); /* start discoverying characteristic descriptor , if failed, disc for next char*/ bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); @@ -559,12 +585,11 @@ static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_sr { p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx); /* add the next characteristic into cache */ - bta_gattc_add_attr_to_cache (p_srvc_cb, + bta_gattc_add_char_to_cache (p_srvc_cb, + p_rec->char_decl_handle, p_rec->s_handle, &p_rec->uuid, - p_rec->property, - 0 /* incl_srvc_handle */, - BTA_GATTC_ATTR_TYPE_CHAR); + p_rec->property); /* start discoverying next characteristic for char descriptor */ bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); @@ -677,6 +702,7 @@ static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb, p_srvc_cb->total_char ++; p_rec->s_handle = value_handle; + p_rec->char_decl_handle = decl_handle; p_rec->property = property; p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle; memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID)); @@ -1173,7 +1199,7 @@ static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb, btgatt_db_element_t **db, int *count) { - APPL_TRACE_DEBUG(LOG_TAG, "%s: start_handle 0x%04x, end_handle 0x%04x", + APPL_TRACE_DEBUG("%s: start_handle 0x%04x, end_handle 0x%04x", __func__, start_handle, end_handle); if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) { @@ -1339,6 +1365,14 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr, break; case BTA_GATTC_ATTR_TYPE_CHAR: + //TODO(jpawlowski): store decl_handle properly. + bta_gattc_add_char_to_cache(p_srvc_cb, + p_attr->s_handle, + p_attr->s_handle, + &p_attr->uuid, + p_attr->prop); + break; + case BTA_GATTC_ATTR_TYPE_CHAR_DESCR: case BTA_GATTC_ATTR_TYPE_INCL_SRVC: bta_gattc_add_attr_to_cache(p_srvc_cb, diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h index c74f7d2a7..d895864c8 100644 --- a/bta/gatt/bta_gattc_int.h +++ b/bta/gatt/bta_gattc_int.h @@ -240,6 +240,8 @@ typedef struct tBT_UUID uuid; UINT16 s_handle; UINT16 e_handle; + // this field is set only for characteristic + UINT16 char_decl_handle; BOOLEAN is_primary; tBTA_GATT_CHAR_PROP property; }tBTA_GATTC_ATTR_REC; -- 2.11.0