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