1 /******************************************************************************
3 * Copyright (C) 2003-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * This file contains the GATT client discovery procedures and cache
24 ******************************************************************************/
26 #define LOG_TAG "bt_bta_gattc"
28 #include "bt_target.h"
30 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
36 #include "bta_gattc_int.h"
39 #include "btm_ble_api.h"
41 #include "bt_common.h"
42 #include "osi/include/log.h"
47 static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr);
48 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
49 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
50 extern void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
52 #define BTA_GATT_SDP_DB_SIZE 4096
54 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
55 #define GATT_CACHE_VERSION 1
57 static void bta_gattc_generate_cache_file_name(char *buffer, BD_ADDR bda)
59 sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX,
60 bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
63 /*****************************************************************************
64 ** Constants and data types
65 *****************************************************************************/
69 tSDP_DISCOVERY_DB *p_sdp_db;
73 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
74 static char *bta_gattc_attr_type[] =
76 "I", /* Included Service */
77 "C", /* Characteristic */
78 "D" /* Characteristic Descriptor */
80 /* utility functions */
82 bool display_cache_attribute(void *data, void *context) {
83 tBTA_GATTC_CACHE_ATTR *p_attr = data;
84 APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]",
85 p_attr->attr_handle, p_attr->uuid.uu.uuid16,
86 bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
90 bool display_cache_service(void *data, void *context) {
91 tBTA_GATTC_CACHE *p_cur_srvc = data;
92 APPL_TRACE_ERROR("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]",
93 p_cur_srvc->s_handle, p_cur_srvc->e_handle,
94 ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
95 p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
96 p_cur_srvc->service_uuid.id.inst_id);
98 if (p_cur_srvc->p_attr != NULL) {
99 list_foreach(p_cur_srvc->p_attr, display_cache_attribute, NULL);
105 /*******************************************************************************
107 ** Function bta_gattc_display_cache_server
109 ** Description debug function to display the server cache.
113 *******************************************************************************/
114 static void bta_gattc_display_cache_server(list_t *p_cache)
116 APPL_TRACE_ERROR("<================Start Server Cache =============>");
117 list_foreach(p_cache, display_cache_service, NULL);
118 APPL_TRACE_ERROR("<================End Server Cache =============>");
119 APPL_TRACE_ERROR(" ");
122 /*******************************************************************************
124 ** Function bta_gattc_display_explore_record
126 ** Description debug function to display the exploration list
130 *******************************************************************************/
131 static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
134 tBTA_GATTC_ATTR_REC *pp = p_rec;
136 APPL_TRACE_ERROR("<================Start Explore Queue =============>");
137 for (i = 0; i < num_rec; i ++, pp ++)
139 APPL_TRACE_ERROR("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
140 i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
142 APPL_TRACE_ERROR("<================ End Explore Queue =============>");
143 APPL_TRACE_ERROR(" ");
146 #endif /* BTA_GATT_DEBUG == TRUE */
148 /*******************************************************************************
150 ** Function bta_gattc_init_cache
152 ** Description Initialize the database cache and discovery related resources.
156 *******************************************************************************/
157 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
159 if (p_srvc_cb->p_srvc_cache != NULL) {
160 list_free(p_srvc_cb->p_srvc_cache);
161 p_srvc_cb->p_srvc_cache = NULL;
164 osi_free(p_srvc_cb->p_srvc_list);
165 p_srvc_cb->p_srvc_list =
166 (tBTA_GATTC_ATTR_REC *)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE);
167 p_srvc_cb->total_srvc = 0;
168 p_srvc_cb->cur_srvc_idx = 0;
169 p_srvc_cb->cur_char_idx = 0;
170 p_srvc_cb->next_avail_idx = 0;
172 p_srvc_cb->p_cur_srvc = NULL;
177 void service_free(void *ptr) {
178 tBTA_GATTC_CACHE *srvc = ptr;
181 list_free(srvc->p_attr);
186 /*******************************************************************************
188 ** Function bta_gattc_add_srvc_to_cache
190 ** Description Add a service into database cache.
194 *******************************************************************************/
195 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
196 UINT16 s_handle, UINT16 e_handle,
200 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
201 APPL_TRACE_DEBUG("Add a service into Service");
204 tBTA_GATTC_CACHE *p_new_srvc = osi_malloc(sizeof(tBTA_GATTC_CACHE));
206 /* update service information */
207 p_new_srvc->s_handle = s_handle;
208 p_new_srvc->e_handle = e_handle;
209 p_new_srvc->service_uuid.is_primary = is_primary;
210 memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
211 p_new_srvc->service_uuid.id.inst_id = s_handle;
212 p_new_srvc->p_attr = NULL;
214 p_srvc_cb->p_cur_srvc = p_new_srvc;
215 p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
217 if (p_srvc_cb->p_srvc_cache == NULL) {
218 p_srvc_cb->p_srvc_cache = list_new(service_free);
221 list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
224 /*******************************************************************************
226 ** Function bta_gattc_add_attr_to_cache
228 ** Description Add an attribute into database cache buffer.
232 *******************************************************************************/
233 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
237 tBTA_GATTC_ATTR_TYPE type)
239 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
240 APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__, bta_gattc_attr_type[type]);
241 APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
244 if (p_srvc_cb->p_cur_srvc == NULL) {
245 APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc before adding a service!");
246 return GATT_WRONG_STATE;
249 tBTA_GATTC_CACHE_ATTR *p_attr =
250 osi_malloc(sizeof(tBTA_GATTC_CACHE_ATTR));
252 p_attr->attr_handle = handle;
253 p_attr->attr_type = type;
254 p_attr->property = property;
255 memcpy(&p_attr->uuid, p_uuid, sizeof(tBT_UUID));
257 if (p_srvc_cb->p_cur_srvc->p_attr == NULL) {
258 p_srvc_cb->p_cur_srvc->p_attr = list_new(osi_free);
261 list_append(p_srvc_cb->p_cur_srvc->p_attr, p_attr);
263 if (type == BTA_GATTC_ATTR_TYPE_CHAR)
264 p_srvc_cb->p_cur_srvc->p_cur_char = list_back_node(p_srvc_cb->p_cur_srvc->p_attr);
269 /*******************************************************************************
271 ** Function bta_gattc_get_disc_range
273 ** Description get discovery stating and ending handle range.
277 *******************************************************************************/
278 void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
280 tBTA_GATTC_ATTR_REC *p_rec = NULL;
284 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
285 *p_s_hdl = p_rec->s_handle;
289 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
290 *p_s_hdl = p_rec->s_handle + 1;
293 *p_e_hdl = p_rec->e_handle;
294 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
295 APPL_TRACE_DEBUG("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle);
299 /*******************************************************************************
301 ** Function bta_gattc_discover_pri_service
303 ** Description Start primary service discovery
305 ** Returns status of the operation.
307 *******************************************************************************/
308 tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
311 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
312 tBTA_GATT_STATUS status = BTA_GATT_ERROR;
316 if (p_clcb->transport == BTA_TRANSPORT_LE)
317 status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
319 status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
324 /*******************************************************************************
326 ** Function bta_gattc_discover_procedure
328 ** Description Start a particular type of discovery procedure on server.
330 ** Returns status of the operation.
332 *******************************************************************************/
333 tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
336 tGATT_DISC_PARAM param;
337 BOOLEAN is_service = TRUE;
339 memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
341 if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID)
344 param.e_handle = 0xFFFF;
348 if (disc_type == GATT_DISC_CHAR_DSCPT)
351 bta_gattc_get_disc_range(p_server_cb, ¶m.s_handle, ¶m.e_handle, is_service);
353 if (param.s_handle > param.e_handle)
358 return GATTC_Discover (conn_id, disc_type, ¶m);
361 /*******************************************************************************
363 ** Function bta_gattc_start_disc_include_srvc
365 ** Description Start discovery for included service
367 ** Returns status of the operation.
369 *******************************************************************************/
370 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
372 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
374 /*******************************************************************************
376 ** Function bta_gattc_start_disc_char
378 ** Description Start discovery for characteristic
380 ** Returns status of the operation.
382 *******************************************************************************/
383 tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
385 p_srvc_cb->total_char = 0;
387 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
389 /*******************************************************************************
391 ** Function bta_gattc_start_disc_char_dscp
393 ** Description Start discovery for characteristic descriptor
397 *******************************************************************************/
398 void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
400 APPL_TRACE_DEBUG("starting discover characteristics descriptor");
402 if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0)
403 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
406 /*******************************************************************************
408 ** Function bta_gattc_explore_srvc
410 ** Description process the service discovery complete event
414 *******************************************************************************/
415 static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
417 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
418 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
420 APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
422 p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
426 APPL_TRACE_ERROR("unknown connection ID");
429 /* start expore a service if there is service not been explored */
430 if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc)
432 /* add the first service into cache */
433 if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
437 p_rec->is_primary) == 0)
439 /* start discovering included services */
440 bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
444 /* no service found at all, the end of server discovery*/
445 LOG_WARN(LOG_TAG, "%s no more services found", __func__);
447 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
448 bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
450 /* save cache to NV */
451 p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
453 if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
454 bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
457 bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
459 /*******************************************************************************
461 ** Function bta_gattc_incl_srvc_disc_cmpl
463 ** Description process the relationship discovery complete event
467 *******************************************************************************/
468 static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
470 p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
472 /* start discoverying characteristic */
473 bta_gattc_start_disc_char(conn_id, p_srvc_cb);
475 /*******************************************************************************
477 ** Function bta_gattc_char_disc_cmpl
479 ** Description process the characteristic discovery complete event
483 *******************************************************************************/
484 static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
486 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
488 /* if there are characteristic needs to be explored */
489 if (p_srvc_cb->total_char > 0)
491 /* add the first characteristic into cache */
492 bta_gattc_add_attr_to_cache (p_srvc_cb,
496 BTA_GATTC_ATTR_TYPE_CHAR);
498 /* start discoverying characteristic descriptor , if failed, disc for next char*/
499 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
501 else /* otherwise start with next service */
503 p_srvc_cb->cur_srvc_idx ++;
505 bta_gattc_explore_srvc (conn_id, p_srvc_cb);
508 /*******************************************************************************
510 ** Function bta_gattc_char_dscpt_disc_cmpl
512 ** Description process the char descriptor discovery complete event
516 *******************************************************************************/
517 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
519 tBTA_GATTC_ATTR_REC *p_rec = NULL;
521 if (-- p_srvc_cb->total_char > 0)
523 p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
524 /* add the next characteristic into cache */
525 bta_gattc_add_attr_to_cache (p_srvc_cb,
529 BTA_GATTC_ATTR_TYPE_CHAR);
531 /* start discoverying next characteristic for char descriptor */
532 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
535 /* all characteristic has been explored, start with next service if any */
537 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
538 APPL_TRACE_ERROR("all char has been explored");
540 p_srvc_cb->cur_srvc_idx ++;
541 bta_gattc_explore_srvc (conn_id, p_srvc_cb);
545 static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
546 UINT16 e_handle, tBT_UUID uuid)
548 tBTA_GATTC_ATTR_REC *p_rec = NULL;
550 BOOLEAN exist_srvc = FALSE;
553 if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle))
555 APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
560 for (i = 0; i < p_srvc_cb->next_avail_idx; i ++)
562 p_rec = p_srvc_cb->p_srvc_list + i;
564 /* a new service should not have any overlap with other service handle range */
565 if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle)
574 /*******************************************************************************
576 ** Function bta_gattc_add_srvc_to_list
578 ** Description Add a service into explore pending list
582 *******************************************************************************/
583 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
584 UINT16 s_handle, UINT16 e_handle,
585 tBT_UUID uuid, BOOLEAN is_primary)
587 tBTA_GATTC_ATTR_REC *p_rec = NULL;
588 tBTA_GATT_STATUS status = BTA_GATT_OK;
590 if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
592 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
594 APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x",
595 __func__, s_handle, uuid.uu.uuid16);
597 p_rec->s_handle = s_handle;
598 p_rec->e_handle = e_handle;
599 p_rec->is_primary = is_primary;
600 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
602 p_srvc_cb->total_srvc ++;
603 p_srvc_cb->next_avail_idx ++;
606 { /* allocate bigger buffer ?? */
607 status = GATT_DB_FULL;
609 APPL_TRACE_ERROR("service not added, no resources or wrong state");
613 /*******************************************************************************
615 ** Function bta_gattc_add_char_to_list
617 ** Description Add a characteristic into explore pending list
621 *******************************************************************************/
622 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
623 UINT16 decl_handle, UINT16 value_handle,
624 tBT_UUID uuid, UINT8 property)
626 tBTA_GATTC_ATTR_REC *p_rec = NULL;
627 tBTA_GATT_STATUS status = BTA_GATT_OK;
629 if (p_srvc_cb->p_srvc_list == NULL)
631 APPL_TRACE_ERROR("No service available, unexpected char discovery result");
632 status = BTA_GATT_INTERNAL_ERROR;
634 else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
637 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
639 p_srvc_cb->total_char ++;
641 p_rec->s_handle = value_handle;
642 p_rec->property = property;
643 p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
644 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
646 /* update the endind handle of pervious characteristic if available */
647 if (p_srvc_cb->total_char > 1)
650 p_rec->e_handle = decl_handle - 1;
652 p_srvc_cb->next_avail_idx ++;
656 APPL_TRACE_ERROR("char not added, no resources");
657 /* allocate bigger buffer ?? */
658 status = BTA_GATT_DB_FULL;
664 /*******************************************************************************
666 ** Function bta_gattc_sdp_callback
668 ** Description Process the discovery result from sdp
672 *******************************************************************************/
673 void bta_gattc_sdp_callback(UINT16 sdp_status, void* user_data)
675 tSDP_DISC_REC *p_sdp_rec = NULL;
676 tBT_UUID service_uuid;
677 tSDP_PROTOCOL_ELEM pe;
678 UINT16 start_handle = 0, end_handle = 0;
679 tBTA_GATTC_CB_DATA *cb_data = user_data;
680 tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
682 if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL)
686 /* find a service record, report it */
687 p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
690 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
693 if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
695 start_handle = (UINT16) pe.params[0];
696 end_handle = (UINT16) pe.params[1];
698 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
699 APPL_TRACE_EVENT("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
700 service_uuid.uu.uuid16, start_handle, end_handle);
703 if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle)&&
706 /* discover services result, add services into a service list */
707 bta_gattc_add_srvc_to_list(p_srvc_cb,
715 APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
716 start_handle, end_handle);
726 if ( p_srvc_cb != NULL)
728 /* start discover primary service */
729 bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
733 APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
736 /* both were allocated in bta_gattc_sdp_service_disc */
737 osi_free(cb_data->p_sdp_db);
740 /*******************************************************************************
742 ** Function bta_gattc_sdp_service_disc
744 ** Description Start DSP Service Discovert
748 *******************************************************************************/
749 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
752 UINT16 num_attrs = 2;
755 memset (&uuid, 0, sizeof(tSDP_UUID));
757 uuid.len = LEN_UUID_16;
758 uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
761 * On success, cb_data will be freed inside bta_gattc_sdp_callback,
762 * otherwise it will be freed within this function.
764 tBTA_GATTC_CB_DATA *cb_data =
765 (tBTA_GATTC_CB_DATA *)osi_malloc(sizeof(tBTA_GATTC_CB_DATA));
767 cb_data->p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(BTA_GATT_SDP_DB_SIZE);
768 attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
769 attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
771 SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
772 &uuid, num_attrs, attr_list);
774 if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda,
775 cb_data->p_sdp_db, &bta_gattc_sdp_callback, cb_data))
777 osi_free(cb_data->p_sdp_db);
779 return BTA_GATT_ERROR;
782 cb_data->sdp_conn_id = conn_id;
785 /*******************************************************************************
787 ** Function bta_gattc_disc_res_cback
788 ** bta_gattc_disc_cmpl_cback
790 ** Description callback functions to GATT client stack.
794 *******************************************************************************/
795 void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
797 tBTA_GATTC_SERV * p_srvc_cb = NULL;
799 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
801 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
803 if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST)
807 case GATT_DISC_SRVC_ALL:
808 /* discover services result, add services into a service list */
809 bta_gattc_add_srvc_to_list(p_srvc_cb,
811 p_data->value.group_value.e_handle,
812 p_data->value.group_value.service_type,
816 case GATT_DISC_SRVC_BY_UUID:
817 bta_gattc_add_srvc_to_list(p_srvc_cb,
819 p_data->value.group_value.e_handle,
820 p_data->value.group_value.service_type,
824 case GATT_DISC_INC_SRVC:
825 /* add included service into service list if it's secondary or it never showed up
826 in the primary service search */
827 pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
828 p_data->value.incl_service.s_handle,
829 p_data->value.incl_service.e_handle,
830 p_data->value.incl_service.service_type);
833 bta_gattc_add_srvc_to_list(p_srvc_cb,
834 p_data->value.incl_service.s_handle,
835 p_data->value.incl_service.e_handle,
836 p_data->value.incl_service.service_type,
838 /* add into database */
839 bta_gattc_add_attr_to_cache(p_srvc_cb,
841 &p_data->value.incl_service.service_type,
843 BTA_GATTC_ATTR_TYPE_INCL_SRVC);
847 /* add char value into database */
848 bta_gattc_add_char_to_list(p_srvc_cb,
850 p_data->value.dclr_value.val_handle,
851 p_data->value.dclr_value.char_uuid,
852 p_data->value.dclr_value.char_prop);
855 case GATT_DISC_CHAR_DSCPT:
856 bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
857 BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
862 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
864 tBTA_GATTC_SERV * p_srvc_cb;
865 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
867 if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
869 if (status == GATT_SUCCESS)
870 p_clcb->status = status;
871 bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
874 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
876 if (p_srvc_cb != NULL)
880 case GATT_DISC_SRVC_ALL:
881 case GATT_DISC_SRVC_BY_UUID:
882 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
883 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
885 bta_gattc_explore_srvc(conn_id, p_srvc_cb);
888 case GATT_DISC_INC_SRVC:
889 bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
894 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
895 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
897 bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
900 case GATT_DISC_CHAR_DSCPT:
901 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
907 /*******************************************************************************
909 ** Function bta_gattc_handle2id
911 ** Description map a handle to GATT ID in a given cache.
913 ** Returns FALSE if map can not be found.
915 *******************************************************************************/
917 BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
918 tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
921 tBTA_GATTC_CACHE_ATTR *p_char = NULL;
923 memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
924 memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
925 memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
927 if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
930 for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
931 sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
932 tBTA_GATTC_CACHE *p_cache = list_node(sn);
934 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
935 APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x]",
936 p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16);
938 /* a service found */
939 if (p_cache->s_handle == handle) {
940 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
944 if (!p_cache->p_attr || list_is_empty(p_cache->p_attr))
947 for (list_node_t *an = list_begin(p_cache->p_attr);
948 an != list_end(p_cache->p_attr); an = list_next(an)) {
949 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
950 /* start looking for attributes within the service */
952 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
953 APPL_TRACE_DEBUG("\t Attr handle[0x%04x] uuid[0x%04x] type[%d]",
954 p_attr->attr_handle, p_attr->uuid.uu.uuid16,
957 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
960 if (handle == p_attr->attr_handle) {
961 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
963 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
964 memcpy(&p_descr_type->uuid, &p_attr->uuid, sizeof(tBT_UUID));
965 p_descr_type->inst_id = p_attr->attr_handle;
967 if (p_char != NULL) {
968 memcpy(&p_char_id->uuid, &p_char->uuid, sizeof(tBT_UUID));
969 p_char_id->inst_id = p_char->attr_handle;
971 APPL_TRACE_ERROR("descptr does not belong to any chracteristic");
974 /* is a characterisitc value or included service */
975 memcpy(&p_char_id->uuid, &p_attr->uuid, sizeof(tBT_UUID));
976 p_char_id->inst_id =p_attr->attr_handle;
986 /*******************************************************************************
988 ** Function bta_gattc_search_service
990 ** Description search local cache for matching service record.
992 ** Returns FALSE if map can not be found.
994 *******************************************************************************/
995 void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
999 if (!p_clcb->p_srcb->p_srvc_cache || list_is_empty(p_clcb->p_srcb->p_srvc_cache))
1002 for (list_node_t *sn = list_begin(p_clcb->p_srcb->p_srvc_cache);
1003 sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) {
1004 tBTA_GATTC_CACHE *p_cache = list_node(sn);
1006 if (!bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE))
1009 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1010 APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
1011 p_cache->service_uuid.id.uuid.uu.uuid16,
1012 p_cache->service_uuid.id.inst_id,
1015 if (!p_clcb->p_rcb->p_cback)
1018 memset(&cb_data, 0, sizeof(tBTA_GATTC));
1020 cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
1021 memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid,
1022 sizeof(tBTA_GATT_SRVC_ID));
1024 (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
1027 /*******************************************************************************
1029 ** Function bta_gattc_find_record
1031 ** Description search local cache for matching attribute record.
1033 ** Parameter p_result: output parameter to store the characteristic/
1034 ** included service GATT ID.
1036 ** Returns GATT_ERROR is no recording found. BTA_GATT_OK if record found.
1038 *******************************************************************************/
1039 static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
1040 tBTA_GATTC_ATTR_TYPE attr_type,
1041 tBTA_GATT_SRVC_ID *p_service_id,
1042 tBTA_GATT_ID *p_start_rec,
1043 tBT_UUID * p_uuid_cond,
1044 tBTA_GATT_ID *p_result,
1047 tBTA_GATT_STATUS status = BTA_GATT_ERROR;
1048 BOOLEAN char_found = FALSE, descr_found = FALSE;
1049 tBTA_GATT_ID *p_descr_id = (tBTA_GATT_ID *)p_param;;
1051 if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
1054 for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
1055 sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
1056 tBTA_GATTC_CACHE *p_cache = list_node(sn);
1058 if (status == BTA_GATT_OK)
1061 if (!bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
1064 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1065 APPL_TRACE_DEBUG("found matching service [0x%04x], inst[%d]",
1066 p_cache->service_uuid.id.uuid.uu.uuid16,
1067 p_cache->service_uuid.id.inst_id);
1069 if (!p_cache->p_attr || list_is_empty(p_cache->p_attr))
1072 for (list_node_t *an = list_begin(p_cache->p_attr);
1073 an != list_end(p_cache->p_attr); an = list_next(an)) {
1074 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1076 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1077 APPL_TRACE_DEBUG("\t Attr handle[0x%04x] uuid[0x%04x] type[%d]",
1078 p_attr->attr_handle,
1079 p_attr->uuid.uu.uuid16,
1082 memcpy(&p_result->uuid, &p_attr->uuid, sizeof(tBT_UUID));
1084 if (p_start_rec != NULL && char_found == FALSE) {
1085 /* find the starting record first */
1086 if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
1087 p_start_rec->inst_id == p_attr->attr_handle &&
1088 (attr_type == p_attr->attr_type ||
1089 /* find descriptor would look for characteristic first */
1090 (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
1091 p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
1094 /* if looking for descriptor, here is the where the descrptor to be found */
1095 if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
1096 /* next characeteristic already, return error */
1097 if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
1100 /* find starting descriptor */
1101 if (p_descr_id != NULL && !descr_found) {
1102 if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
1103 && p_descr_id->inst_id == p_attr->attr_handle)
1106 /* with matching descriptor */
1107 if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE))
1109 p_result->inst_id = p_attr->attr_handle;
1110 status = BTA_GATT_OK;
1115 if (!bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) ||
1116 attr_type != p_attr->attr_type)
1119 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1120 APPL_TRACE_DEBUG("found char handle mapping characteristic");
1122 p_result->inst_id = p_attr->attr_handle;
1124 if (p_param != NULL && (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
1125 attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC))
1126 *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
1128 status = BTA_GATT_OK;
1133 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1135 APPL_TRACE_ERROR("In the given service, can not find matching record");
1141 /*******************************************************************************
1143 ** Function bta_gattc_query_cache
1145 ** Description search local cache for matching attribute record.
1147 ** Parameters conn_id: connection ID which identify the server.
1148 ** p_srvc_id: the service ID of which the characteristic is belonged to.
1149 ** *p_start_rec: start the search from the next record
1150 ** after the one identified by *p_start_rec.
1151 ** p_uuid_cond: UUID, if NULL find the first available
1152 ** characteristic/included service.
1153 ** p_output: output parameter which will store the GATT ID
1154 ** of the characteristic /included service found.
1156 ** Returns BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
1158 *******************************************************************************/
1159 tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
1160 tBTA_GATTC_ATTR_TYPE query_type,
1161 tBTA_GATT_SRVC_ID *p_srvc_id,
1162 tBTA_GATT_ID *p_start_rec,
1163 tBT_UUID *p_uuid_cond,
1164 tBTA_GATT_ID *p_output,
1167 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1168 tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
1170 if (p_clcb != NULL )
1172 if (p_clcb->state == BTA_GATTC_CONN_ST)
1174 if (p_clcb->p_srcb &&
1175 !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
1176 p_clcb->p_srcb->p_srvc_cache)
1178 status = bta_gattc_find_record(p_clcb->p_srcb,
1188 status = BTA_GATT_ERROR;
1189 APPL_TRACE_ERROR("No server cache available");
1194 APPL_TRACE_ERROR("server cache not available, CLCB state = %d", p_clcb->state);
1196 status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
1201 APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
1207 /*******************************************************************************
1209 ** Function bta_gattc_fill_gatt_db_el
1211 ** Description fill a btgatt_db_element_t value
1215 *******************************************************************************/
1216 void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr,
1217 bt_gatt_db_attribute_type_t type,
1219 UINT16 s_handle, UINT16 e_handle,
1220 UINT8 id, tBT_UUID uuid, UINT8 prop)
1222 p_attr->type = type;
1223 p_attr->attribute_handle = att_handle;
1224 p_attr->start_handle = s_handle;
1225 p_attr->end_handle = e_handle;
1227 p_attr->properties = prop;
1228 bta_to_btif_uuid(&p_attr->uuid, &uuid);
1231 /*******************************************************************************
1232 ** Returns number of elements inside db from start_handle to end_handle
1233 *******************************************************************************/
1234 static size_t bta_gattc_get_db_size(list_t *services,
1235 UINT16 start_handle, UINT16 end_handle) {
1236 if (!services || list_is_empty(services))
1241 for (list_node_t *sn = list_begin(services);
1242 sn != list_end(services); sn = list_next(sn)) {
1243 tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
1245 if (p_cur_srvc->s_handle < start_handle)
1248 if (p_cur_srvc->e_handle > end_handle)
1252 if (p_cur_srvc->p_attr)
1253 db_size += list_length(p_cur_srvc->p_attr);
1259 /*******************************************************************************
1261 ** Function bta_gattc_get_gatt_db_impl
1263 ** Description copy the server GATT database into db parameter.
1265 ** Parameters p_srvc_cb: server.
1266 ** db: output parameter which will contain GATT database copy.
1267 ** Caller is responsible for freeing it.
1268 ** count: output parameter which will contain number of
1269 ** elements in database.
1273 *******************************************************************************/
1274 static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
1275 UINT16 start_handle, UINT16 end_handle,
1276 btgatt_db_element_t **db,
1279 APPL_TRACE_DEBUG(LOG_TAG, "%s", __func__);
1281 if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
1287 size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, start_handle, end_handle);
1289 void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
1290 btgatt_db_element_t *curr_db_attr = buffer;
1292 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
1293 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1294 tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
1296 if (p_cur_srvc->s_handle < start_handle)
1299 if (p_cur_srvc->e_handle > end_handle)
1302 bta_gattc_fill_gatt_db_el(curr_db_attr,
1303 p_cur_srvc->service_uuid.is_primary ?
1304 BTGATT_DB_PRIMARY_SERVICE :
1305 BTGATT_DB_SECONDARY_SERVICE,
1307 p_cur_srvc->s_handle,
1308 p_cur_srvc->e_handle,
1309 p_cur_srvc->s_handle,
1310 p_cur_srvc->service_uuid.id.uuid,
1314 if (!p_cur_srvc->p_attr || list_is_empty(p_cur_srvc->p_attr))
1317 for (list_node_t *an = list_begin(p_cur_srvc->p_attr);
1318 an != list_end(p_cur_srvc->p_attr); an = list_next(an)) {
1319 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1321 bt_gatt_db_attribute_type_t type;
1322 switch (p_attr->attr_type)
1324 case BTA_GATTC_ATTR_TYPE_CHAR:
1325 type = BTGATT_DB_CHARACTERISTIC;
1328 case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
1329 type = BTGATT_DB_DESCRIPTOR;
1332 case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
1333 type = BTGATT_DB_INCLUDED_SERVICE;
1337 LOG_ERROR(LOG_TAG, "%s unknown gatt db attribute type: %d",
1338 __func__, p_attr->attr_type);
1342 bta_gattc_fill_gatt_db_el(curr_db_attr,
1344 p_attr->attr_handle,
1347 p_attr->attr_handle,
1358 /*******************************************************************************
1360 ** Function bta_gattc_get_gatt_db
1362 ** Description copy the server GATT database into db parameter.
1364 ** Parameters conn_id: connection ID which identify the server.
1365 ** db: output parameter which will contain GATT database copy.
1366 ** Caller is responsible for freeing it.
1367 ** count: number of elements in database.
1371 *******************************************************************************/
1372 void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, int *count)
1374 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1376 LOG_DEBUG(LOG_TAG, "%s", __func__);
1377 if (p_clcb == NULL) {
1378 APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
1382 if (p_clcb->state != BTA_GATTC_CONN_ST) {
1383 APPL_TRACE_ERROR("server cache not available, CLCB state = %d",
1388 if (!p_clcb->p_srcb || p_clcb->p_srcb->p_srvc_list || /* no active discovery */
1389 !p_clcb->p_srcb->p_srvc_cache) {
1390 APPL_TRACE_ERROR("No server cache available");
1393 bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db, count);
1396 /*******************************************************************************
1398 ** Function bta_gattc_rebuild_cache
1400 ** Description rebuild server cache from NV cache.
1406 *******************************************************************************/
1407 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
1408 tBTA_GATTC_NV_ATTR *p_attr)
1410 /* first attribute loading, initialize buffer */
1411 APPL_TRACE_ERROR("%s: bta_gattc_rebuild_cache", __func__);
1413 list_free(p_srvc_cb->p_srvc_cache);
1414 p_srvc_cb->p_srvc_cache = NULL;
1415 p_srvc_cb->p_cur_srvc = NULL;
1417 while (num_attr > 0 && p_attr != NULL)
1419 switch (p_attr->attr_type)
1421 case BTA_GATTC_ATTR_TYPE_SRVC:
1422 bta_gattc_add_srvc_to_cache(p_srvc_cb,
1426 p_attr->is_primary);
1429 case BTA_GATTC_ATTR_TYPE_CHAR:
1430 case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
1431 case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
1432 bta_gattc_add_attr_to_cache(p_srvc_cb,
1444 /*******************************************************************************
1446 ** Function bta_gattc_fill_nv_attr
1448 ** Description fill a NV attribute entry value
1452 *******************************************************************************/
1453 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
1454 UINT16 e_handle, tBT_UUID uuid, UINT8 prop,
1457 p_attr->s_handle = s_handle;
1458 p_attr->e_handle = e_handle;
1459 p_attr->attr_type = type;
1460 p_attr->is_primary = is_primary;
1462 p_attr->prop = prop;
1464 memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
1467 /*******************************************************************************
1469 ** Function bta_gattc_cache_save
1471 ** Description save the server cache into NV
1475 *******************************************************************************/
1476 void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
1478 if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache))
1482 size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, 0x0000, 0xFFFF);
1483 tBTA_GATTC_NV_ATTR *nv_attr = osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR));
1485 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
1486 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1487 tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
1489 bta_gattc_fill_nv_attr(&nv_attr[i++],
1490 BTA_GATTC_ATTR_TYPE_SRVC,
1491 p_cur_srvc->s_handle,
1492 p_cur_srvc->e_handle,
1493 p_cur_srvc->service_uuid.id.uuid,
1495 p_cur_srvc->service_uuid.is_primary);
1497 if (!p_cur_srvc->p_attr || list_is_empty(p_cur_srvc->p_attr))
1500 for (list_node_t *an = list_begin(p_cur_srvc->p_attr);
1501 an != list_end(p_cur_srvc->p_attr); an = list_next(an)) {
1502 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1504 bta_gattc_fill_nv_attr(&nv_attr[i++],
1506 p_attr->attr_handle,
1514 bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr);
1518 /*******************************************************************************
1520 ** Function bta_gattc_cache_load
1522 ** Description Load GATT cache from storage for server.
1524 ** Parameter p_clcb: pointer to server clcb, that will
1525 ** be filled from storage
1526 ** Returns true on success, false otherwise
1528 *******************************************************************************/
1529 bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb)
1531 char fname[255] = {0};
1532 bta_gattc_generate_cache_file_name(fname, p_clcb->p_srcb->server_bda);
1534 FILE *fd = fopen(fname, "rb");
1536 APPL_TRACE_ERROR("%s: can't open GATT cache file %s for reading, error: %s",
1537 __func__, fname, strerror(errno));
1541 UINT16 cache_ver = 0;
1542 tBTA_GATTC_NV_ATTR *attr = NULL;
1543 bool success = false;
1545 if (fread(&cache_ver, sizeof(UINT16), 1, fd) != 1) {
1546 APPL_TRACE_ERROR("%s: can't read GATT cache version from: %s", __func__, fname);
1550 if (cache_ver != GATT_CACHE_VERSION) {
1551 APPL_TRACE_ERROR("%s: wrong GATT cache version: %s", __func__, fname);
1555 UINT16 num_attr = 0;
1557 if (fread(&num_attr, sizeof(UINT16), 1, fd) != 1) {
1558 APPL_TRACE_ERROR("%s: can't read number of GATT attributes: %s", __func__, fname);
1562 attr = osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr);
1564 if (fread(attr, sizeof(tBTA_GATTC_NV_ATTR), 0xFF, fd) != num_attr) {
1565 APPL_TRACE_ERROR("%s: can't read GATT attributes: %s", __func__, fname);
1569 bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr);
1579 /*******************************************************************************
1581 ** Function bta_gattc_cache_write
1583 ** Description This callout function is executed by GATT when a server cache
1584 ** is available to save.
1586 ** Parameter server_bda: server bd address of this cache belongs to
1587 ** num_attr: number of attribute to be save.
1588 ** attr: pointer to the list of attributes to save.
1591 *******************************************************************************/
1592 static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr,
1593 tBTA_GATTC_NV_ATTR *attr)
1595 char fname[255] = {0};
1596 bta_gattc_generate_cache_file_name(fname, server_bda);
1598 FILE *fd = fopen(fname, "wb");
1600 APPL_TRACE_ERROR("%s: can't open GATT cache file for writing: %s", __func__, fname);
1604 UINT16 cache_ver = GATT_CACHE_VERSION;
1605 if (fwrite(&cache_ver, sizeof(UINT16), 1, fd) != 1) {
1606 APPL_TRACE_ERROR("%s: can't write GATT cache version: %s", __func__, fname);
1611 if (fwrite(&num_attr, sizeof(UINT16), 1, fd) != 1) {
1612 APPL_TRACE_ERROR("%s: can't write GATT cache attribute count: %s", __func__, fname);
1617 if (fwrite(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
1618 APPL_TRACE_ERROR("%s: can't write GATT cache attributes: %s", __func__, fname);
1626 /*******************************************************************************
1628 ** Function bta_gattc_cache_reset
1630 ** Description This callout function is executed by GATTC to reset cache in
1633 ** Parameter server_bda: server bd address of this cache belongs to
1637 *******************************************************************************/
1638 void bta_gattc_cache_reset(BD_ADDR server_bda)
1640 BTIF_TRACE_DEBUG("%s", __func__);
1641 char fname[255] = {0};
1642 bta_gattc_generate_cache_file_name(fname, server_bda);
1645 #endif /* BTA_GATT_INCLUDED */