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