1 /******************************************************************************
2  *
3  *  Copyright (C) 2003-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains the GATT client discovery procedures and cache
22  *  related functions.
23  *
24  ******************************************************************************/
25 
26 #include "common/bt_target.h"
27 
28 #if defined(GATTC_INCLUDED) && (GATTC_INCLUDED == TRUE)
29 //#if( defined GATTC_CACHE_NVS ) && (GATTC_CACHE_NVS == TRUE)
30 
31 #include <string.h>
32 #include "bta/utl.h"
33 #include "bta/bta_sys.h"
34 #include "stack/sdp_api.h"
35 #include "stack/sdpdefs.h"
36 #include "bta_gattc_int.h"
37 #include "stack/btm_api.h"
38 #include "stack/btm_ble_api.h"
39 #include "osi/allocator.h"
40 #include "stack/l2c_api.h"
41 #include "btm_int.h"
42 #include "errno.h"
43 
44 // #include "osi/include/log.h"
45 
46 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
47 extern void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
48 static size_t bta_gattc_get_db_size_with_type(list_t *services,
49                                               bt_gatt_db_attribute_type_t type,
50                                               tBT_UUID *char_uuid,
51                                               UINT16 start_handle, UINT16 end_handle);
52 static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr,
53                            tBTA_GATTC_NV_ATTR *attr);
54 tBTA_GATTC_SERVICE*  bta_gattc_find_matching_service(const list_t *services, UINT16 handle);
55 tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
56 tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
57 void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr,
58                                bt_gatt_db_attribute_type_t type,
59                                UINT16 att_handle,
60                                UINT16 s_handle, UINT16 e_handle,
61                                UINT16 id, tBT_UUID uuid, UINT8 prop);
62 
63 
64 #if (SDP_INCLUDED == TRUE)
65 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
66 #define BTA_GATT_SDP_DB_SIZE 4096
67 #endif  ///SDP_INCLUDED == TRUE
68 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
69 #define GATT_CACHE_VERSION 2
70 
bta_gattc_generate_cache_file_name(char * buffer,BD_ADDR bda)71 static void bta_gattc_generate_cache_file_name(char *buffer, BD_ADDR bda)
72 {
73     sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX,
74             bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
75 }
76 
77 /*****************************************************************************
78 **  Constants and data types
79 *****************************************************************************/
80 #if (SDP_INCLUDED == TRUE)
81 typedef struct
82 {
83     tSDP_DISCOVERY_DB   *p_sdp_db;
84     UINT16              sdp_conn_id;
85 } tBTA_GATTC_CB_DATA;
86 #endif  ///SDP_INCLUDED == TRUE
87 
88 
89 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
90 static char *bta_gattc_attr_type[] = {
91     "I", /* Included Service */
92     "C", /* Characteristic */
93     "D" /* Characteristic Descriptor */
94 };
95 /* utility functions */
96 
display_cache_attribute(void * data,void * context)97 bool display_cache_attribute(void *data, void *context)
98 {
99     //tBTA_GATTC_CACHE_ATTR *p_attr = data;
100     //APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]",
101     //                  p_attr->handle, p_attr->uuid.uu.uuid16,
102     //                  bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
103     return true;
104 }
105 
display_cache_service(void * data,void * context)106 bool display_cache_service(void *data, void *context)
107 {
108     tBTA_GATTC_SERVICE    *p_cur_srvc = data;
109     APPL_TRACE_API("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]",
110               p_cur_srvc->s_handle, p_cur_srvc->e_handle,
111               ((p_cur_srvc->uuid.len == 2) ? "uuid16" : "uuid128"),
112               p_cur_srvc->uuid.uu.uuid16,
113               p_cur_srvc->handle);
114 
115     if (p_cur_srvc->characteristics != NULL) {
116         list_foreach(p_cur_srvc->characteristics, display_cache_attribute, NULL);
117     }
118 
119     return true;
120 }
121 
122 /*******************************************************************************
123 **
124 ** Function         bta_gattc_display_cache_server
125 **
126 ** Description      debug function to display the server cache.
127 **
128 ** Returns          none.
129 **
130 *******************************************************************************/
bta_gattc_display_cache_server(list_t * p_cache)131 static void bta_gattc_display_cache_server(list_t *p_cache)
132 {
133     APPL_TRACE_ERROR("<================Start Server Cache =============>");
134     list_foreach(p_cache, display_cache_service, NULL);
135     APPL_TRACE_ERROR("<================End Server Cache =============>");
136     APPL_TRACE_ERROR(" ");
137 }
138 
139 /*******************************************************************************
140 **
141 ** Function         bta_gattc_display_explore_record
142 **
143 ** Description      debug function to display the exploration list
144 **
145 ** Returns          none.
146 **
147 *******************************************************************************/
bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC * p_rec,UINT8 num_rec)148 static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
149 {
150     UINT8 i;
151     tBTA_GATTC_ATTR_REC *pp = p_rec;
152 
153     APPL_TRACE_ERROR("<================Start Explore Queue =============>");
154     for (i = 0; i < num_rec; i ++, pp ++) {
155         APPL_TRACE_ERROR("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
156                          i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
157     }
158     APPL_TRACE_ERROR("<================ End Explore Queue =============>");
159     APPL_TRACE_ERROR(" ");
160 
161 }
162 #endif  /* BTA_GATT_DEBUG == TRUE */
163 
164 
165 /*******************************************************************************
166 **
167 ** Function         bta_gattc_init_cache
168 **
169 ** Description      Initialize the database cache and discovery related resources.
170 **
171 ** Returns          status
172 **
173 *******************************************************************************/
bta_gattc_init_cache(tBTA_GATTC_SERV * p_srvc_cb)174 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
175 {
176     if (p_srvc_cb->p_srvc_cache != NULL) {
177         list_free(p_srvc_cb->p_srvc_cache);
178         p_srvc_cb->p_srvc_cache = NULL;
179     }
180 
181     osi_free(p_srvc_cb->p_srvc_list);
182 
183     if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC *)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE)) == NULL) {
184         APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
185         return BTA_GATT_NO_RESOURCES;
186     } else {
187         p_srvc_cb->total_srvc = 0;
188         p_srvc_cb->cur_srvc_idx = 0;
189         p_srvc_cb->cur_char_idx = 0;
190         p_srvc_cb->next_avail_idx = 0;
191         p_srvc_cb->total_attr = 0;
192     }
193 
194     return BTA_GATT_OK;
195 }
196 
characteristic_free(void * ptr)197 static void characteristic_free(void *ptr)
198 {
199   tBTA_GATTC_CHARACTERISTIC *p_char = ptr;
200   list_free(p_char->descriptors);
201   osi_free(p_char);
202 }
203 
service_free(void * ptr)204 static void service_free(void *ptr)
205 {
206   tBTA_GATTC_SERVICE *srvc = ptr;
207   list_free(srvc->characteristics);
208   list_free(srvc->included_svc);
209   osi_free(srvc);
210 }
211 
bta_gattc_free(void * ptr)212 static void bta_gattc_free(void *ptr)
213 {
214     osi_free(ptr);
215 }
216 
bta_gattc_insert_sec_service_to_cache(list_t * services,tBTA_GATTC_SERVICE * p_new_srvc)217 void bta_gattc_insert_sec_service_to_cache(list_t *services, tBTA_GATTC_SERVICE *p_new_srvc)
218 {
219     // services/p_new_srvc is NULL
220     if (!services || !p_new_srvc) {
221         APPL_TRACE_ERROR("%s services/p_new_srvc is NULL", __func__);
222         return;
223     }
224     //list is empty
225     if (list_is_empty(services)) {
226         list_append(services, p_new_srvc);
227     } else {
228         //check the first service
229         list_node_t *sn = list_begin(services);
230         tBTA_GATTC_SERVICE *service = list_node(sn);
231         if(service && p_new_srvc->e_handle < service->s_handle) {
232             list_prepend(services, p_new_srvc);
233         } else {
234             for (list_node_t *sn = list_begin(services); sn != list_end(services); sn = list_next(sn)) {
235                 list_node_t *next_sn = list_next(sn);
236                 if(next_sn == list_end(services)) {
237                     list_append(services, p_new_srvc);
238                     return;
239                 }
240                 tBTA_GATTC_SERVICE *service = list_node(sn);
241                 tBTA_GATTC_SERVICE *next_service = list_node(next_sn);
242                 if (p_new_srvc->s_handle > service->e_handle && p_new_srvc->e_handle < next_service->s_handle) {
243                     list_insert_after(services, sn, p_new_srvc);
244                     return;
245                 }
246             }
247         }
248     }
249 }
250 
251 /*******************************************************************************
252 **
253 ** Function         bta_gattc_add_srvc_to_cache
254 **
255 ** Description      Add a service into database cache.
256 **
257 ** Returns          status
258 **
259 *******************************************************************************/
bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV * p_srvc_cb,UINT16 s_handle,UINT16 e_handle,tBT_UUID * p_uuid,BOOLEAN is_primary)260 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
261                                                     UINT16 s_handle, UINT16 e_handle,
262                                                     tBT_UUID *p_uuid,
263                                                     BOOLEAN is_primary)
264 {
265 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
266     APPL_TRACE_DEBUG("Add a service into Service");
267 #endif
268 
269     tBTA_GATTC_SERVICE *p_new_srvc = osi_malloc(sizeof(tBTA_GATTC_SERVICE));
270     if (!p_new_srvc) {
271         APPL_TRACE_WARNING("%s(), no resource.", __func__);
272         return BTA_GATT_NO_RESOURCES;
273     }
274 
275     /* update service information */
276     p_new_srvc->s_handle = s_handle;
277     p_new_srvc->e_handle = e_handle;
278     p_new_srvc->is_primary = is_primary;
279     memcpy(&p_new_srvc->uuid, p_uuid, sizeof(tBT_UUID));
280     p_new_srvc->handle = s_handle;
281     p_new_srvc->characteristics = list_new(characteristic_free);
282     p_new_srvc->included_svc = list_new(bta_gattc_free);
283 
284     if (p_srvc_cb->p_srvc_cache == NULL) {
285         p_srvc_cb->p_srvc_cache = list_new(service_free);
286     }
287 
288     if(!p_srvc_cb->p_srvc_cache) {
289         APPL_TRACE_WARNING("%s(), no resource.", __func__);
290         osi_free(p_new_srvc);
291         return BTA_GATT_NO_RESOURCES;
292     }
293 
294     if(is_primary) {
295         list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
296     } else {
297         //add secondary service into list
298         bta_gattc_insert_sec_service_to_cache(p_srvc_cb->p_srvc_cache, p_new_srvc);
299     }
300     return BTA_GATT_OK;
301 }
302 
bta_gattc_add_char_to_cache(tBTA_GATTC_SERV * p_srvc_cb,UINT16 attr_handle,UINT16 value_handle,tBT_UUID * p_uuid,UINT8 property)303 static tBTA_GATT_STATUS bta_gattc_add_char_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
304                                                     UINT16 attr_handle,
305                                                     UINT16 value_handle,
306                                                     tBT_UUID *p_uuid,
307                                                     UINT8 property)
308 {
309 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
310     APPL_TRACE_DEBUG("%s: Add a characteristic into Service", __func__);
311     APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x",
312                       value_handle, p_uuid->uu.uuid16, property);
313 #endif
314 
315     tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, attr_handle);
316     if (!service) {
317         APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!");
318         return GATT_WRONG_STATE;
319     }
320 
321     /* TODO(jpawlowski): We should use attribute handle, not value handle to refer to characteristic.
322        This is just a temporary workaround.
323     */
324     if (service->e_handle < value_handle) {
325         service->e_handle = value_handle;
326     }
327 
328     tBTA_GATTC_CHARACTERISTIC *characteristic = osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC));
329     if (!characteristic) {
330         APPL_TRACE_WARNING("%s(), no resource.", __func__);
331         return BTA_GATT_NO_RESOURCES;
332     }
333     characteristic->handle = value_handle;
334     characteristic->properties = property;
335     characteristic->descriptors = list_new(bta_gattc_free);
336     memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID));
337 
338     characteristic->service = service;
339     list_append(service->characteristics, characteristic);
340 
341     return BTA_GATT_OK;
342 }
343 /*******************************************************************************
344 **
345 ** Function         bta_gattc_add_attr_to_cache
346 **
347 ** Description      Add an attribute into database cache buffer.
348 **
349 ** Returns          status
350 **
351 *******************************************************************************/
bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV * p_srvc_cb,UINT16 handle,tBT_UUID * p_uuid,UINT8 property,UINT16 incl_srvc_s_handle,UINT16 incl_srvc_e_handle,tBTA_GATTC_ATTR_TYPE type)352 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
353                                                     UINT16 handle,
354                                                     tBT_UUID *p_uuid,
355                                                     UINT8 property,
356                                                     UINT16 incl_srvc_s_handle,
357                                                     UINT16 incl_srvc_e_handle,
358                                                     tBTA_GATTC_ATTR_TYPE type)
359 {
360 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
361     APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__, bta_gattc_attr_type[type]);
362     APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d",
363                       handle, p_uuid->uu.uuid16, property, type);
364 #endif
365 
366     tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, handle);
367     if (!service) {
368         APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!");
369         return GATT_WRONG_STATE;
370     }
371 
372     if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) {
373         tBTA_GATTC_INCLUDED_SVC *isvc =
374             osi_malloc(sizeof(tBTA_GATTC_INCLUDED_SVC));
375         if (!isvc) {
376             APPL_TRACE_WARNING("%s(), no resource.", __func__);
377             return BTA_GATT_NO_RESOURCES;
378         }
379         isvc->handle = handle;
380         memcpy(&isvc->uuid, p_uuid, sizeof(tBT_UUID));
381         isvc->incl_srvc_s_handle = incl_srvc_s_handle;
382         isvc->incl_srvc_e_handle = incl_srvc_e_handle;
383         isvc->owning_service = service;
384         isvc->included_service = bta_gattc_find_matching_service(
385                                     p_srvc_cb->p_srvc_cache, incl_srvc_s_handle);
386         if (!isvc->included_service) {
387             // if can't find included service, wait to update later
388             p_srvc_cb->update_incl_srvc = true;
389         }
390 
391         list_append(service->included_svc, isvc);
392     } else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
393         tBTA_GATTC_DESCRIPTOR *descriptor =
394             osi_malloc(sizeof(tBTA_GATTC_DESCRIPTOR));
395         if (!descriptor) {
396             APPL_TRACE_WARNING("%s(), no resource.", __func__);
397             return BTA_GATT_NO_RESOURCES;
398         }
399         descriptor->handle = handle;
400         memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID));
401 
402         if (service->characteristics == NULL ||
403             list_is_empty(service->characteristics)) {
404             APPL_TRACE_ERROR("%s: Illegal action to add descriptor before adding a characteristic!",
405                              __func__);
406             osi_free(descriptor);
407             return GATT_WRONG_STATE;
408         }
409 
410         tBTA_GATTC_CHARACTERISTIC *char_node = list_back(service->characteristics);
411 
412         descriptor->characteristic = char_node;
413         list_append(char_node->descriptors, descriptor);
414     }
415     return BTA_GATT_OK;
416 }
417 
418 /*******************************************************************************
419 **
420 ** Function         bta_gattc_get_disc_range
421 **
422 ** Description      get discovery stating and ending handle range.
423 **
424 ** Returns          None.
425 **
426 *******************************************************************************/
bta_gattc_get_disc_range(tBTA_GATTC_SERV * p_srvc_cb,UINT16 * p_s_hdl,UINT16 * p_e_hdl,BOOLEAN is_srvc)427 void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
428 {
429     tBTA_GATTC_ATTR_REC *p_rec = NULL;
430 
431     if (is_srvc) {
432         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
433         *p_s_hdl = p_rec->s_handle;
434     } else {
435         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
436         *p_s_hdl = p_rec->s_handle + 1;
437     }
438 
439     *p_e_hdl = p_rec->e_handle;
440 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
441     APPL_TRACE_DEBUG("discover range [%d ~ %d]", p_rec->s_handle, p_rec->e_handle);
442 #endif
443     return;
444 }
445 /*******************************************************************************
446 **
447 ** Function         bta_gattc_discover_pri_service
448 **
449 ** Description      Start primary service discovery
450 **
451 ** Returns          status of the operation.
452 **
453 *******************************************************************************/
bta_gattc_discover_pri_service(UINT16 conn_id,tBTA_GATTC_SERV * p_server_cb,UINT8 disc_type)454 tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
455         UINT8 disc_type)
456 {
457     tBTA_GATTC_CLCB     *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
458     tBTA_GATT_STATUS    status =  BTA_GATT_ERROR;
459 
460     if (p_clcb) {
461         if (p_clcb->transport == BTA_TRANSPORT_LE) {
462             status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
463         } else {
464  #if (SDP_INCLUDED == TRUE)
465             status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
466  #endif ///SDP_INCLUDED == TRUE
467         }
468     }
469 
470     return status;
471 }
472 /*******************************************************************************
473 **
474 ** Function         bta_gattc_discover_procedure
475 **
476 ** Description      Start a particular type of discovery procedure on server.
477 **
478 ** Returns          status of the operation.
479 **
480 *******************************************************************************/
bta_gattc_discover_procedure(UINT16 conn_id,tBTA_GATTC_SERV * p_server_cb,UINT8 disc_type)481 tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
482                                               UINT8 disc_type)
483 {
484     tGATT_DISC_PARAM param;
485     BOOLEAN is_service = TRUE;
486 
487     memset(&param, 0, sizeof(tGATT_DISC_PARAM));
488 
489     if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID) {
490         param.s_handle = 1;
491         param.e_handle = 0xFFFF;
492     } else {
493         if (disc_type == GATT_DISC_CHAR_DSCPT) {
494             is_service = FALSE;
495         }
496 
497         bta_gattc_get_disc_range(p_server_cb, &param.s_handle, &param.e_handle, is_service);
498 
499         if (param.s_handle > param.e_handle) {
500             return GATT_ERROR;
501         }
502     }
503     return GATTC_Discover (conn_id, disc_type, &param);
504 
505 }
506 /*******************************************************************************
507 **
508 ** Function         bta_gattc_start_disc_include_srvc
509 **
510 ** Description      Start discovery for included service
511 **
512 ** Returns          status of the operation.
513 **
514 *******************************************************************************/
bta_gattc_start_disc_include_srvc(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)515 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
516 {
517     return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
518 }
519 /*******************************************************************************
520 **
521 ** Function         bta_gattc_start_disc_char
522 **
523 ** Description      Start discovery for characteristic
524 **
525 ** Returns          status of the operation.
526 **
527 *******************************************************************************/
bta_gattc_start_disc_char(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)528 tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
529 {
530     p_srvc_cb->total_char = 0;
531 
532     return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
533 }
534 /*******************************************************************************
535 **
536 ** Function         bta_gattc_start_disc_char_dscp
537 **
538 ** Description      Start discovery for characteristic descriptor
539 **
540 ** Returns          none.
541 **
542 *******************************************************************************/
bta_gattc_start_disc_char_dscp(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)543 void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
544 {
545     APPL_TRACE_DEBUG("starting discover characteristics descriptor");
546 
547     if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0) {
548         bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
549     }
550 }
551 
bta_gattc_update_include_service(const list_t * services)552 void bta_gattc_update_include_service(const list_t *services) {
553     if (!services || list_is_empty(services)) {
554         return;
555     }
556     for (list_node_t *sn = list_begin(services); sn != list_end(services); sn = list_next(sn)) {
557         tBTA_GATTC_SERVICE *service = list_node(sn);
558         if(!service || !service->included_svc || list_is_empty(service->included_svc)) break;
559         for (list_node_t *sn = list_begin(service->included_svc); sn != list_end(service->included_svc); sn = list_next(sn)) {
560             tBTA_GATTC_INCLUDED_SVC *include_service = list_node(sn);
561             if(include_service && !include_service->included_service) {
562                 //update
563                 include_service->included_service = bta_gattc_find_matching_service(services, include_service->incl_srvc_s_handle);
564                 if(!include_service->included_service) {
565                     //not match, free it
566                     list_remove(service->included_svc, include_service);
567                     osi_free(include_service);
568                 }
569             }
570         }
571 
572     }
573 }
574 
575 /*******************************************************************************
576 **
577 ** Function         bta_gattc_explore_srvc
578 **
579 ** Description      process the service discovery complete event
580 **
581 ** Returns          status
582 **
583 *******************************************************************************/
bta_gattc_explore_srvc(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)584 static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
585 {
586     tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
587     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
588 
589     APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
590 
591     p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
592 
593     if (p_clcb == NULL) {
594         APPL_TRACE_ERROR("unknown connection ID");
595         return;
596     }
597     /* start expore a service if there is service not been explored */
598     if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc) {
599         /* add the first service into cache */
600         if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
601                                          p_rec->s_handle,
602                                          p_rec->e_handle,
603                                          &p_rec->uuid,
604                                          p_rec->is_primary) == 0) {
605             /* start discovering included services */
606             bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
607             return;
608         }
609     }
610     // if update_incl_srvc is true, update include service
611     if(p_srvc_cb->update_incl_srvc) {
612         bta_gattc_update_include_service(p_srvc_cb->p_srvc_cache);
613         p_srvc_cb->update_incl_srvc = false;
614     }
615     /* no service found at all, the end of server discovery*/
616     APPL_TRACE_DEBUG("%s no more services found", __func__);
617 
618 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
619     bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
620 #endif
621 
622     //server discover end, update connection parameters
623 #if BLE_INCLUDED == TRUE
624     #if (BT_MULTI_CONNECTION_ENBALE == FALSE)
625     if (p_clcb->transport == BTA_TRANSPORT_LE) {
626         L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE);
627     }
628     #endif
629     //discover service complete, trigger callback
630     tBTA_GATTC cb_data;
631     cb_data.dis_cmpl.status  = p_clcb->status;
632     cb_data.dis_cmpl.conn_id = conn_id;
633     ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_DIS_SRVC_CMPL_EVT,  &cb_data);
634 #endif
635 #if(GATTC_CACHE_NVS == TRUE)
636     /* save cache to NV */
637     p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
638     bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
639 #endif
640     bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
641 }
642 /*******************************************************************************
643 **
644 ** Function         bta_gattc_incl_srvc_disc_cmpl
645 **
646 ** Description      process the relationship discovery complete event
647 **
648 ** Returns          status
649 **
650 *******************************************************************************/
bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)651 static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
652 {
653     p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
654 
655     /* start discoverying characteristic */
656     bta_gattc_start_disc_char(conn_id, p_srvc_cb);
657 }
658 /*******************************************************************************
659 **
660 ** Function         bta_gattc_char_disc_cmpl
661 **
662 ** Description      process the characteristic discovery complete event
663 **
664 ** Returns          status
665 **
666 *******************************************************************************/
bta_gattc_char_disc_cmpl(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)667 static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
668 {
669     tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
670 
671     /* if there are characteristic needs to be explored */
672     if (p_srvc_cb->total_char > 0) {
673         /* add the first characteristic into cache */
674         bta_gattc_add_char_to_cache (p_srvc_cb,
675                                      p_rec->char_decl_handle,
676                                      p_rec->s_handle,
677                                      &p_rec->uuid,
678                                      p_rec->property);
679 
680         /* start discoverying characteristic descriptor , if failed, disc for next char */
681         bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
682     } else { /* otherwise start with next service */
683         p_srvc_cb->cur_srvc_idx ++;
684 
685         bta_gattc_explore_srvc (conn_id, p_srvc_cb);
686     }
687 }
688 /*******************************************************************************
689 **
690 ** Function         bta_gattc_char_dscpt_disc_cmpl
691 **
692 ** Description      process the char descriptor discovery complete event
693 **
694 ** Returns          status
695 **
696 *******************************************************************************/
bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)697 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
698 {
699     tBTA_GATTC_ATTR_REC *p_rec = NULL;
700 
701     /* Recursive function will cause BTU stack overflow when there are a large number of characteristic
702      * without descriptor to discover. So replace it with while function */
703     while (--p_srvc_cb->total_char > 0) {
704         p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
705         /* add the next characteristic into cache */
706         bta_gattc_add_char_to_cache (p_srvc_cb,
707                                      p_rec->char_decl_handle,
708                                      p_rec->s_handle,
709                                      &p_rec->uuid,
710                                      p_rec->property);
711         /* start to discover next characteristic for descriptor */
712         if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) == 0) {
713             /* send att req and wait for att rsp */
714             break;
715         }
716     }
717 
718     if (p_srvc_cb->total_char == 0) /* all characteristic has been explored, start with next service if any */
719     {
720 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
721         APPL_TRACE_ERROR("all char has been explored");
722 #endif
723         p_srvc_cb->cur_srvc_idx ++;
724         bta_gattc_explore_srvc (conn_id, p_srvc_cb);
725     }
726 
727 }
bta_gattc_srvc_in_list(tBTA_GATTC_SERV * p_srvc_cb,UINT16 s_handle,UINT16 e_handle,tBT_UUID uuid)728 static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
729                                       UINT16 e_handle, tBT_UUID uuid)
730 {
731     tBTA_GATTC_ATTR_REC *p_rec = NULL;
732     UINT8   i;
733     BOOLEAN exist_srvc = FALSE;
734     UNUSED(uuid);
735 
736     if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) {
737         APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
738         exist_srvc = TRUE;
739     } else {
740         for (i = 0; i < p_srvc_cb->next_avail_idx; i ++) {
741             p_rec = p_srvc_cb->p_srvc_list + i;
742 
743             /* a new service should not have any overlap with other service handle range */
744             if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle) {
745                 exist_srvc = TRUE;
746                 break;
747             }
748         }
749     }
750     return exist_srvc;
751 }
752 /*******************************************************************************
753 **
754 ** Function         bta_gattc_add_srvc_to_list
755 **
756 ** Description      Add a service into explore pending list
757 **
758 ** Returns          status
759 **
760 *******************************************************************************/
bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV * p_srvc_cb,UINT16 s_handle,UINT16 e_handle,tBT_UUID uuid,BOOLEAN is_primary)761 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
762                                                    UINT16 s_handle, UINT16 e_handle,
763                                                    tBT_UUID uuid, BOOLEAN is_primary)
764 {
765     tBTA_GATTC_ATTR_REC *p_rec = NULL;
766     tBTA_GATT_STATUS    status = BTA_GATT_OK;
767 
768     if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) {
769         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
770 
771         APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x",
772                          __func__, s_handle, uuid.uu.uuid16);
773 
774         p_rec->s_handle     = s_handle;
775         p_rec->e_handle     = e_handle;
776         p_rec->is_primary   = is_primary;
777         memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
778 
779         p_srvc_cb->total_srvc ++;
780         p_srvc_cb->next_avail_idx ++;
781     } else {
782         /* allocate bigger buffer ?? */
783         status = GATT_DB_FULL;
784 
785         APPL_TRACE_ERROR("service not added, no resources or wrong state, see CONFIG_BT_GATTC_MAX_CACHE_CHAR");
786     }
787     return status;
788 }
789 /*******************************************************************************
790 **
791 ** Function         bta_gattc_add_char_to_list
792 **
793 ** Description      Add a characteristic into explore pending list
794 **
795 ** Returns          status
796 **
797 *******************************************************************************/
bta_gattc_add_char_to_list(tBTA_GATTC_SERV * p_srvc_cb,UINT16 decl_handle,UINT16 value_handle,tBT_UUID uuid,UINT8 property)798 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
799                                                    UINT16 decl_handle, UINT16 value_handle,
800                                                    tBT_UUID uuid, UINT8 property)
801 {
802     tBTA_GATTC_ATTR_REC *p_rec = NULL;
803     tBTA_GATT_STATUS    status = BTA_GATT_OK;
804 
805     if (p_srvc_cb->p_srvc_list == NULL) {
806         APPL_TRACE_ERROR("No service available, unexpected char discovery result");
807         status = BTA_GATT_INTERNAL_ERROR;
808     } else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) {
809 
810         p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
811 
812         p_srvc_cb->total_char ++;
813 
814         p_rec->s_handle = value_handle;
815         p_rec->char_decl_handle = decl_handle;
816         p_rec->property = property;
817         p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
818         memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
819 
820         /* update the endind handle of pervious characteristic if available */
821         if (p_srvc_cb->total_char > 1) {
822             p_rec -= 1;
823             p_rec->e_handle = decl_handle - 1;
824         }
825         p_srvc_cb->next_avail_idx ++;
826     } else {
827         APPL_TRACE_ERROR("char not added, no resources, see CONFIG_BT_GATTC_MAX_CACHE_CHAR");
828         /* allocate bigger buffer ?? */
829         status = BTA_GATT_DB_FULL;
830     }
831     return status;
832 
833 }
834 /*******************************************************************************
835 **
836 ** Function         bta_gattc_sdp_callback
837 **
838 ** Description      Process the discovery result from sdp
839 **
840 ** Returns          void
841 **
842 *******************************************************************************/
843 #if (SDP_INCLUDED == TRUE)
bta_gattc_sdp_callback(UINT16 sdp_status,void * user_data)844 void bta_gattc_sdp_callback(UINT16 sdp_status, void* user_data)
845 {
846     tSDP_DISC_REC       *p_sdp_rec = NULL;
847     tBT_UUID            service_uuid;
848     tSDP_PROTOCOL_ELEM  pe;
849     UINT16              start_handle = 0, end_handle = 0;
850     tBTA_GATTC_CB_DATA  *cb_data = user_data;
851     tBTA_GATTC_SERV     *p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
852 
853     if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL) {
854         do {
855             /* find a service record, report it */
856             p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
857             if (p_sdp_rec) {
858                 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
859 
860                     if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe)) {
861                         start_handle    = (UINT16) pe.params[0];
862                         end_handle      = (UINT16) pe.params[1];
863 
864 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
865                         APPL_TRACE_EVENT("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
866                                          service_uuid.uu.uuid16, start_handle, end_handle);
867 #endif
868 
869                         if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle) &&
870                                 p_srvc_cb != NULL) {
871                             /* discover services result, add services into a service list */
872                             bta_gattc_add_srvc_to_list(p_srvc_cb,
873                                                        start_handle,
874                                                        end_handle,
875                                                        service_uuid,
876                                                        TRUE);
877                         } else {
878                             APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
879                                              start_handle, end_handle);
880                         }
881                     }
882 
883 
884                 }
885             }
886         } while (p_sdp_rec);
887     }
888 
889     if ( p_srvc_cb != NULL)
890     {
891         /* start discover primary service */
892         bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
893     }
894     else
895     {
896         APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
897     }
898 
899     /* both were allocated in bta_gattc_sdp_service_disc */
900     osi_free(cb_data->p_sdp_db);
901     osi_free(cb_data);
902 }
903 #endif  ///SDP_INCLUDED == TRUE
904 
905 /*******************************************************************************
906 **
907 ** Function         bta_gattc_sdp_service_disc
908 **
909 ** Description      Start DSP Service Discovert
910 **
911 ** Returns          void
912 **
913 *******************************************************************************/
914 #if (SDP_INCLUDED == TRUE)
bta_gattc_sdp_service_disc(UINT16 conn_id,tBTA_GATTC_SERV * p_server_cb)915 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
916 {
917     tSDP_UUID       uuid;
918     UINT16          num_attrs = 2;
919     UINT16          attr_list[2];
920 
921     memset (&uuid, 0, sizeof(tSDP_UUID));
922 
923     uuid.len = LEN_UUID_16;
924     uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
925 
926     /*
927      * On success, cb_data will be freed inside bta_gattc_sdp_callback,
928      * otherwise it will be freed within this function.
929      */
930     tBTA_GATTC_CB_DATA *cb_data =
931         (tBTA_GATTC_CB_DATA *)osi_malloc(sizeof(tBTA_GATTC_CB_DATA));
932     cb_data->p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(BTA_GATT_SDP_DB_SIZE);
933     if (!cb_data || cb_data->p_sdp_db) {
934         APPL_TRACE_WARNING("%s(), no resource.", __func__);
935         return BTA_GATT_NO_RESOURCES;
936     }
937     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
938     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
939 
940     SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
941                          &uuid, num_attrs, attr_list);
942 
943     if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda,
944                                           cb_data->p_sdp_db, &bta_gattc_sdp_callback, cb_data))
945     {
946         osi_free(cb_data->p_sdp_db);
947         osi_free(cb_data);
948         return BTA_GATT_ERROR;
949     }
950 
951     cb_data->sdp_conn_id = conn_id;
952     return BTA_GATT_OK;
953 }
954 #endif  ///SDP_INCLUDED == TRUE
955 
956 /*******************************************************************************
957 **
958 ** Function         bta_gattc_disc_res_cback
959 **                  bta_gattc_disc_cmpl_cback
960 **
961 ** Description      callback functions to GATT client stack.
962 **
963 ** Returns          void
964 **
965 *******************************************************************************/
bta_gattc_disc_res_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)966 void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
967 {
968     tBTA_GATTC_SERV *p_srvc_cb = NULL;
969     BOOLEAN          pri_srvc;
970     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
971 
972     if (bta_gattc_cb.auto_disc == FALSE) {
973         return;
974     }
975 
976     p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
977 
978     if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST) {
979         p_srvc_cb->total_attr++;
980         switch (disc_type) {
981         case GATT_DISC_SRVC_ALL:
982             /* discover services result, add services into a service list */
983             bta_gattc_add_srvc_to_list(p_srvc_cb,
984                                        p_data->handle,
985                                        p_data->value.group_value.e_handle,
986                                        p_data->value.group_value.service_type,
987                                        TRUE);
988 
989             break;
990         case GATT_DISC_SRVC_BY_UUID:
991             bta_gattc_add_srvc_to_list(p_srvc_cb,
992                                        p_data->handle,
993                                        p_data->value.group_value.e_handle,
994                                        p_data->value.group_value.service_type,
995                                        TRUE);
996             break;
997 
998         case GATT_DISC_INC_SRVC:
999             /* add included service into service list if it's secondary or it never showed up
1000                in the primary service search */
1001             pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
1002                                               p_data->value.incl_service.s_handle,
1003                                               p_data->value.incl_service.e_handle,
1004                                               p_data->value.incl_service.service_type);
1005 
1006             if (!pri_srvc) {
1007                 bta_gattc_add_srvc_to_list(p_srvc_cb,
1008                                            p_data->value.incl_service.s_handle,
1009                                            p_data->value.incl_service.e_handle,
1010                                            p_data->value.incl_service.service_type,
1011                                            FALSE);
1012             }
1013             /* add into database */
1014             bta_gattc_add_attr_to_cache(p_srvc_cb,
1015                                         p_data->handle,
1016                                         &p_data->value.incl_service.service_type,
1017                                         pri_srvc,
1018                                         p_data->value.incl_service.s_handle,
1019                                         p_data->value.incl_service.e_handle,
1020                                         BTA_GATTC_ATTR_TYPE_INCL_SRVC);
1021             break;
1022 
1023         case GATT_DISC_CHAR:
1024             /* add char value into database */
1025             bta_gattc_add_char_to_list(p_srvc_cb,
1026                                        p_data->handle,
1027                                        p_data->value.dclr_value.val_handle,
1028                                        p_data->value.dclr_value.char_uuid,
1029                                        p_data->value.dclr_value.char_prop);
1030             break;
1031 
1032         case GATT_DISC_CHAR_DSCPT:
1033             bta_gattc_add_attr_to_cache(p_srvc_cb,
1034                                         p_data->handle,
1035                                         &p_data->type,
1036                                         0,
1037                                         0 /* incl_srvc_s_handle */,
1038                                         0 /* incl_srvc_e_handle */,
1039                                         BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
1040             break;
1041         }
1042     }
1043 }
bta_gattc_disc_cmpl_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_STATUS status)1044 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
1045 {
1046     tBTA_GATTC_SERV *p_srvc_cb;
1047     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1048 
1049     if (bta_gattc_cb.auto_disc == FALSE) {
1050         return;
1051     }
1052 
1053     if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) ) {
1054         if (status == GATT_SUCCESS) {
1055             p_clcb->status = status;
1056         }
1057         bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
1058         return;
1059     }
1060     p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
1061 
1062     if (p_srvc_cb != NULL) {
1063         switch (disc_type) {
1064         case GATT_DISC_SRVC_ALL:
1065         case GATT_DISC_SRVC_BY_UUID:
1066 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1067             bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
1068 #endif
1069             bta_gattc_explore_srvc(conn_id, p_srvc_cb);
1070             break;
1071 
1072         case GATT_DISC_INC_SRVC:
1073             bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
1074 
1075             break;
1076 
1077         case GATT_DISC_CHAR:
1078 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1079             bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
1080 #endif
1081             bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
1082             break;
1083 
1084         case GATT_DISC_CHAR_DSCPT:
1085             bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
1086             break;
1087         }
1088     }
1089 }
1090 /*******************************************************************************
1091 **
1092 ** Function         bta_gattc_search_service
1093 **
1094 ** Description      search local cache for matching service record.
1095 **
1096 ** Returns          FALSE if map can not be found.
1097 **
1098 *******************************************************************************/
bta_gattc_search_service(tBTA_GATTC_CLCB * p_clcb,tBT_UUID * p_uuid)1099 void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
1100 {
1101     tBTA_GATTC          cb_data;
1102 
1103     if (!p_clcb->p_srcb->p_srvc_cache || list_is_empty(p_clcb->p_srcb->p_srvc_cache)) {
1104         return;
1105     }
1106 
1107     for (list_node_t *sn = list_begin(p_clcb->p_srcb->p_srvc_cache);
1108          sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) {
1109         tBTA_GATTC_SERVICE *p_cache = list_node(sn);
1110 
1111         if (!bta_gattc_uuid_compare(p_uuid, &p_cache->uuid, FALSE)) {
1112             continue;
1113         }
1114 
1115 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1116         APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
1117                           p_cache->uuid.uu.uuid16,
1118                           p_cache->handle,
1119                           p_cache->s_handle);
1120 #endif
1121         if (!p_clcb->p_rcb->p_cback) {
1122             continue;
1123         }
1124 
1125         memset(&cb_data, 0, sizeof(tBTA_GATTC));
1126 
1127         cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
1128         cb_data.srvc_res.service_uuid.inst_id = p_cache->handle;
1129         cb_data.srvc_res.start_handle = p_cache->s_handle;
1130         cb_data.srvc_res.end_handle = p_cache->e_handle;
1131         cb_data.srvc_res.is_primary = p_cache->is_primary;
1132         memcpy(&cb_data.srvc_res.service_uuid.uuid, &p_cache->uuid, sizeof(tBT_UUID));
1133         (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
1134     }
1135 }
1136 
bta_gattc_get_services_srcb(tBTA_GATTC_SERV * p_srcb)1137 list_t* bta_gattc_get_services_srcb(tBTA_GATTC_SERV *p_srcb) {
1138     if (!p_srcb || !p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
1139         return NULL;
1140     }
1141 
1142     return p_srcb->p_srvc_cache;
1143 }
1144 
bta_gattc_get_services(UINT16 conn_id)1145 const list_t* bta_gattc_get_services(UINT16 conn_id) {
1146     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1147 
1148     if (p_clcb == NULL ) {
1149         return NULL;
1150     }
1151 
1152     tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
1153 
1154     return bta_gattc_get_services_srcb(p_srcb);
1155 }
1156 
bta_gattc_find_matching_service(const list_t * services,UINT16 handle)1157 tBTA_GATTC_SERVICE*  bta_gattc_find_matching_service(const list_t *services, UINT16 handle) {
1158     if (!services || list_is_empty(services)) {
1159         return NULL;
1160     }
1161 
1162     for (list_node_t *sn = list_begin(services);
1163          sn != list_end(services); sn = list_next(sn)) {
1164         tBTA_GATTC_SERVICE *service = list_node(sn);
1165 
1166         if (handle >= service->s_handle && handle <= service->e_handle) {
1167             return service;
1168         }
1169     }
1170 
1171     return NULL;
1172 }
1173 
bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV * p_srcb,UINT16 handle)1174 const tBTA_GATTC_SERVICE*  bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle)
1175 {
1176     const list_t *services = bta_gattc_get_services_srcb(p_srcb);
1177 
1178     return bta_gattc_find_matching_service(services, handle);
1179 }
1180 
bta_gattc_get_service_for_handle(UINT16 conn_id,UINT16 handle)1181 const tBTA_GATTC_SERVICE*  bta_gattc_get_service_for_handle(UINT16 conn_id, UINT16 handle)
1182 {
1183     const list_t *services = bta_gattc_get_services(conn_id);
1184 
1185     return bta_gattc_find_matching_service(services, handle);
1186 }
1187 
bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV * p_srcb,UINT16 handle)1188 tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle)
1189 {
1190     const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
1191 
1192     if (!service) {
1193         return NULL;
1194     }
1195 
1196     for (list_node_t *cn = list_begin(service->characteristics);
1197          cn != list_end(service->characteristics); cn = list_next(cn)) {
1198         tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1199         if (handle == p_char->handle) {
1200             return p_char;
1201         }
1202     }
1203 
1204     return NULL;
1205 }
1206 
bta_gattc_get_characteristic(UINT16 conn_id,UINT16 handle)1207 tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic(UINT16 conn_id, UINT16 handle)
1208 {
1209    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1210 
1211     if (p_clcb == NULL ) {
1212         return NULL;
1213     }
1214 
1215     tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
1216     return bta_gattc_get_characteristic_srcb(p_srcb, handle);
1217 }
1218 
bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV * p_srcb,UINT16 handle)1219 tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle)
1220 {
1221     const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
1222 
1223     if (!service) {
1224         return NULL;
1225     }
1226 
1227     for (list_node_t *cn = list_begin(service->characteristics);
1228          cn != list_end(service->characteristics); cn = list_next(cn)) {
1229         tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1230         for (list_node_t *dn = list_begin(p_char->descriptors);
1231              dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1232             tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
1233             if (handle == p_desc->handle) {
1234                 return p_desc;
1235             }
1236         }
1237     }
1238 
1239     return NULL;
1240 }
1241 
bta_gattc_get_descriptor(UINT16 conn_id,UINT16 handle)1242 tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor(UINT16 conn_id, UINT16 handle)
1243 {
1244     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1245 
1246     if (p_clcb == NULL ) {
1247         return NULL;
1248     }
1249 
1250     tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
1251     return bta_gattc_get_descriptor_srcb(p_srcb, handle);
1252 }
1253 
bta_gattc_get_service_with_uuid(UINT16 conn_id,tBT_UUID * svc_uuid,btgatt_db_element_t ** svc_db,UINT16 * count)1254 void bta_gattc_get_service_with_uuid(UINT16 conn_id, tBT_UUID *svc_uuid,
1255                                      btgatt_db_element_t **svc_db,
1256                                      UINT16 *count)
1257 {
1258     const list_t* svc = bta_gattc_get_services(conn_id);
1259     if(!svc) {
1260         APPL_TRACE_WARNING("%s(), no service.", __func__);
1261         *svc_db = NULL;
1262         *count = 0;
1263         return;
1264     }
1265     size_t db_size = list_length(svc);
1266     void *buffer = osi_malloc(db_size*sizeof(btgatt_db_element_t));
1267     if (!buffer) {
1268         APPL_TRACE_WARNING("%s(), no resource.", __func__);
1269         *svc_db = NULL;
1270         *count = 0;
1271         return;
1272     }
1273     btgatt_db_element_t *curr_db_attr = buffer;
1274     db_size = 0;
1275     for (list_node_t *sn = list_begin(svc);
1276          sn != list_end(svc); sn = list_next(sn)) {
1277         tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
1278         if (svc_uuid == NULL || bta_gattc_uuid_compare(svc_uuid, &p_cur_srvc->uuid, TRUE)) {
1279             bta_gattc_fill_gatt_db_el(curr_db_attr,
1280                                       p_cur_srvc->is_primary ?
1281                                       BTGATT_DB_PRIMARY_SERVICE :
1282                                       BTGATT_DB_SECONDARY_SERVICE,
1283                                       0 /* att_handle */,
1284                                       p_cur_srvc->s_handle /* s_handle */,
1285                                       p_cur_srvc->e_handle /* e_handle */,
1286                                       p_cur_srvc->s_handle,
1287                                       p_cur_srvc->uuid,
1288                                       0 /* prop */);
1289             db_size++;
1290             curr_db_attr++;
1291         }
1292     }
1293 
1294     *svc_db = buffer;
1295     *count = db_size;
1296 }
1297 
1298 /*******************************************************************************
1299 **
1300 ** Function         bta_gattc_fill_gatt_db_el
1301 **
1302 ** Description      fill a btgatt_db_element_t value
1303 **
1304 ** Returns          None.
1305 **
1306 *******************************************************************************/
bta_gattc_fill_gatt_db_el(btgatt_db_element_t * p_attr,bt_gatt_db_attribute_type_t type,UINT16 att_handle,UINT16 s_handle,UINT16 e_handle,UINT16 id,tBT_UUID uuid,UINT8 prop)1307 void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr,
1308                                bt_gatt_db_attribute_type_t type,
1309                                UINT16 att_handle,
1310                                UINT16 s_handle, UINT16 e_handle,
1311                                UINT16 id, tBT_UUID uuid, UINT8 prop)
1312 {
1313     p_attr->type             = type;
1314     p_attr->attribute_handle = att_handle;
1315     p_attr->start_handle     = s_handle;
1316     p_attr->end_handle       = e_handle;
1317     p_attr->id               = id;
1318     p_attr->properties       = prop;
1319     bta_to_btif_uuid(&p_attr->uuid, &uuid);
1320 }
1321 
bta_gattc_get_db_with_opration(UINT16 conn_id,bt_gatt_get_db_op_t op,UINT16 char_handle,tBT_UUID * incl_uuid,tBT_UUID * char_uuid,tBT_UUID * descr_uuid,UINT16 start_handle,UINT16 end_handle,btgatt_db_element_t ** char_db,UINT16 * count)1322 void bta_gattc_get_db_with_opration(UINT16 conn_id,
1323                                                       bt_gatt_get_db_op_t op,
1324                                                       UINT16 char_handle,
1325                                                       tBT_UUID *incl_uuid,
1326                                                       tBT_UUID *char_uuid,
1327                                                       tBT_UUID *descr_uuid,
1328                                                       UINT16 start_handle, UINT16 end_handle,
1329                                                       btgatt_db_element_t **char_db,
1330                                                       UINT16 *count)
1331 {
1332     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1333 
1334     if (p_clcb == NULL) {
1335         *count = 0;
1336         *char_db = NULL;
1337         return;
1338     }
1339 
1340     tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
1341     if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
1342         APPL_TRACE_DEBUG("the service cache is empty.");
1343         *count = 0;
1344         *char_db = NULL;
1345         return;
1346     }
1347 
1348     size_t db_size = ((end_handle - start_handle + 1) < p_srcb->total_attr) ? (end_handle - start_handle + 1) : p_srcb->total_attr;
1349     if (!db_size) {
1350         APPL_TRACE_DEBUG("the db size is 0.");
1351         *count = 0;
1352         *char_db = NULL;
1353         return;
1354     }
1355 
1356     void *buffer = osi_malloc(db_size*sizeof(btgatt_db_element_t));
1357 
1358     if (!buffer) {
1359         APPL_TRACE_DEBUG("the buffer is NULL.");
1360         *count = 0;
1361         *char_db = NULL;
1362         return;
1363     }
1364     btgatt_db_element_t *curr_db_attr = buffer;
1365     db_size = 0;
1366     for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
1367          sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
1368         tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
1369 
1370         if (p_cur_srvc->e_handle < start_handle) {
1371             continue;
1372         }
1373 
1374         if (p_cur_srvc->s_handle > end_handle) {
1375             break;
1376         }
1377 
1378         if (op == GATT_OP_GET_INCLUDE_SVC) {
1379             if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
1380                 continue;
1381 
1382             for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
1383                  isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
1384                 tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
1385 
1386                 if (p_isvc->handle < start_handle) {
1387                     continue;
1388                 }
1389 
1390                 if (p_isvc->handle > end_handle) {
1391                     *char_db = buffer;
1392                     *count = db_size;
1393                     return;
1394                 }
1395                 if (!incl_uuid || bta_gattc_uuid_compare(&p_isvc->uuid, incl_uuid, TRUE)) {
1396                     bta_gattc_fill_gatt_db_el(curr_db_attr,
1397                                               BTGATT_DB_INCLUDED_SERVICE,
1398                                               p_isvc->handle,
1399                                               p_isvc->incl_srvc_s_handle /* s_handle */,
1400                                               p_isvc->incl_srvc_e_handle /* e_handle */,
1401                                               p_isvc->handle,
1402                                               p_isvc->uuid,
1403                                               0 /* property */);
1404                     curr_db_attr++;
1405                     db_size++;
1406                 }
1407             }
1408             continue;
1409         }
1410 
1411         if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) {
1412             continue;
1413         }
1414 
1415         for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
1416              cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1417             tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1418             if(op == GATT_OP_GET_ALL_CHAR || op == GATT_OP_GET_CHAR_BY_UUID) {
1419                 if (p_char->handle < start_handle) {
1420                     continue;
1421                 }
1422             }
1423 
1424             if (p_char->handle > end_handle) {
1425                 *char_db = buffer;
1426                 *count = db_size;
1427                 return;
1428             }
1429             if ((op == GATT_OP_GET_ALL_CHAR || op == GATT_OP_GET_CHAR_BY_UUID) &&
1430                 (char_uuid == NULL || bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE))) {
1431                 APPL_TRACE_DEBUG("%s(), uuid match.", __func__);
1432                 bta_gattc_fill_gatt_db_el(curr_db_attr,
1433                                           BTGATT_DB_CHARACTERISTIC,
1434                                           p_char->handle,
1435                                           0 /* s_handle */,
1436                                           0 /* e_handle */,
1437                                           p_char->handle,
1438                                           p_char->uuid,
1439                                           p_char->properties);
1440                 curr_db_attr++;
1441                 db_size++;
1442                 continue;
1443             }
1444 
1445             if (!p_char->descriptors || list_is_empty(p_char->descriptors)) {
1446                 continue;
1447             }
1448 
1449             if ((op == GATT_OP_GET_DESCRI_BY_HANDLE || op == GATT_OP_GET_ALL_DESCRI) && (p_char->handle != char_handle)) {
1450                 continue;
1451             }
1452 
1453             if ((op == GATT_OP_GET_DESCRI_BY_UUID) &&
1454                 !bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE)) {
1455                 continue;
1456             }
1457 
1458             if (op == GATT_OP_GET_ALL_DESCRI || op == GATT_OP_GET_DESCRI_BY_UUID || op == GATT_OP_GET_DESCRI_BY_HANDLE) {
1459                 for (list_node_t *dn = list_begin(p_char->descriptors);
1460                      dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1461                     tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
1462 
1463                     if (p_desc->handle < start_handle) {
1464                         continue;
1465                     }
1466                     if (p_desc->handle > end_handle) {
1467                         *char_db = buffer;
1468                         *count = db_size;
1469                         return;
1470                     }
1471                     if (((op == GATT_OP_GET_ALL_DESCRI || op == GATT_OP_GET_DESCRI_BY_UUID) &&
1472                         (descr_uuid == NULL || bta_gattc_uuid_compare(&p_desc->uuid, descr_uuid, TRUE))) ||
1473                         (op == GATT_OP_GET_DESCRI_BY_HANDLE && bta_gattc_uuid_compare(&p_desc->uuid, descr_uuid, TRUE))) {
1474                         bta_gattc_fill_gatt_db_el(curr_db_attr,
1475                                                   BTGATT_DB_DESCRIPTOR,
1476                                                   p_desc->handle,
1477                                                   0 /* s_handle */,
1478                                                   0 /* e_handle */,
1479                                                   p_desc->handle,
1480                                                   p_desc->uuid,
1481                                                   0 /* property */);
1482                         curr_db_attr++;
1483                         db_size++;
1484                     }
1485                 }
1486             }
1487 
1488         }
1489     }
1490 
1491     *char_db = buffer;
1492     *count = db_size;
1493 }
1494 
bta_gattc_get_db_size_with_type(list_t * services,bt_gatt_db_attribute_type_t type,tBT_UUID * char_uuid,UINT16 start_handle,UINT16 end_handle)1495 static size_t bta_gattc_get_db_size_with_type(list_t *services,
1496                                               bt_gatt_db_attribute_type_t type,
1497                                               tBT_UUID *char_uuid,
1498                                               UINT16 start_handle, UINT16 end_handle)
1499 {
1500     if (!services || list_is_empty(services)) {
1501         return 0;
1502     }
1503 
1504     size_t db_size = 0;
1505     UINT16 svc_length = list_length(services) - 1;
1506 
1507     for (list_node_t *sn = list_begin(services);
1508          sn != list_end(services); sn = list_next(sn), svc_length--) {
1509         tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
1510 
1511         if (p_cur_srvc->e_handle < start_handle) {
1512             continue;
1513         }
1514 
1515         if (p_cur_srvc->s_handle > end_handle) {
1516             break;
1517         }
1518 
1519         if (type == BTGATT_DB_PRIMARY_SERVICE || type == BTGATT_DB_SECONDARY_SERVICE) {
1520             if ((type == BTGATT_DB_PRIMARY_SERVICE && p_cur_srvc->is_primary) ||
1521                 (type == BTGATT_DB_SECONDARY_SERVICE && !p_cur_srvc->is_primary)) {
1522                 // if the current service is the last service in the db, need to ensure the current service start handle is not less than the start_handle.
1523                 if (!svc_length) {
1524                     if (p_cur_srvc->s_handle >= start_handle) {
1525                         db_size++;
1526                     }
1527                 } else {
1528                     db_size++;
1529                 }
1530             }
1531             continue;
1532         }
1533 
1534         if (p_cur_srvc->included_svc && (type == BTGATT_DB_INCLUDED_SERVICE)) {
1535             for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
1536                  isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
1537                 tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
1538 
1539                 if (p_isvc->handle < start_handle) {
1540                     continue;
1541                 }
1542 
1543                 if (p_isvc->handle > end_handle) {
1544                     return db_size;
1545                 }
1546                 db_size++;
1547             }
1548             continue;
1549         }
1550 
1551         if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) {
1552             continue;
1553         }
1554 
1555         if (char_uuid != NULL) {
1556             for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
1557                 cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1558                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1559 
1560                 if (p_char->handle < start_handle) {
1561                     continue;
1562                 }
1563 
1564                 if (p_char->handle > end_handle) {
1565                     return db_size;
1566                 }
1567 
1568                 if ((type == BTGATT_DB_CHARACTERISTIC) && bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE)) {
1569                     db_size++;
1570                     continue;
1571                 }
1572 
1573                 if (p_char->descriptors && (type == BTGATT_DB_DESCRIPTOR) && bta_gattc_uuid_compare(&p_char->uuid, char_uuid, TRUE)) {
1574                     for (list_node_t *dn = list_begin(p_char->descriptors);
1575                          dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1576                         tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
1577 
1578                         if (p_desc->handle < start_handle) {
1579                             continue;
1580                         }
1581 
1582                         if (p_desc->handle > end_handle) {
1583                             return db_size;
1584                         }
1585                         db_size++;
1586                     }
1587                 }
1588             }
1589         } else {
1590             if (type == BTGATT_DB_CHARACTERISTIC) {
1591                 for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
1592                      cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1593                     tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1594 
1595                     if (p_char->handle < start_handle) {
1596                         continue;
1597                     }
1598 
1599                     if (p_char->handle > end_handle) {
1600                         return db_size;
1601                     }
1602                     db_size++;
1603                 }
1604             }
1605         }
1606 
1607     }
1608 
1609     return db_size;
1610 }
1611 
1612 /*******************************************************************************
1613 ** Returns          number of elements inside db from start_handle to end_handle
1614 *******************************************************************************/
bta_gattc_get_db_size(list_t * services,UINT16 start_handle,UINT16 end_handle)1615 static size_t bta_gattc_get_db_size(list_t *services,
1616                                     UINT16 start_handle, UINT16 end_handle)
1617 {
1618     if (!services || list_is_empty(services)) {
1619         return 0;
1620     }
1621 
1622     size_t db_size = 0;
1623     UINT16 svc_length = list_length(services) - 1;
1624     for (list_node_t *sn = list_begin(services);
1625          sn != list_end(services); sn = list_next(sn), svc_length--) {
1626         tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
1627 
1628         if (p_cur_srvc->e_handle < start_handle) {
1629             continue;
1630         }
1631 
1632         if (p_cur_srvc->s_handle > end_handle) {
1633             break;
1634         }
1635 
1636         if (!svc_length) {
1637             if (p_cur_srvc->s_handle >= start_handle) {
1638                 db_size++;
1639             }
1640         } else {
1641             db_size++;
1642         }
1643 
1644         if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) {
1645             continue;
1646         }
1647 
1648         for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
1649              cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1650             tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1651 
1652             if (p_char->handle < start_handle) {
1653                 continue;
1654             }
1655             if (p_char->handle > end_handle) {
1656                 return db_size;
1657             }
1658             db_size++;
1659 
1660             if (p_char->descriptors) {
1661                 for (list_node_t *dn = list_begin(p_char->descriptors);
1662                      dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1663                     tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
1664                     if (p_desc->handle < start_handle) {
1665                         continue;
1666                     }
1667                     if (p_desc->handle > end_handle) {
1668                         return db_size;
1669                     }
1670                     db_size++;
1671                 }
1672             }
1673         }
1674 
1675         if (p_cur_srvc->included_svc) {
1676             for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
1677                  isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
1678                 tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
1679 
1680                 if (p_isvc->handle < start_handle) {
1681                     continue;
1682                 }
1683 
1684                 if (p_isvc->handle > end_handle) {
1685                     return db_size;
1686                 }
1687                 db_size++;
1688             }
1689         }
1690     }
1691 
1692     return db_size;
1693 }
1694 
bta_gattc_get_db_size_handle(UINT16 conn_id,UINT16 start_handle,UINT16 end_handle,UINT16 * count)1695 void bta_gattc_get_db_size_handle(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, UINT16 *count)
1696 {
1697     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1698 
1699     if (p_clcb == NULL) {
1700         *count = 0;
1701         return;
1702     }
1703 
1704     tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
1705     if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
1706         *count = 0;
1707         return;
1708     }
1709 
1710     *count = bta_gattc_get_db_size(p_srcb->p_srvc_cache, start_handle, end_handle);
1711 }
1712 
bta_gattc_get_db_size_with_type_handle(UINT16 conn_id,bt_gatt_db_attribute_type_t type,UINT16 start_handle,UINT16 end_handle,UINT16 char_handle,UINT16 * count)1713 void bta_gattc_get_db_size_with_type_handle(UINT16 conn_id, bt_gatt_db_attribute_type_t type,
1714                                             UINT16 start_handle, UINT16 end_handle, UINT16 char_handle, UINT16 *count)
1715 {
1716     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1717 
1718     if (p_clcb == NULL) {
1719         *count = 0;
1720         return;
1721     }
1722 
1723     tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
1724     if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) {
1725         *count = 0;
1726         return;
1727     }
1728 
1729     if (type == BTGATT_DB_DESCRIPTOR) {
1730         if (char_handle == BTA_GATTC_INVALID_HANDLE) {
1731             *count = 0;
1732             return;
1733         } else {
1734             tBTA_GATTC_CHARACTERISTIC *char_db = bta_gattc_get_characteristic(conn_id, char_handle);
1735             *count = char_db ? list_length(char_db->descriptors) : 0;
1736             return;
1737         }
1738     }
1739     *count = bta_gattc_get_db_size_with_type(p_srcb->p_srvc_cache, type, NULL, start_handle, end_handle);
1740 
1741 }
1742 
1743 /*******************************************************************************
1744 **
1745 ** Function         bta_gattc_get_gatt_db_impl
1746 **
1747 ** Description      copy the server GATT database into db parameter.
1748 **
1749 ** Parameters       p_srvc_cb: server.
1750 **                  db: output parameter which will contain GATT database copy.
1751 **                      Caller is responsible for freeing it.
1752 **                  count: output parameter which will contain number of
1753 **                  elements in database.
1754 **
1755 ** Returns          None.
1756 **
1757 *******************************************************************************/
bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV * p_srvc_cb,UINT16 start_handle,UINT16 end_handle,btgatt_db_element_t ** db,UINT16 * count)1758 static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
1759                                        UINT16 start_handle, UINT16 end_handle,
1760                                        btgatt_db_element_t **db,
1761                                        UINT16 *count)
1762 {
1763     APPL_TRACE_DEBUG("%s: start_handle 0x%04x, end_handle 0x%04x",
1764                      __func__, start_handle, end_handle);
1765 
1766     if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
1767         *count = 0;
1768         *db = NULL;
1769         return;
1770     }
1771 
1772     size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, start_handle, end_handle);
1773 
1774     void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
1775     if (!buffer) {
1776         APPL_TRACE_WARNING("%s(), no resource.", __func__);
1777         *db = NULL;
1778         *count = 0;
1779         return;
1780     }
1781     btgatt_db_element_t *curr_db_attr = buffer;
1782 
1783     for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
1784          sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1785         tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
1786 
1787         if (p_cur_srvc->e_handle < start_handle) {
1788             continue;
1789         }
1790 
1791         if (p_cur_srvc->s_handle > end_handle) {
1792             break;
1793         }
1794 
1795         bta_gattc_fill_gatt_db_el(curr_db_attr,
1796                                   p_cur_srvc->is_primary ?
1797                                   BTGATT_DB_PRIMARY_SERVICE :
1798                                   BTGATT_DB_SECONDARY_SERVICE,
1799                                   0 /* att_handle */,
1800                                   p_cur_srvc->s_handle,
1801                                   p_cur_srvc->e_handle,
1802                                   p_cur_srvc->s_handle,
1803                                   p_cur_srvc->uuid,
1804                                   0 /* prop */);
1805         curr_db_attr++;
1806 
1807         if (p_cur_srvc->characteristics && !list_is_empty(p_cur_srvc->characteristics)) {
1808 
1809             for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
1810                  cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
1811                 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
1812 
1813                 if (p_char->handle < start_handle) {
1814                     continue;
1815                 }
1816 
1817                 if (p_char->handle > end_handle) {
1818                     *db = buffer;
1819                     *count = db_size;
1820                     return;
1821                 }
1822                 bta_gattc_fill_gatt_db_el(curr_db_attr,
1823                                           BTGATT_DB_CHARACTERISTIC,
1824                                           p_char->handle,
1825                                           0 /* s_handle */,
1826                                           0 /* e_handle */,
1827                                           p_char->handle,
1828                                           p_char->uuid,
1829                                           p_char->properties);
1830                 curr_db_attr++;
1831 
1832                 if (!p_char->descriptors || list_is_empty(p_char->descriptors)) {
1833                     continue;
1834                 }
1835 
1836                 for (list_node_t *dn = list_begin(p_char->descriptors);
1837                      dn != list_end(p_char->descriptors); dn = list_next(dn)) {
1838                     tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
1839 
1840                     if (p_desc->handle < start_handle) {
1841                         continue;
1842                     }
1843 
1844                     if (p_desc->handle > end_handle) {
1845                         *db = buffer;
1846                         *count = db_size;
1847                         return;
1848                     }
1849                     bta_gattc_fill_gatt_db_el(curr_db_attr,
1850                                               BTGATT_DB_DESCRIPTOR,
1851                                               p_desc->handle,
1852                                               0 /* s_handle */,
1853                                               0 /* e_handle */,
1854                                               p_desc->handle,
1855                                               p_desc->uuid,
1856                                               0 /* property */);
1857                     curr_db_attr++;
1858                 }
1859             }
1860         }
1861 
1862         if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc)) {
1863             continue;
1864         }
1865 
1866         for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
1867              isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
1868             tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
1869 
1870             if (p_isvc->handle < start_handle) {
1871                 continue;
1872             }
1873 
1874             if (p_isvc->handle > end_handle) {
1875                 *db = buffer;
1876                 *count = db_size;
1877                 return;
1878             }
1879             bta_gattc_fill_gatt_db_el(curr_db_attr,
1880                                       BTGATT_DB_INCLUDED_SERVICE,
1881                                       p_isvc->handle,
1882                                       0 /* s_handle */,
1883                                       0 /* e_handle */,
1884                                       p_isvc->handle,
1885                                       p_isvc->uuid,
1886                                       0 /* property */);
1887             curr_db_attr++;
1888         }
1889     }
1890 
1891     *db = buffer;
1892     *count = db_size;
1893 }
1894 
1895 /*******************************************************************************
1896 **
1897 ** Function         bta_gattc_get_gatt_db
1898 **
1899 ** Description      copy the server GATT database into db parameter.
1900 **
1901 ** Parameters       conn_id: connection ID which identify the server.
1902 **                  db: output parameter which will contain GATT database copy.
1903 **                      Caller is responsible for freeing it.
1904 **                  count: number of elements in database.
1905 **
1906 ** Returns          None.
1907 **
1908 *******************************************************************************/
bta_gattc_get_gatt_db(UINT16 conn_id,UINT16 start_handle,UINT16 end_handle,btgatt_db_element_t ** db,UINT16 * count)1909 void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, UINT16 *count)
1910 {
1911     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1912 
1913     if (p_clcb == NULL) {
1914         APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
1915         return;
1916     }
1917 
1918     if (p_clcb->state != BTA_GATTC_CONN_ST) {
1919         APPL_TRACE_ERROR("server cache not available, CLCB state = %d",
1920                          p_clcb->state);
1921         return;
1922     }
1923 
1924     if (!p_clcb->p_srcb || p_clcb->p_srcb->p_srvc_list || /* no active discovery */
1925         !p_clcb->p_srcb->p_srvc_cache) {
1926         APPL_TRACE_ERROR("No server cache available");
1927         return;
1928     }
1929 
1930     bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db, count);
1931 }
1932 
1933 /*******************************************************************************
1934 **
1935 ** Function         bta_gattc_rebuild_cache
1936 **
1937 ** Description      rebuild server cache from NV cache.
1938 **
1939 ** Parameters
1940 **
1941 ** Returns          None.
1942 **
1943 *******************************************************************************/
bta_gattc_rebuild_cache(tBTA_GATTC_SERV * p_srvc_cb,UINT16 num_attr,tBTA_GATTC_NV_ATTR * p_attr)1944 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
1945                              tBTA_GATTC_NV_ATTR *p_attr)
1946 {
1947     /* first attribute loading, initialize buffer */
1948     APPL_TRACE_DEBUG("%s: bta_gattc_rebuild_cache, num_attr = %d", __func__, num_attr);
1949 
1950     list_free(p_srvc_cb->p_srvc_cache);
1951     p_srvc_cb->p_srvc_cache = NULL;
1952 
1953     while (num_attr > 0 && p_attr != NULL) {
1954         switch (p_attr->attr_type) {
1955         case BTA_GATTC_ATTR_TYPE_SRVC:
1956                 bta_gattc_add_srvc_to_cache(p_srvc_cb,
1957                                             p_attr->s_handle,
1958                                             p_attr->e_handle,
1959                                             &p_attr->uuid,
1960                                             p_attr->is_primary);
1961                 break;
1962 
1963             case BTA_GATTC_ATTR_TYPE_CHAR:
1964                 //TODO(jpawlowski): store decl_handle properly.
1965                 bta_gattc_add_char_to_cache(p_srvc_cb,
1966                                             p_attr->s_handle,
1967                                             p_attr->s_handle,
1968                                             &p_attr->uuid,
1969                                             p_attr->prop);
1970                 break;
1971 
1972             case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
1973                 bta_gattc_add_attr_to_cache(p_srvc_cb,
1974                                              p_attr->s_handle,
1975                                              &p_attr->uuid,
1976                                              p_attr->prop,
1977                                              p_attr->incl_srvc_s_handle,
1978                                              p_attr->incl_srvc_e_handle,
1979                                              p_attr->attr_type);
1980                 break;
1981             case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
1982                 bta_gattc_add_attr_to_cache(p_srvc_cb,
1983                                             p_attr->s_handle,
1984                                             &p_attr->uuid,
1985                                             p_attr->prop,
1986                                             p_attr->incl_srvc_s_handle,
1987                                             p_attr->incl_srvc_e_handle,
1988                                             p_attr->attr_type);
1989                 break;
1990         }
1991         p_attr ++;
1992         num_attr --;
1993     }
1994 }
1995 
1996 /*******************************************************************************
1997 **
1998 ** Function         bta_gattc_fill_nv_attr
1999 **
2000 ** Description      fill a NV attribute entry value
2001 **
2002 ** Returns          None.
2003 **
2004 *******************************************************************************/
bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR * p_attr,UINT8 type,UINT16 s_handle,UINT16 e_handle,tBT_UUID uuid,UINT8 prop,UINT16 incl_srvc_s_handle,UINT16 incl_srvc_e_handle,BOOLEAN is_primary)2005 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
2006                             UINT16 e_handle, tBT_UUID uuid, UINT8 prop, UINT16 incl_srvc_s_handle,
2007                             UINT16 incl_srvc_e_handle, BOOLEAN is_primary)
2008 {
2009     p_attr->s_handle    = s_handle;
2010     p_attr->e_handle    = e_handle;
2011     p_attr->attr_type   = type;
2012     p_attr->is_primary  = is_primary;
2013     p_attr->id          = 0;
2014     p_attr->prop        = prop;
2015     p_attr->incl_srvc_s_handle = incl_srvc_s_handle;
2016     p_attr->incl_srvc_e_handle = incl_srvc_e_handle;
2017 
2018     memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
2019 }
2020 /*******************************************************************************
2021 **
2022 ** Function         bta_gattc_cache_save
2023 **
2024 ** Description      save the server cache into NV
2025 **
2026 ** Returns          None.
2027 **
2028 *******************************************************************************/
bta_gattc_cache_save(tBTA_GATTC_SERV * p_srvc_cb,UINT16 conn_id)2029 void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
2030 {
2031     if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
2032         return;
2033     }
2034 
2035     int i = 0;
2036     size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, 0x0000, 0xFFFF);
2037     tBTA_GATTC_NV_ATTR *nv_attr = osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR));
2038     // This step is very importent, if not clear the memory, the hasy key base on the attribute case will be not corret.
2039     if (nv_attr != NULL) {
2040         memset(nv_attr, 0, db_size * sizeof(tBTA_GATTC_NV_ATTR));
2041     }
2042 
2043     if (!nv_attr) {
2044         APPL_TRACE_WARNING("%s(), no resource.", __func__);
2045         return;
2046     }
2047     for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
2048          sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
2049         tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
2050 
2051         bta_gattc_fill_nv_attr(&nv_attr[i++],
2052                                 BTA_GATTC_ATTR_TYPE_SRVC,
2053                                p_cur_srvc->s_handle,
2054                                p_cur_srvc->e_handle,
2055                                p_cur_srvc->uuid,
2056                                0 /* properties */,
2057                                0 /* incl_srvc_s_handle */,
2058                                0 /* incl_srvc_e_handle */,
2059                                p_cur_srvc->is_primary);
2060     }
2061 
2062     for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
2063          sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
2064         tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
2065 
2066         if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) {
2067             continue;
2068         }
2069 
2070         for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
2071              cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
2072             tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
2073 
2074             bta_gattc_fill_nv_attr(&nv_attr[i++],
2075                                    BTA_GATTC_ATTR_TYPE_CHAR,
2076                                    p_char->handle,
2077                                    0,
2078                                    p_char->uuid,
2079                                    p_char->properties,
2080                                    0 /* incl_srvc_s_handle */,
2081                                    0 /* incl_srvc_e_handle */,
2082                                    FALSE);
2083 
2084             if (!p_char->descriptors || list_is_empty(p_char->descriptors)) {
2085                 continue;
2086             }
2087 
2088             for (list_node_t *dn = list_begin(p_char->descriptors);
2089                  dn != list_end(p_char->descriptors); dn = list_next(dn)) {
2090                 tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
2091 
2092                 bta_gattc_fill_nv_attr(&nv_attr[i++],
2093                                        BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
2094                                        p_desc->handle,
2095                                        0,
2096                                        p_desc->uuid,
2097                                        0 /* properties */,
2098                                        0 /* incl_srvc_s_handle */,
2099                                        0 /* incl_srvc_e_handle */,
2100                                        FALSE);
2101             }
2102         }
2103 
2104         if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc)) {
2105             continue;
2106         }
2107 
2108         for (list_node_t *an = list_begin(p_cur_srvc->included_svc);
2109              an != list_end(p_cur_srvc->included_svc); an = list_next(an)) {
2110             tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(an);
2111 
2112             bta_gattc_fill_nv_attr(&nv_attr[i++],
2113                                    BTA_GATTC_ATTR_TYPE_INCL_SRVC,
2114                                    p_isvc->handle,
2115                                    0,
2116                                    p_isvc->uuid,
2117                                    0 /* properties */,
2118                                    p_isvc->included_service->s_handle,
2119                                    p_isvc->included_service->e_handle,
2120                                    FALSE);
2121         }
2122     }
2123 
2124     /* TODO: Gattc cache write/read need to be added in IDF 3.1*/
2125     bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr);
2126     osi_free(nv_attr);
2127 }
2128 
2129 /*******************************************************************************
2130 **
2131 ** Function         bta_gattc_cache_load
2132 **
2133 ** Description      Load GATT cache from storage for server.
2134 **
2135 ** Parameter        p_clcb: pointer to server clcb, that will
2136 **                          be filled from storage
2137 ** Returns          true on success, false otherwise
2138 **
2139 *******************************************************************************/
bta_gattc_cache_load(tBTA_GATTC_CLCB * p_clcb)2140 bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb)
2141 {
2142     /* open NV cache and send call in */
2143     tBTA_GATT_STATUS status = BTA_GATT_OK;
2144     UINT8 index = 0;
2145     tBTA_GATTC_NV_ATTR  *attr = NULL;
2146 
2147     if ((status = bta_gattc_co_cache_open(p_clcb->p_srcb->server_bda, true, &index)) != BTA_GATT_OK) {
2148         APPL_TRACE_DEBUG("%s(), gattc cache open fail, index = %x", __func__, index);
2149         return false;
2150     }
2151 
2152     size_t num_attr = bta_gattc_get_cache_attr_length(index) / sizeof(tBTA_GATTC_NV_ATTR);
2153 
2154     if (!num_attr) {
2155         return false;
2156     }
2157     //don't forget to set the total attribute number.
2158     p_clcb->p_srcb->total_attr = num_attr;
2159     APPL_TRACE_DEBUG("%s(), index = %x, num_attr = %d", __func__, index, num_attr);
2160     if ((attr = osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr)) == NULL) {
2161         APPL_TRACE_ERROR("%s, No Memory.", __func__);
2162         return false;
2163     }
2164     if ((status = bta_gattc_co_cache_load(attr, index)) != BTA_GATT_OK) {
2165         APPL_TRACE_DEBUG("%s(), gattc cache load fail, status = %x", __func__, status);
2166         return false;
2167     }
2168     p_clcb->searched_service_source = BTA_GATTC_SERVICE_INFO_FROM_NVS_FLASH;
2169     bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr);
2170     //free the attr buffer after used.
2171     osi_free(attr);
2172     return true;
2173 }
2174 
2175 /*******************************************************************************
2176 **
2177 ** Function         bta_gattc_cache_write
2178 **
2179 ** Description      This callout function is executed by GATT when a server cache
2180 **                  is available to save.
2181 **
2182 ** Parameter        server_bda: server bd address of this cache belongs to
2183 **                  num_attr: number of attribute to be save.
2184 **                  attr: pointer to the list of attributes to save.
2185 ** Returns
2186 **
2187 *******************************************************************************/
bta_gattc_cache_write(BD_ADDR server_bda,UINT16 num_attr,tBTA_GATTC_NV_ATTR * attr)2188 static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr,
2189                            tBTA_GATTC_NV_ATTR *attr)
2190 {
2191     bta_gattc_co_cache_save(server_bda, num_attr, attr);
2192 }
2193 
2194 /*******************************************************************************
2195 **
2196 ** Function         bta_gattc_cache_reset
2197 **
2198 ** Description      This callout function is executed by GATTC to reset cache in
2199 **                  application
2200 **
2201 ** Parameter        server_bda: server bd address of this cache belongs to
2202 **
2203 ** Returns          void.
2204 **
2205 *******************************************************************************/
bta_gattc_cache_reset(BD_ADDR server_bda)2206 void bta_gattc_cache_reset(BD_ADDR server_bda)
2207 {
2208     BTIF_TRACE_DEBUG("%s", __func__);
2209     char fname[255] = {0};
2210     bta_gattc_generate_cache_file_name(fname, server_bda);
2211     bta_gattc_co_cache_reset(server_bda);
2212     //unlink(fname);
2213 }
2214 
2215 //#endif /* GATTC_CACHE_NVS */
2216 #endif /* BTA_GATT_INCLUDED */
2217