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