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