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