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 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 = 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 = 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 = 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
228static 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*******************************************************************************/
274static 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*******************************************************************************/
341void 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*******************************************************************************/
371tBTA_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*******************************************************************************/
396tBTA_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*******************************************************************************/
433tBTA_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*******************************************************************************/
446tBTA_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*******************************************************************************/
461void 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*******************************************************************************/
478static 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*******************************************************************************/
531static 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*******************************************************************************/
547static 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*******************************************************************************/
580static 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}
608static 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*******************************************************************************/
646static 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*******************************************************************************/
685static 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*******************************************************************************/
737void 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*******************************************************************************/
813static 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*******************************************************************************/
859void 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}
928void 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*******************************************************************************/
982void 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
1015list_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
1022const 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
1033tBTA_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
1048const 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
1054const 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
1060tBTA_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
1076tBTA_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
1086tBTA_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
1107tBTA_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*******************************************************************************/
1126void 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*******************************************************************************/
1144static 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*******************************************************************************/
1197static 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*******************************************************************************/
1311void 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*******************************************************************************/
1346void 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*******************************************************************************/
1400void 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*******************************************************************************/
1424void 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*******************************************************************************/
1518bool 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
1562done:
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*******************************************************************************/
1581static 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*******************************************************************************/
1627void 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