Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2003-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  This file contains the GATT client discovery procedures and cache
     22  *  related functions.
     23  *
     24  ******************************************************************************/
     25 
     26 #include "bt_target.h"
     27 
     28 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
     29 
     30 #include <string.h>
     31 #include "utl.h"
     32 #include "gki.h"
     33 #include "bta_sys.h"
     34 #include "sdp_api.h"
     35 #include "sdpdefs.h"
     36 #include "bta_gattc_int.h"
     37 #include "btm_api.h"
     38 #include "btm_ble_api.h"
     39 
     40 #define LOG_TAG "bt_bta_gattc"
     41 #include "osi/include/log.h"
     42 
     43 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
     44 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
     45 
     46 #define BTA_GATT_SDP_DB_SIZE 4096
     47 
     48 /*****************************************************************************
     49 **  Constants
     50 *****************************************************************************/
     51 
     52 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
     53 static char *bta_gattc_attr_type[] =
     54 {
     55     "I", /* Included Service */
     56     "C", /* Characteristic */
     57     "D" /* Characteristic Descriptor */
     58 };
     59 /* utility functions */
     60 
     61 /*******************************************************************************
     62 **
     63 ** Function         bta_gattc_display_cache_server
     64 **
     65 ** Description      debug function to display the server cache.
     66 **
     67 ** Returns          none.
     68 **
     69 *******************************************************************************/
     70 static void bta_gattc_display_cache_server(tBTA_GATTC_CACHE *p_cache)
     71 {
     72     UINT8 i = 0, j;
     73     tBTA_GATTC_CACHE    *p_cur_srvc = p_cache;
     74     tBTA_GATTC_CACHE_ATTR   *p_attr;
     75 
     76     APPL_TRACE_ERROR("<================Start Server Cache =============>");
     77 
     78     while (p_cur_srvc)
     79     {
     80         APPL_TRACE_ERROR("Service[%d]: handle[%d ~ %d] %s[0x%04x] inst[%d]",
     81                           i, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
     82                           ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
     83                           p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
     84                           p_cur_srvc->service_uuid.id.inst_id);
     85         i ++;
     86 
     87         p_attr = p_cur_srvc->p_attr;
     88 
     89         for (j = 0; p_attr; j ++ )
     90         {
     91             APPL_TRACE_ERROR("\t Attr[0x%04x] handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]",
     92                               j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id,
     93                               bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
     94 
     95             p_attr = p_attr->p_next;
     96         }
     97         p_cur_srvc = p_cur_srvc->p_next;
     98     }
     99 
    100     APPL_TRACE_ERROR("<================End Server Cache =============>");
    101     APPL_TRACE_ERROR(" ");
    102 }
    103 
    104 /*******************************************************************************
    105 **
    106 ** Function         bta_gattc_display_explore_record
    107 **
    108 ** Description      debug function to display the exploration list
    109 **
    110 ** Returns          none.
    111 **
    112 *******************************************************************************/
    113 static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
    114 {
    115     UINT8 i;
    116     tBTA_GATTC_ATTR_REC *pp = p_rec;
    117 
    118     APPL_TRACE_ERROR("<================Start Explore Queue =============>");
    119     for (i = 0; i < num_rec; i ++, pp ++)
    120     {
    121         APPL_TRACE_ERROR("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
    122                           i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
    123     }
    124     APPL_TRACE_ERROR("<================ End Explore Queue =============>");
    125     APPL_TRACE_ERROR(" ");
    126 
    127 }
    128 #endif  /* BTA_GATT_DEBUG == TRUE */
    129 
    130 
    131 /*******************************************************************************
    132 **
    133 ** Function         bta_gattc_alloc_cache_buf
    134 **
    135 ** Description      Allocate a GKI buffer for database cache.
    136 **
    137 ** Returns          status
    138 **
    139 *******************************************************************************/
    140 BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb)
    141 {
    142     BT_HDR  *p_buf;
    143 
    144     if ((p_buf = (BT_HDR *)GKI_getpoolbuf(GATT_DB_POOL_ID)) == NULL)
    145     {
    146         APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
    147         utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
    148         p_srvc_cb->free_byte = 0;
    149     }
    150     else
    151     {
    152         memset(p_buf, 0, GKI_get_buf_size(p_buf));
    153         p_srvc_cb->p_free = (UINT8 *) p_buf;
    154         p_srvc_cb->free_byte = GKI_get_buf_size(p_buf);
    155 
    156         /* link into buffer queue */
    157         GKI_enqueue(&p_srvc_cb->cache_buffer, p_buf);
    158     }
    159 #if BTA_GATT_DEBUG== TRUE
    160     APPL_TRACE_DEBUG("allocating new buffer: free byte = %d", p_srvc_cb->free_byte);
    161 #endif
    162     return p_buf;
    163 }
    164 /*******************************************************************************
    165 **
    166 ** Function         bta_gattc_init_cache
    167 **
    168 ** Description      Initialize the database cache and discovery related resources.
    169 **
    170 ** Returns          status
    171 **
    172 *******************************************************************************/
    173 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
    174 {
    175     tBTA_GATT_STATUS    status = BTA_GATT_OK;
    176 
    177     while (!GKI_queue_is_empty(&p_srvc_cb->cache_buffer))
    178         GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
    179 
    180     utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
    181 
    182     if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC*)GKI_getbuf(BTA_GATTC_ATTR_LIST_SIZE)) == NULL)
    183     {
    184         APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
    185         status = GATT_NO_RESOURCES;
    186     }
    187     else
    188     {
    189         p_srvc_cb->total_srvc = 0;
    190         p_srvc_cb->cur_srvc_idx =
    191         p_srvc_cb->cur_char_idx =
    192         p_srvc_cb->next_avail_idx = 0;
    193 
    194         if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
    195         {
    196             status = GATT_NO_RESOURCES;
    197         }
    198         else
    199         {
    200             p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
    201         }
    202     }
    203 
    204     return status;
    205 }
    206 /*******************************************************************************
    207 **
    208 ** Function         bta_gattc_get_srvc_inst_id
    209 **
    210 ** Description      get service instance number
    211 **
    212 ** Returns          instance ID of the service.
    213 **
    214 *******************************************************************************/
    215 static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid)
    216 {
    217     UINT8 i = 0, inst = 0;
    218     tBTA_GATTC_ATTR_REC   *p_srvc_rec;
    219 
    220     for (i = 0; i < p_srvc_cb->total_srvc; i ++)
    221     /*
    222     for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/
    223     {
    224         p_srvc_rec = p_srvc_cb->p_srvc_list + i;
    225 
    226         if (bta_gattc_uuid_compare(&p_srvc_rec->uuid, &uuid, TRUE))
    227             inst ++;
    228     }
    229     return inst ;
    230 }
    231 /*******************************************************************************
    232 **
    233 ** Function         bta_gattc_get_char_inst_id
    234 **
    235 ** Description      get characteristic instance number
    236 **
    237 ** Returns          characteristic instance ID.
    238 **
    239 *******************************************************************************/
    240 static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID *p_uuid)
    241 {
    242     UINT8 inst = 0;
    243     tBTA_GATTC_CACHE_ATTR   *p_attr;
    244     tBT_UUID    attr_uuid;
    245 
    246     p_attr = p_service_cache->p_attr;
    247 
    248     while (p_attr)
    249     {
    250         bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
    251 
    252         if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
    253             inst ++;
    254 
    255         p_attr = p_attr->p_next;
    256     }
    257 
    258     return inst ;
    259 }
    260 /*******************************************************************************
    261 **
    262 ** Function         bta_gattc_get_char_descr_inst_id
    263 **
    264 ** Description      get characteristic descriptor instance number
    265 **
    266 ** Returns          characteristic instance ID.
    267 **
    268 *******************************************************************************/
    269 static UINT8 bta_gattc_get_char_descr_inst_id(tBTA_GATTC_CACHE_ATTR *p_char_attr, tBT_UUID *p_uuid)
    270 {
    271     UINT8 inst = 0;
    272     tBT_UUID    attr_uuid;
    273 
    274     if (p_char_attr != NULL)
    275         p_char_attr = p_char_attr->p_next;
    276 
    277     while (p_char_attr)
    278     {
    279         bta_gattc_pack_attr_uuid(p_char_attr, &attr_uuid);
    280 
    281         if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
    282             inst ++;
    283 
    284         p_char_attr = p_char_attr->p_next;
    285     }
    286     return inst ;
    287 }
    288 
    289 /*******************************************************************************
    290 **
    291 ** Function         bta_gattc_add_srvc_to_cache
    292 **
    293 ** Description      Add a service into database cache.
    294 **
    295 ** Returns          status
    296 **
    297 *******************************************************************************/
    298 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
    299                                                     UINT16 s_handle, UINT16 e_handle,
    300                                                     tBT_UUID *p_uuid,
    301                                                     BOOLEAN is_primary, UINT8 srvc_inst)
    302 {
    303     tBTA_GATTC_CACHE    *p_new_srvc = NULL;
    304     tBTA_GATT_STATUS    status = BTA_GATT_OK;
    305 
    306 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
    307     APPL_TRACE_DEBUG("Add a service into Service");
    308     APPL_TRACE_DEBUG("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, sizeof(tBTA_GATTC_CACHE))
    309 #endif
    310 
    311     if (p_srvc_cb->free_byte < sizeof(tBTA_GATTC_CACHE))
    312     {
    313         if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
    314             return GATT_NO_RESOURCES;
    315     }
    316 
    317     p_new_srvc = (tBTA_GATTC_CACHE *)p_srvc_cb->p_free;
    318     /* update service information */
    319     p_new_srvc->s_handle = s_handle;
    320     p_new_srvc->e_handle = e_handle;
    321     p_new_srvc->service_uuid.is_primary = is_primary;
    322     memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
    323     p_new_srvc->service_uuid.id.inst_id = srvc_inst;
    324     p_new_srvc->p_next  = NULL;
    325 
    326     if (p_srvc_cb->p_cur_srvc != NULL)
    327         p_srvc_cb->p_cur_srvc->p_next = p_new_srvc;
    328     p_srvc_cb->p_cur_srvc = p_new_srvc;
    329     p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
    330 
    331     /* first service */
    332     if (p_srvc_cb->p_srvc_cache == NULL)
    333         p_srvc_cb->p_srvc_cache = p_new_srvc;
    334 
    335     /* update buffer managament info */
    336     p_srvc_cb->p_free += sizeof(tBTA_GATTC_CACHE);
    337     p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE);
    338 
    339 
    340     return status;
    341 }
    342 /*******************************************************************************
    343 **
    344 ** Function         bta_gattc_add_attr_to_cache
    345 **
    346 ** Description      Add an attribute into database cache buffer.
    347 **
    348 ** Returns          status
    349 **
    350 *******************************************************************************/
    351 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
    352                                                     UINT16 handle,
    353                                                     tBT_UUID *p_uuid,
    354                                                     UINT8 property,
    355                                                     tBTA_GATTC_ATTR_TYPE type)
    356 {
    357     tBTA_GATTC_CACHE_ATTR *p_attr;
    358     tBTA_GATT_STATUS    status = BTA_GATT_OK;
    359     UINT16  len = sizeof(tBTA_GATTC_CACHE_ATTR) + p_uuid->len;
    360     UINT8   *pp;
    361 
    362 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
    363     APPL_TRACE_DEBUG("bta_gattc_add_attr_to_cache: Add a [%s] into Service", bta_gattc_attr_type[type]);
    364     APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
    365     APPL_TRACE_DEBUG("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, len);
    366 #endif
    367 
    368     if (p_srvc_cb->p_cur_srvc == NULL)
    369     {
    370         APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc before adding a service!");
    371         return GATT_WRONG_STATE;
    372     }
    373 
    374     if (p_srvc_cb->free_byte < len)
    375     {
    376         if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
    377             return GATT_NO_RESOURCES;
    378     }
    379 
    380     p_attr = (tBTA_GATTC_CACHE_ATTR *)p_srvc_cb->p_free;
    381 
    382     p_attr->attr_handle = handle;
    383     p_attr->attr_type   = type;
    384     p_attr->property    = property;
    385     p_attr->uuid_len    = p_uuid->len;
    386     p_attr->p_uuid      = (tBTA_GATTC_UUID *)(p_attr + 1);
    387     p_attr->p_next      = NULL;
    388 
    389     pp = (UINT8 *)p_attr->p_uuid;
    390 
    391     if (p_uuid->len == LEN_UUID_16)
    392     {
    393         UINT16_TO_STREAM(pp, p_uuid->uu.uuid16);
    394     }
    395     else if (p_uuid->len == LEN_UUID_128)
    396     {
    397         memcpy(pp, p_uuid->uu.uuid128, LEN_UUID_128);
    398     }
    399 
    400     if (type == BTA_GATTC_ATTR_TYPE_CHAR)
    401     {
    402         p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, p_uuid);
    403         p_srvc_cb->p_cur_srvc->p_cur_char = p_attr;
    404     }
    405     else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
    406         p_attr->inst_id = bta_gattc_get_char_descr_inst_id(p_srvc_cb->p_cur_srvc->p_cur_char, p_uuid);
    407     else /* TODO: --->> temp treat included service as single instance */
    408         p_attr->inst_id = 0;
    409 
    410     /* update service information */
    411     p_srvc_cb->p_free += len;
    412     p_srvc_cb->free_byte -= len;
    413 
    414     /* first attribute within the service, update the attribute pointer */
    415     if (p_srvc_cb->p_cur_srvc->p_attr == NULL)
    416     {
    417         p_srvc_cb->p_cur_srvc->p_attr = p_attr;
    418     }
    419     if (p_srvc_cb->p_cur_srvc->p_last_attr != NULL)
    420         p_srvc_cb->p_cur_srvc->p_last_attr->p_next = p_attr;
    421 
    422     p_srvc_cb->p_cur_srvc->p_last_attr = p_attr;
    423 
    424     return status;
    425 }
    426 
    427 /*******************************************************************************
    428 **
    429 ** Function         bta_gattc_get_disc_range
    430 **
    431 ** Description      get discovery stating and ending handle range.
    432 **
    433 ** Returns          None.
    434 **
    435 *******************************************************************************/
    436 void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
    437 {
    438     tBTA_GATTC_ATTR_REC *p_rec = NULL;
    439 
    440     if (is_srvc)
    441     {
    442         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
    443         *p_s_hdl = p_rec->s_handle;
    444     }
    445     else
    446     {
    447         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
    448         *p_s_hdl = p_rec->s_handle + 1;
    449     }
    450 
    451     *p_e_hdl = p_rec->e_handle;
    452 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
    453     APPL_TRACE_DEBUG("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle);
    454 #endif
    455     return;
    456 }
    457 /*******************************************************************************
    458 **
    459 ** Function         bta_gattc_discover_pri_service
    460 **
    461 ** Description      Start primary service discovery
    462 **
    463 ** Returns          status of the operation.
    464 **
    465 *******************************************************************************/
    466 tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
    467                                                     UINT8 disc_type)
    468 {
    469     tBTA_GATTC_CLCB     *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    470     tBTA_GATT_STATUS    status =  BTA_GATT_ERROR;
    471 
    472     if (p_clcb)
    473     {
    474         if (p_clcb->transport == BTA_TRANSPORT_LE)
    475             status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
    476         else
    477             status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
    478     }
    479 
    480     return status;
    481 }
    482 /*******************************************************************************
    483 **
    484 ** Function         bta_gattc_discover_procedure
    485 **
    486 ** Description      Start a particular type of discovery procedure on server.
    487 **
    488 ** Returns          status of the operation.
    489 **
    490 *******************************************************************************/
    491 tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
    492                                                    UINT8 disc_type)
    493 {
    494     tGATT_DISC_PARAM param;
    495     BOOLEAN is_service = TRUE;
    496 
    497     memset(&param, 0, sizeof(tGATT_DISC_PARAM));
    498 
    499     if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID)
    500     {
    501         param.s_handle = 1;
    502         param.e_handle = 0xFFFF;
    503     }
    504     else
    505     {
    506         if (disc_type == GATT_DISC_CHAR_DSCPT)
    507             is_service = FALSE;
    508 
    509         bta_gattc_get_disc_range(p_server_cb, &param.s_handle, &param.e_handle, is_service);
    510 
    511         if (param.s_handle > param.e_handle)
    512         {
    513             return GATT_ERROR;
    514         }
    515     }
    516     return GATTC_Discover (conn_id, disc_type, &param);
    517 
    518 }
    519 /*******************************************************************************
    520 **
    521 ** Function         bta_gattc_start_disc_include_srvc
    522 **
    523 ** Description      Start discovery for included service
    524 **
    525 ** Returns          status of the operation.
    526 **
    527 *******************************************************************************/
    528 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
    529 {
    530     return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
    531 }
    532 /*******************************************************************************
    533 **
    534 ** Function         bta_gattc_start_disc_char
    535 **
    536 ** Description      Start discovery for characteristic
    537 **
    538 ** Returns          status of the operation.
    539 **
    540 *******************************************************************************/
    541 tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
    542 {
    543     p_srvc_cb->total_char = 0;
    544 
    545     return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
    546 }
    547 /*******************************************************************************
    548 **
    549 ** Function         bta_gattc_start_disc_char_dscp
    550 **
    551 ** Description      Start discovery for characteristic descriptor
    552 **
    553 ** Returns          none.
    554 **
    555 *******************************************************************************/
    556 void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
    557 {
    558     APPL_TRACE_DEBUG("starting discover characteristics descriptor");
    559 
    560     if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0)
    561         bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
    562 
    563 }
    564 /*******************************************************************************
    565 **
    566 ** Function         bta_gattc_explore_srvc
    567 **
    568 ** Description      process the service discovery complete event
    569 **
    570 ** Returns          status
    571 **
    572 *******************************************************************************/
    573 static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
    574 {
    575     tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
    576     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    577 
    578     APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
    579 
    580     p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
    581 
    582     if (p_clcb == NULL)
    583     {
    584         APPL_TRACE_ERROR("unknown connection ID");
    585         return;
    586     }
    587     /* start expore a service if there is service not been explored */
    588     if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc)
    589     {
    590         /* add the first service into cache */
    591         if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
    592                                          p_rec->s_handle,
    593                                          p_rec->e_handle,
    594                                          &p_rec->uuid,
    595                                          p_rec->is_primary,
    596                                          p_rec->srvc_inst_id) == 0)
    597         {
    598             /* start discovering included services */
    599             bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
    600             return;
    601         }
    602     }
    603     /* no service found at all, the end of server discovery*/
    604     LOG_WARN("%s no more services found", __func__);
    605 
    606 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
    607     bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
    608 #endif
    609     /* save cache to NV */
    610     p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
    611     bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
    612                             conn_id, TRUE);
    613 }
    614 /*******************************************************************************
    615 **
    616 ** Function         bta_gattc_incl_srvc_disc_cmpl
    617 **
    618 ** Description      process the relationship discovery complete event
    619 **
    620 ** Returns          status
    621 **
    622 *******************************************************************************/
    623 static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
    624 {
    625     p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
    626 
    627     /* start discoverying characteristic */
    628     bta_gattc_start_disc_char(conn_id, p_srvc_cb);
    629 }
    630 /*******************************************************************************
    631 **
    632 ** Function         bta_gattc_char_disc_cmpl
    633 **
    634 ** Description      process the characteristic discovery complete event
    635 **
    636 ** Returns          status
    637 **
    638 *******************************************************************************/
    639 static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
    640 {
    641     tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
    642 
    643     /* if there are characteristic needs to be explored */
    644     if (p_srvc_cb->total_char > 0)
    645     {
    646         /* add the first characteristic into cache */
    647         bta_gattc_add_attr_to_cache (p_srvc_cb,
    648                                      p_rec->s_handle,
    649                                      &p_rec->uuid,
    650                                      p_rec->property,
    651                                      BTA_GATTC_ATTR_TYPE_CHAR);
    652 
    653         /* start discoverying characteristic descriptor , if failed, disc for next char*/
    654         bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
    655     }
    656     else /* otherwise start with next service */
    657     {
    658         p_srvc_cb->cur_srvc_idx ++;
    659 
    660         bta_gattc_explore_srvc (conn_id, p_srvc_cb);
    661     }
    662 }
    663 /*******************************************************************************
    664 **
    665 ** Function         bta_gattc_char_dscpt_disc_cmpl
    666 **
    667 ** Description      process the char descriptor discovery complete event
    668 **
    669 ** Returns          status
    670 **
    671 *******************************************************************************/
    672 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
    673 {
    674     tBTA_GATTC_ATTR_REC *p_rec = NULL;
    675 
    676     if (-- p_srvc_cb->total_char > 0)
    677     {
    678         p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
    679         /* add the next characteristic into cache */
    680         bta_gattc_add_attr_to_cache (p_srvc_cb,
    681                                      p_rec->s_handle,
    682                                      &p_rec->uuid,
    683                                      p_rec->property,
    684                                      BTA_GATTC_ATTR_TYPE_CHAR);
    685 
    686         /* start discoverying next characteristic for char descriptor */
    687         bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
    688     }
    689     else
    690     /* all characteristic has been explored, start with next service if any */
    691     {
    692 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
    693         APPL_TRACE_ERROR("all char has been explored");
    694 #endif
    695         p_srvc_cb->cur_srvc_idx ++;
    696         bta_gattc_explore_srvc (conn_id, p_srvc_cb);
    697     }
    698 
    699 }
    700 static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
    701                                       UINT16 e_handle, tBT_UUID uuid)
    702 {
    703     tBTA_GATTC_ATTR_REC *p_rec = NULL;
    704     UINT8   i;
    705     BOOLEAN exist_srvc = FALSE;
    706     UNUSED(uuid);
    707 
    708     if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle))
    709     {
    710         APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
    711         exist_srvc = TRUE;
    712     }
    713     else
    714     {
    715         for (i = 0; i < p_srvc_cb->next_avail_idx; i ++)
    716         {
    717             p_rec = p_srvc_cb->p_srvc_list + i;
    718 
    719             /* a new service should not have any overlap with other service handle range */
    720             if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle)
    721             {
    722                 exist_srvc = TRUE;
    723                 break;
    724             }
    725         }
    726     }
    727     return exist_srvc;
    728 }
    729 /*******************************************************************************
    730 **
    731 ** Function         bta_gattc_add_srvc_to_list
    732 **
    733 ** Description      Add a service into explore pending list
    734 **
    735 ** Returns          status
    736 **
    737 *******************************************************************************/
    738 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
    739                                                    UINT16 s_handle, UINT16 e_handle,
    740                                                    tBT_UUID uuid, BOOLEAN is_primary)
    741 {
    742     tBTA_GATTC_ATTR_REC *p_rec = NULL;
    743     tBTA_GATT_STATUS    status = BTA_GATT_OK;
    744 
    745     if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
    746     {
    747         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
    748 
    749         APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x",
    750                             __func__, s_handle, uuid.uu.uuid16);
    751 
    752         p_rec->s_handle     = s_handle;
    753         p_rec->e_handle     = e_handle;
    754         p_rec->is_primary   = is_primary;
    755         p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid);
    756         memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
    757 
    758         p_srvc_cb->total_srvc ++;
    759         p_srvc_cb->next_avail_idx ++;
    760     }
    761     else
    762     {   /* allocate bigger buffer ?? */
    763         status = GATT_DB_FULL;
    764 
    765         APPL_TRACE_ERROR("service not added, no resources or wrong state");
    766     }
    767     return status;
    768 }
    769 /*******************************************************************************
    770 **
    771 ** Function         bta_gattc_add_char_to_list
    772 **
    773 ** Description      Add a characteristic into explore pending list
    774 **
    775 ** Returns          status
    776 **
    777 *******************************************************************************/
    778 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
    779                                                    UINT16 decl_handle, UINT16 value_handle,
    780                                                    tBT_UUID uuid, UINT8 property)
    781 {
    782     tBTA_GATTC_ATTR_REC *p_rec = NULL;
    783     tBTA_GATT_STATUS    status = BTA_GATT_OK;
    784 
    785     if (p_srvc_cb->p_srvc_list == NULL)
    786     {
    787         APPL_TRACE_ERROR("No service available, unexpected char discovery result");
    788         status = BTA_GATT_INTERNAL_ERROR;
    789     }
    790     else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
    791     {
    792 
    793         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
    794 
    795         p_srvc_cb->total_char ++;
    796 
    797         p_rec->s_handle = value_handle;
    798         p_rec->property = property;
    799         p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
    800         memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
    801 
    802         /* update the endind handle of pervious characteristic if available */
    803         if (p_srvc_cb->total_char > 1)
    804         {
    805             p_rec -= 1;
    806             p_rec->e_handle = decl_handle - 1;
    807         }
    808         p_srvc_cb->next_avail_idx ++;
    809     }
    810     else
    811     {
    812         APPL_TRACE_ERROR("char not added, no resources");
    813         /* allocate bigger buffer ?? */
    814         status = BTA_GATT_DB_FULL;
    815     }
    816     return status;
    817 
    818 }
    819 /*******************************************************************************
    820 **
    821 ** Function         bta_gattc_sdp_callback
    822 **
    823 ** Description      Process the discovery result from sdp
    824 **
    825 ** Returns          void
    826 **
    827 *******************************************************************************/
    828 void bta_gattc_sdp_callback (UINT16 sdp_status)
    829 {
    830     tSDP_DISC_REC       *p_sdp_rec = NULL;
    831     tBT_UUID            service_uuid;
    832     tSDP_PROTOCOL_ELEM  pe;
    833     UINT16              start_handle = 0, end_handle = 0;
    834     tBTA_GATTC_SERV     *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id);
    835 
    836     if(((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL)
    837     {
    838         do
    839         {
    840             /* find a service record, report it */
    841             p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db,
    842                                             0, p_sdp_rec);
    843             if (p_sdp_rec)
    844             {
    845                 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
    846                 {
    847 
    848                     if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
    849                     {
    850                         start_handle    = (UINT16) pe.params[0];
    851                         end_handle      = (UINT16) pe.params[1];
    852 
    853 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
    854                         APPL_TRACE_EVENT("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
    855                                         service_uuid.uu.uuid16, start_handle, end_handle);
    856 #endif
    857 
    858                         if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle)&&
    859                             p_srvc_cb != NULL)
    860                         {
    861                             /* discover services result, add services into a service list */
    862                             bta_gattc_add_srvc_to_list(p_srvc_cb,
    863                                                        start_handle,
    864                                                        end_handle,
    865                                                        service_uuid,
    866                                                        TRUE);
    867                         }
    868                         else
    869                         {
    870                             APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
    871                                                 start_handle, end_handle);
    872                         }
    873                 }
    874 
    875 
    876                 }
    877             }
    878         } while (p_sdp_rec);
    879     }
    880 
    881     if ( p_srvc_cb != NULL)
    882         /* start discover primary service */
    883         bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb);
    884     else
    885     {
    886         APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
    887     }
    888 
    889     GKI_freebuf(bta_gattc_cb.p_sdp_db);
    890     bta_gattc_cb.p_sdp_db  = NULL;
    891     bta_gattc_cb.sdp_conn_id = 0;
    892 }
    893 /*******************************************************************************
    894 **
    895 ** Function         bta_gattc_sdp_service_disc
    896 **
    897 ** Description      Start DSP Service Discovert
    898 **
    899 ** Returns          void
    900 **
    901 *******************************************************************************/
    902 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
    903 {
    904     tSDP_UUID       uuid;
    905     UINT16          num_attrs = 2;
    906     UINT16          attr_list[2];
    907     tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
    908 
    909     memset (&uuid, 0, sizeof(tSDP_UUID));
    910 
    911     uuid.len = LEN_UUID_16;
    912     uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
    913 
    914      if((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_GATT_SDP_DB_SIZE)) != NULL)
    915     {
    916         attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
    917         attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
    918 
    919         SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
    920                              &uuid, num_attrs, attr_list);
    921 
    922         if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda,
    923                                               bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback))
    924         {
    925             GKI_freebuf(bta_gattc_cb.p_sdp_db);
    926             bta_gattc_cb.p_sdp_db = NULL;
    927         }
    928         else
    929         {
    930             bta_gattc_cb.sdp_conn_id = conn_id;
    931             status = BTA_GATT_OK;
    932         }
    933      }
    934      return status;
    935 }
    936 /*******************************************************************************
    937 **
    938 ** Function         bta_gattc_disc_res_cback
    939 **                  bta_gattc_disc_cmpl_cback
    940 **
    941 ** Description      callback functions to GATT client stack.
    942 **
    943 ** Returns          void
    944 **
    945 *******************************************************************************/
    946 void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
    947 {
    948     tBTA_GATTC_SERV * p_srvc_cb = NULL;
    949     BOOLEAN          pri_srvc;
    950     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    951 
    952     p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
    953 
    954     if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST)
    955     {
    956         switch (disc_type)
    957         {
    958             case GATT_DISC_SRVC_ALL:
    959                 /* discover services result, add services into a service list */
    960                 bta_gattc_add_srvc_to_list(p_srvc_cb,
    961                                            p_data->handle,
    962                                            p_data->value.group_value.e_handle,
    963                                            p_data->value.group_value.service_type,
    964                                            TRUE);
    965 
    966                 break;
    967             case GATT_DISC_SRVC_BY_UUID:
    968                 bta_gattc_add_srvc_to_list(p_srvc_cb,
    969                                            p_data->handle,
    970                                            p_data->value.group_value.e_handle,
    971                                            p_data->value.group_value.service_type,
    972                                            TRUE);
    973                 break;
    974 
    975             case GATT_DISC_INC_SRVC:
    976                 /* add included service into service list if it's secondary or it never showed up
    977                    in the primary service search */
    978                 pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
    979                                                   p_data->value.incl_service.s_handle,
    980                                                   p_data->value.incl_service.e_handle,
    981                                                   p_data->value.incl_service.service_type);
    982 
    983                 if (!pri_srvc)
    984                     bta_gattc_add_srvc_to_list(p_srvc_cb,
    985                                                p_data->value.incl_service.s_handle,
    986                                                p_data->value.incl_service.e_handle,
    987                                                p_data->value.incl_service.service_type,
    988                                                FALSE);
    989                 /* add into database */
    990                 bta_gattc_add_attr_to_cache(p_srvc_cb,
    991                                             p_data->handle,
    992                                             &p_data->value.incl_service.service_type,
    993                                             pri_srvc,
    994                                             BTA_GATTC_ATTR_TYPE_INCL_SRVC);
    995                 break;
    996 
    997             case GATT_DISC_CHAR:
    998                 /* add char value into database */
    999                 bta_gattc_add_char_to_list(p_srvc_cb,
   1000                                            p_data->handle,
   1001                                            p_data->value.dclr_value.val_handle,
   1002                                            p_data->value.dclr_value.char_uuid,
   1003                                            p_data->value.dclr_value.char_prop);
   1004                 break;
   1005 
   1006             case GATT_DISC_CHAR_DSCPT:
   1007                 bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
   1008                                             BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
   1009                 break;
   1010         }
   1011     }
   1012 }
   1013 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
   1014 {
   1015     tBTA_GATTC_SERV * p_srvc_cb;
   1016     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
   1017 
   1018     if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
   1019     {
   1020         if (p_clcb->status == GATT_SUCCESS)
   1021             p_clcb->status = status;
   1022         bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
   1023         return;
   1024     }
   1025     p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
   1026 
   1027     if (p_srvc_cb != NULL)
   1028     {
   1029         switch (disc_type)
   1030         {
   1031             case GATT_DISC_SRVC_ALL:
   1032             case GATT_DISC_SRVC_BY_UUID:
   1033 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1034                 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
   1035 #endif
   1036                 bta_gattc_explore_srvc(conn_id, p_srvc_cb);
   1037                 break;
   1038 
   1039             case GATT_DISC_INC_SRVC:
   1040                 bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
   1041 
   1042                 break;
   1043 
   1044             case GATT_DISC_CHAR:
   1045 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1046                 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
   1047 #endif
   1048                 bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
   1049                 break;
   1050 
   1051             case GATT_DISC_CHAR_DSCPT:
   1052                 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
   1053                 break;
   1054         }
   1055     }
   1056 }
   1057 /*******************************************************************************
   1058 **
   1059 ** Function         bta_gattc_id2handle
   1060 **
   1061 ** Description      map GATT ID to handle in a given cache.
   1062 **
   1063 ** Returns          the handle mapped. 0 if not found.
   1064 **
   1065 *******************************************************************************/
   1066 UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
   1067                            tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid)
   1068 {
   1069     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
   1070     tBTA_GATTC_CACHE_ATTR   *p_attr;
   1071     UINT8       j;
   1072     UINT16      handle = 0;
   1073     tBT_UUID    attr_uuid;
   1074     BOOLEAN     char_map = FALSE, done = FALSE;
   1075 
   1076     while (p_service_id && p_cache && !done)
   1077     {
   1078 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1079         APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
   1080                           p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
   1081                           p_cache->service_uuid.id.inst_id);
   1082 #endif
   1083         p_attr = p_cache->p_attr;
   1084 
   1085         if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
   1086         {
   1087             for (j = 0; p_attr; j ++)
   1088             {
   1089 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1090                 APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
   1091                                   j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
   1092                                     p_attr->inst_id, p_attr->attr_type);
   1093 #endif
   1094                 bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
   1095 
   1096                 if (bta_gattc_uuid_compare(&p_char_id->uuid, &attr_uuid, TRUE) &&
   1097                     p_char_id->inst_id == p_attr->inst_id)
   1098                 {
   1099                     if (p_descr_uuid == NULL)
   1100                     {
   1101                         handle = p_attr->attr_handle;
   1102                         done = TRUE;
   1103                         break;
   1104                     }
   1105                     else
   1106                     {
   1107 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1108                         APPL_TRACE_DEBUG("found matching characteristic for the descriptor");
   1109 #endif
   1110                         char_map = TRUE;
   1111                     }
   1112                 }
   1113                 else if (char_map == TRUE)
   1114                 {
   1115                     if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
   1116                     {
   1117 
   1118                         if (p_descr_uuid != NULL &&
   1119                             bta_gattc_uuid_compare(&p_descr_uuid->uuid, &attr_uuid, TRUE) &&
   1120                             p_descr_uuid->inst_id == p_attr->inst_id)
   1121                         {
   1122 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1123                             APPL_TRACE_DEBUG("found descriptor!!");
   1124 #endif
   1125                             handle = p_attr->attr_handle;
   1126                             done = TRUE;
   1127                             break;
   1128                         }
   1129                         else
   1130                         {
   1131 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1132                             APPL_TRACE_DEBUG("descriptor UUID not matching");
   1133 #endif
   1134                         }
   1135                     }
   1136                     else /* another char */
   1137                     {
   1138 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1139                        APPL_TRACE_DEBUG("no matching descptr found!!start of next characteristic");
   1140 #endif
   1141                         char_map = FALSE;
   1142                         done = TRUE;
   1143                         break;
   1144                     }
   1145                 }
   1146                 p_attr = p_attr->p_next;
   1147             }
   1148         }
   1149         p_cache = p_cache->p_next;
   1150     }
   1151 
   1152     return handle;
   1153 }
   1154 /*******************************************************************************
   1155 **
   1156 ** Function         bta_gattc_handle2id
   1157 **
   1158 ** Description      map a handle to GATT ID in a given cache.
   1159 **
   1160 ** Returns          FALSE if map can not be found.
   1161 **
   1162 *******************************************************************************/
   1163 
   1164 BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
   1165                             tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
   1166 {
   1167     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
   1168     tBTA_GATTC_CACHE_ATTR   *p_attr, *p_char = NULL;
   1169     UINT8       j;
   1170 
   1171     memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
   1172     memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
   1173     memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
   1174 
   1175     while (p_cache)
   1176     {
   1177 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1178         APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
   1179                           p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
   1180                           p_cache->service_uuid.id.inst_id);
   1181 #endif
   1182         /* a service found */
   1183         if (p_cache->s_handle == handle)
   1184         {
   1185             memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
   1186 
   1187             return TRUE;
   1188         }
   1189         else /* start looking for attributes within the service */
   1190         {
   1191             p_attr = p_cache->p_attr;
   1192 
   1193             for (j = 0; p_attr; j ++)
   1194             {
   1195 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1196                 APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
   1197                                   j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
   1198                                   p_attr->inst_id, p_attr->attr_type);
   1199 #endif
   1200                 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
   1201                     p_char = p_attr;
   1202 
   1203                 if (handle == p_attr->attr_handle)
   1204                 {
   1205                     memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
   1206 
   1207                     if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
   1208                     {
   1209                         bta_gattc_pack_attr_uuid(p_attr, &p_descr_type->uuid);
   1210                         p_descr_type->inst_id = p_attr->inst_id;
   1211 
   1212                         if (p_char != NULL)
   1213                         {
   1214                             bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid);
   1215                             p_char_id->inst_id = p_char->inst_id;
   1216                         }
   1217                         else
   1218                         {
   1219                             APPL_TRACE_ERROR("descptr does not belong to any chracteristic");
   1220                         }
   1221                     }
   1222                     else
   1223                     /* is a characterisitc value or included service */
   1224                     {
   1225                         bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid);
   1226                         p_char_id->inst_id =p_attr->inst_id;
   1227                     }
   1228                     return TRUE;
   1229                 }
   1230                 p_attr = p_attr->p_next;
   1231             }
   1232         }
   1233         p_cache = p_cache->p_next;
   1234     }
   1235 
   1236     return FALSE;
   1237 }
   1238 
   1239 /*******************************************************************************
   1240 **
   1241 ** Function         bta_gattc_search_service
   1242 **
   1243 ** Description      search local cache for matching service record.
   1244 **
   1245 ** Returns          FALSE if map can not be found.
   1246 **
   1247 *******************************************************************************/
   1248 void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
   1249 {
   1250     tBTA_GATTC_SERV     *p_srcb = p_clcb->p_srcb;
   1251     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
   1252     tBTA_GATTC          cb_data;
   1253 
   1254     while (p_cache)
   1255     {
   1256         if (bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE))
   1257         {
   1258 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1259             APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
   1260                               p_cache->service_uuid.id.uuid.uu.uuid16,
   1261                               p_cache->service_uuid.id.inst_id,
   1262                               p_cache->s_handle);
   1263 #endif
   1264             if (p_clcb->p_rcb->p_cback)
   1265             {
   1266                 memset(&cb_data, 0, sizeof(tBTA_GATTC));
   1267 
   1268                 cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
   1269                 memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid,
   1270                         sizeof(tBTA_GATT_SRVC_ID));
   1271 
   1272                 (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
   1273             }
   1274         }
   1275         p_cache = p_cache->p_next;
   1276     }
   1277 }
   1278 /*******************************************************************************
   1279 **
   1280 ** Function         bta_gattc_find_record
   1281 **
   1282 ** Description      search local cache for matching attribute record.
   1283 **
   1284 ** Parameter        p_result: output parameter to store the characteristic/
   1285 **                            included service GATT ID.
   1286 **
   1287 ** Returns          GATT_ERROR is no recording found. BTA_GATT_OK if record found.
   1288 **
   1289 *******************************************************************************/
   1290 static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
   1291                                               tBTA_GATTC_ATTR_TYPE attr_type,
   1292                                               tBTA_GATT_SRVC_ID *p_service_id,
   1293                                               tBTA_GATT_ID  *p_start_rec,
   1294                                               tBT_UUID      * p_uuid_cond,
   1295                                               tBTA_GATT_ID  *p_result,
   1296                                               void *p_param)
   1297 {
   1298     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
   1299     tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
   1300     UINT8               i, j;
   1301     tBTA_GATTC_CACHE_ATTR   *p_attr;
   1302     BOOLEAN             char_found = FALSE, descr_found = FALSE;
   1303     tBTA_GATT_ID        *p_descr_id = (tBTA_GATT_ID *)p_param;;
   1304 
   1305     for (i = 0; p_cache && status != BTA_GATT_OK; i ++)
   1306     {
   1307         if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
   1308         {
   1309 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1310             APPL_TRACE_DEBUG("found matching service [0x%04x], inst[%d]",
   1311                               p_cache->service_uuid.id.uuid.uu.uuid16,
   1312                               p_cache->service_uuid.id.inst_id);
   1313 #endif
   1314             p_attr = p_cache->p_attr;
   1315 
   1316             for (j = 0; p_attr; j ++)
   1317             {
   1318 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1319                 APPL_TRACE_DEBUG("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
   1320                                   j + 1, p_attr->attr_handle,
   1321                                   p_attr->p_uuid->uuid16,
   1322                                   p_attr->inst_id,
   1323                                   p_attr->attr_type);
   1324 #endif
   1325                 bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
   1326 
   1327                 if (p_start_rec != NULL && char_found == FALSE)
   1328                 {
   1329                     /* find the starting record first */
   1330                     if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
   1331                         p_start_rec->inst_id  == p_attr->inst_id &&
   1332                         (attr_type == p_attr->attr_type ||
   1333                         /* find descriptor would look for characteristic first */
   1334                          (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
   1335                           p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
   1336                     {
   1337                         char_found = TRUE;
   1338                     }
   1339                 }
   1340                 else
   1341                 {
   1342                     /* if looking for descriptor, here is the where the descrptor to be found */
   1343                     if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
   1344                     {
   1345                         /* next characeteristic already, return error */
   1346                         if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
   1347                         {
   1348                             break;
   1349                         }
   1350                         else
   1351                         {
   1352                             /* find starting descriptor */
   1353                             if (p_descr_id != NULL && !descr_found)
   1354                             {
   1355                                 if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
   1356                                     && p_descr_id->inst_id == p_attr->inst_id)
   1357                                 {
   1358                                     descr_found = TRUE;
   1359                                 }
   1360                             }
   1361                             else
   1362                             {
   1363                                 /* with matching descriptor */
   1364                                 if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE))
   1365                                 {
   1366                                     p_result->inst_id = p_attr->inst_id;
   1367                                     status = BTA_GATT_OK;
   1368                                     break;
   1369                                 }
   1370                             }
   1371                         }
   1372                     }
   1373                     else
   1374                     {
   1375                         if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) &&
   1376                             attr_type == p_attr->attr_type)
   1377                         {
   1378 
   1379 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1380                             APPL_TRACE_DEBUG("found char handle mapping characteristic");
   1381 #endif
   1382                             p_result->inst_id = p_attr->inst_id;
   1383 
   1384                             if (p_param != NULL)
   1385                             {
   1386                                 if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
   1387                                     attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC)
   1388                                 {
   1389                                     *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
   1390                                 }
   1391                             }
   1392 
   1393                             status = BTA_GATT_OK;
   1394                             break;
   1395                         }
   1396                     }
   1397                 }
   1398                 p_attr = p_attr->p_next;
   1399             }
   1400 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
   1401             if (status)
   1402             {
   1403                 APPL_TRACE_ERROR("In the given service, can not find matching record");
   1404             }
   1405 #endif
   1406             break;
   1407         }
   1408 
   1409         p_cache = p_cache->p_next;
   1410     }
   1411     return status;
   1412 
   1413 }
   1414 
   1415 /*******************************************************************************
   1416 **
   1417 ** Function         bta_gattc_query_cache
   1418 **
   1419 ** Description      search local cache for matching attribute record.
   1420 **
   1421 ** Parameters       conn_id: connection ID which identify the server.
   1422 **                  p_srvc_id: the service ID of which the characteristic is belonged to.
   1423 **                  *p_start_rec: start the search from the next record
   1424 **                                  after the one identified by *p_start_rec.
   1425 **                  p_uuid_cond: UUID, if NULL find the first available
   1426 **                               characteristic/included service.
   1427 **                  p_output:   output parameter which will store the GATT ID
   1428 **                              of the characteristic /included service found.
   1429 **
   1430 ** Returns          BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
   1431 **
   1432 *******************************************************************************/
   1433 tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
   1434                                        tBTA_GATTC_ATTR_TYPE query_type,
   1435                                        tBTA_GATT_SRVC_ID *p_srvc_id,
   1436                                        tBTA_GATT_ID *p_start_rec,
   1437                                        tBT_UUID *p_uuid_cond,
   1438                                        tBTA_GATT_ID *p_output,
   1439                                        void *p_param)
   1440 {
   1441     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
   1442     tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
   1443 
   1444     if (p_clcb != NULL )
   1445     {
   1446         if (p_clcb->state == BTA_GATTC_CONN_ST)
   1447         {
   1448             if (p_clcb->p_srcb &&
   1449                 !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
   1450                 p_clcb->p_srcb->p_srvc_cache)
   1451             {
   1452                 status = bta_gattc_find_record(p_clcb->p_srcb,
   1453                                                query_type,
   1454                                                p_srvc_id,
   1455                                                p_start_rec,
   1456                                                p_uuid_cond,
   1457                                                p_output,
   1458                                                p_param);
   1459             }
   1460             else
   1461             {
   1462                 status = BTA_GATT_ERROR;
   1463                 APPL_TRACE_ERROR("No server cache available");
   1464             }
   1465         }
   1466         else
   1467         {
   1468             APPL_TRACE_ERROR("server cache not available, CLCB state = %d", p_clcb->state);
   1469 
   1470             status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
   1471         }
   1472     }
   1473     else
   1474     {
   1475         APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
   1476     }
   1477 
   1478     return status;
   1479 }
   1480 
   1481 /*******************************************************************************
   1482 **
   1483 ** Function         bta_gattc_rebuild_cache
   1484 **
   1485 ** Description      rebuild server cache from NV cache.
   1486 **
   1487 ** Parameters
   1488 **
   1489 ** Returns          None.
   1490 **
   1491 *******************************************************************************/
   1492 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
   1493                              tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index)
   1494 {
   1495     /* first attribute loading, initialize buffer */
   1496     APPL_TRACE_ERROR("bta_gattc_rebuild_cache");
   1497     if (attr_index == 0)
   1498     {
   1499         while (!GKI_queue_is_empty(&p_srvc_cb->cache_buffer))
   1500             GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
   1501 
   1502         if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
   1503         {
   1504             APPL_TRACE_ERROR("allocate cache buffer failed, no resources");
   1505         }
   1506         else
   1507         {
   1508             p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
   1509         }
   1510     }
   1511 
   1512     while (num_attr > 0 && p_attr != NULL)
   1513     {
   1514         switch (p_attr->attr_type)
   1515         {
   1516             case BTA_GATTC_ATTR_TYPE_SRVC:
   1517                 bta_gattc_add_srvc_to_cache(p_srvc_cb,
   1518                                             p_attr->s_handle,
   1519                                             p_attr->e_handle,
   1520                                             &p_attr->uuid,
   1521                                             p_attr->is_primary,
   1522                                             p_attr->id);
   1523                 break;
   1524 
   1525             case BTA_GATTC_ATTR_TYPE_CHAR:
   1526             case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
   1527             case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
   1528                 bta_gattc_add_attr_to_cache(p_srvc_cb,
   1529                                             p_attr->s_handle,
   1530                                             &p_attr->uuid,
   1531                                             p_attr->prop,
   1532                                             p_attr->attr_type);
   1533                 break;
   1534         }
   1535         p_attr ++;
   1536         num_attr --;
   1537     }
   1538 }
   1539 
   1540 /*******************************************************************************
   1541 **
   1542 ** Function         bta_gattc_fill_nv_attr
   1543 **
   1544 ** Description      fill a NV attribute entry value
   1545 **
   1546 ** Returns          None.
   1547 **
   1548 *******************************************************************************/
   1549 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
   1550                             UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop,
   1551                             BOOLEAN is_primary)
   1552 {
   1553     p_attr->s_handle    = s_handle;
   1554     p_attr->e_handle    = e_handle;
   1555     p_attr->attr_type   = type;
   1556     p_attr->is_primary  = is_primary;
   1557     p_attr->id          = id;
   1558     p_attr->prop        = prop;
   1559 
   1560     memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
   1561 }
   1562 /*******************************************************************************
   1563 **
   1564 ** Function         bta_gattc_cache_save
   1565 **
   1566 ** Description      save the server cache into NV
   1567 **
   1568 ** Returns          None.
   1569 **
   1570 *******************************************************************************/
   1571 BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
   1572 {
   1573     tBTA_GATTC_CACHE        *p_cur_srvc = p_srvc_cb->p_srvc_cache;
   1574     UINT8                   i = 0;
   1575     UINT16                  offset = 0;
   1576     tBTA_GATTC_NV_ATTR      nv_attr[BTA_GATTC_NV_LOAD_MAX];
   1577     tBTA_GATTC_CACHE_ATTR   *p_attr;
   1578     tBT_UUID                uuid;
   1579 
   1580     while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX)
   1581     {
   1582         if (offset ++ >= p_srvc_cb->attr_index)
   1583         {
   1584             bta_gattc_fill_nv_attr(&nv_attr[i++],
   1585                                    BTA_GATTC_ATTR_TYPE_SRVC,
   1586                                    p_cur_srvc->s_handle,
   1587                                    p_cur_srvc->e_handle,
   1588                                    p_cur_srvc->service_uuid.id.inst_id,
   1589                                    p_cur_srvc->service_uuid.id.uuid,
   1590                                    0,
   1591                                    p_cur_srvc->service_uuid.is_primary);
   1592         }
   1593 
   1594         p_attr = p_cur_srvc->p_attr;
   1595 
   1596         for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next)
   1597         {
   1598             if (offset >= p_srvc_cb->attr_index)
   1599             {
   1600                 if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16)
   1601                 {
   1602                     uuid.uu.uuid16 = p_attr->p_uuid->uuid16;
   1603                 }
   1604                 else
   1605                 {
   1606                     memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128);
   1607                 }
   1608 
   1609                 bta_gattc_fill_nv_attr(&nv_attr[i++],
   1610                                        p_attr->attr_type,
   1611                                        p_attr->attr_handle,
   1612                                        0,
   1613                                        p_attr->inst_id,
   1614                                        uuid,
   1615                                        p_attr->property,
   1616                                        FALSE);
   1617             }
   1618         }
   1619         p_cur_srvc = p_cur_srvc->p_next;
   1620     }
   1621 
   1622     if (i > 0)
   1623     {
   1624         bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i,
   1625                                 nv_attr, p_srvc_cb->attr_index, conn_id);
   1626 
   1627         p_srvc_cb->attr_index += i;
   1628 
   1629         return TRUE;
   1630     }
   1631     else
   1632     {
   1633         return FALSE;
   1634     }
   1635 }
   1636 #endif /* BTA_GATT_INCLUDED */
   1637 
   1638