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