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)
34 #include "bta_gattc_int.h"
37 #include "btm_ble_api.h"
38 #include "bt_common.h"
39 #include "osi/include/log.h"
44 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
45 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
46 extern void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
48 #define BTA_GATT_SDP_DB_SIZE 4096
50 /*****************************************************************************
51 ** Constants and data types
52 *****************************************************************************/
56 tSDP_DISCOVERY_DB *p_sdp_db;
60 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
61 static char *bta_gattc_attr_type[] =
63 "I", /* Included Service */
64 "C", /* Characteristic */
65 "D" /* Characteristic Descriptor */
67 /* utility functions */
69 bool display_cache_attribute(void *data, void *context) {
70 tBTA_GATTC_CACHE_ATTR *p_attr = data;
71 APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]",
72 p_attr->attr_handle, p_attr->uuid.uu.uuid16, p_attr->inst_id,
73 bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
77 bool display_cache_service(void *data, void *context) {
78 tBTA_GATTC_CACHE *p_cur_srvc = data;
79 APPL_TRACE_ERROR("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]",
80 p_cur_srvc->s_handle, p_cur_srvc->e_handle,
81 ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
82 p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
83 p_cur_srvc->service_uuid.id.inst_id);
85 if (p_cur_srvc->p_attr != NULL) {
86 list_foreach(p_cur_srvc->p_attr, display_cache_attribute, NULL);
92 /*******************************************************************************
94 ** Function bta_gattc_display_cache_server
96 ** Description debug function to display the server cache.
100 *******************************************************************************/
101 static void bta_gattc_display_cache_server(list_t *p_cache)
103 APPL_TRACE_ERROR("<================Start Server Cache =============>");
104 list_foreach(p_cache, display_cache_service, NULL);
105 APPL_TRACE_ERROR("<================End Server Cache =============>");
106 APPL_TRACE_ERROR(" ");
109 /*******************************************************************************
111 ** Function bta_gattc_display_explore_record
113 ** Description debug function to display the exploration list
117 *******************************************************************************/
118 static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
121 tBTA_GATTC_ATTR_REC *pp = p_rec;
123 APPL_TRACE_ERROR("<================Start Explore Queue =============>");
124 for (i = 0; i < num_rec; i ++, pp ++)
126 APPL_TRACE_ERROR("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
127 i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
129 APPL_TRACE_ERROR("<================ End Explore Queue =============>");
130 APPL_TRACE_ERROR(" ");
133 #endif /* BTA_GATT_DEBUG == TRUE */
135 /*******************************************************************************
137 ** Function bta_gattc_init_cache
139 ** Description Initialize the database cache and discovery related resources.
143 *******************************************************************************/
144 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
146 if (p_srvc_cb->p_srvc_cache != NULL) {
147 list_free(p_srvc_cb->p_srvc_cache);
148 p_srvc_cb->p_srvc_cache = NULL;
151 osi_free(p_srvc_cb->p_srvc_list);
152 p_srvc_cb->p_srvc_list =
153 (tBTA_GATTC_ATTR_REC *)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE);
154 p_srvc_cb->total_srvc = 0;
155 p_srvc_cb->cur_srvc_idx = 0;
156 p_srvc_cb->cur_char_idx = 0;
157 p_srvc_cb->next_avail_idx = 0;
159 p_srvc_cb->p_cur_srvc = NULL;
163 /*******************************************************************************
165 ** Function bta_gattc_get_srvc_inst_id
167 ** Description get service instance number
169 ** Returns instance ID of the service.
171 *******************************************************************************/
172 static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid)
174 UINT8 i = 0, inst = 0;
175 tBTA_GATTC_ATTR_REC *p_srvc_rec;
177 for (i = 0; i < p_srvc_cb->total_srvc; i ++)
179 for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/
181 p_srvc_rec = p_srvc_cb->p_srvc_list + i;
183 if (bta_gattc_uuid_compare(&p_srvc_rec->uuid, &uuid, TRUE))
188 /*******************************************************************************
190 ** Function bta_gattc_get_char_inst_id
192 ** Description get characteristic instance number
194 ** Returns characteristic instance ID.
196 *******************************************************************************/
197 static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID *p_uuid)
201 if (!p_service_cache->p_attr || list_is_empty(p_service_cache->p_attr))
204 for (list_node_t *an = list_begin(p_service_cache->p_attr);
205 an != list_end(p_service_cache->p_attr); an = list_next(an)) {
206 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
208 if (bta_gattc_uuid_compare(&p_attr->uuid, p_uuid, TRUE))
215 /*******************************************************************************
217 ** Function bta_gattc_get_char_descr_inst_id
219 ** Description get characteristic descriptor instance number
221 ** Returns characteristic instance ID.
223 *******************************************************************************/
224 static UINT8 bta_gattc_get_char_descr_inst_id(list_node_t *p_char_attr, tBT_UUID *p_uuid)
228 if (p_char_attr != NULL)
229 p_char_attr = list_next(p_char_attr);
233 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(p_char_attr);
235 if (bta_gattc_uuid_compare(&p_attr->uuid, p_uuid, TRUE))
238 p_char_attr = list_next(p_char_attr);
243 void service_free(void *ptr) {
244 tBTA_GATTC_CACHE *srvc = ptr;
247 list_free(srvc->p_attr);
252 /*******************************************************************************
254 ** Function bta_gattc_add_srvc_to_cache
256 ** Description Add a service into database cache.
260 *******************************************************************************/
261 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
262 UINT16 s_handle, UINT16 e_handle,
264 BOOLEAN is_primary, UINT8 srvc_inst)
266 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
267 APPL_TRACE_DEBUG("Add a service into Service");
270 tBTA_GATTC_CACHE *p_new_srvc = osi_malloc(sizeof(tBTA_GATTC_CACHE));
272 /* update service information */
273 p_new_srvc->s_handle = s_handle;
274 p_new_srvc->e_handle = e_handle;
275 p_new_srvc->service_uuid.is_primary = is_primary;
276 memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
277 p_new_srvc->service_uuid.id.inst_id = srvc_inst;
278 p_new_srvc->p_attr = NULL;
280 p_srvc_cb->p_cur_srvc = p_new_srvc;
281 p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
283 if (p_srvc_cb->p_srvc_cache == NULL) {
284 p_srvc_cb->p_srvc_cache = list_new(service_free);
287 list_append(p_srvc_cb->p_srvc_cache, p_new_srvc);
290 /*******************************************************************************
292 ** Function bta_gattc_add_attr_to_cache
294 ** Description Add an attribute into database cache buffer.
298 *******************************************************************************/
299 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
303 tBTA_GATTC_ATTR_TYPE type)
305 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
306 APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__, bta_gattc_attr_type[type]);
307 APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
310 if (p_srvc_cb->p_cur_srvc == NULL) {
311 APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc before adding a service!");
312 return GATT_WRONG_STATE;
315 tBTA_GATTC_CACHE_ATTR *p_attr =
316 osi_malloc(sizeof(tBTA_GATTC_CACHE_ATTR));
318 p_attr->attr_handle = handle;
319 p_attr->attr_type = type;
320 p_attr->property = property;
321 memcpy(&p_attr->uuid, p_uuid, sizeof(tBT_UUID));
323 if (type == BTA_GATTC_ATTR_TYPE_CHAR) {
324 p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, p_uuid);
325 } else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
326 p_attr->inst_id = bta_gattc_get_char_descr_inst_id(p_srvc_cb->p_cur_srvc->p_cur_char, p_uuid);
327 } else { /* TODO: --->> temp treat included service as single instance */
331 if (p_srvc_cb->p_cur_srvc->p_attr == NULL) {
332 p_srvc_cb->p_cur_srvc->p_attr = list_new(osi_free);
335 list_append(p_srvc_cb->p_cur_srvc->p_attr, p_attr);
337 if (type == BTA_GATTC_ATTR_TYPE_CHAR)
338 p_srvc_cb->p_cur_srvc->p_cur_char = list_back_node(p_srvc_cb->p_cur_srvc->p_attr);
343 /*******************************************************************************
345 ** Function bta_gattc_get_disc_range
347 ** Description get discovery stating and ending handle range.
351 *******************************************************************************/
352 void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
354 tBTA_GATTC_ATTR_REC *p_rec = NULL;
358 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
359 *p_s_hdl = p_rec->s_handle;
363 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
364 *p_s_hdl = p_rec->s_handle + 1;
367 *p_e_hdl = p_rec->e_handle;
368 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
369 APPL_TRACE_DEBUG("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle);
373 /*******************************************************************************
375 ** Function bta_gattc_discover_pri_service
377 ** Description Start primary service discovery
379 ** Returns status of the operation.
381 *******************************************************************************/
382 tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
385 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
386 tBTA_GATT_STATUS status = BTA_GATT_ERROR;
390 if (p_clcb->transport == BTA_TRANSPORT_LE)
391 status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
393 status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
398 /*******************************************************************************
400 ** Function bta_gattc_discover_procedure
402 ** Description Start a particular type of discovery procedure on server.
404 ** Returns status of the operation.
406 *******************************************************************************/
407 tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
410 tGATT_DISC_PARAM param;
411 BOOLEAN is_service = TRUE;
413 memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
415 if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID)
418 param.e_handle = 0xFFFF;
422 if (disc_type == GATT_DISC_CHAR_DSCPT)
425 bta_gattc_get_disc_range(p_server_cb, ¶m.s_handle, ¶m.e_handle, is_service);
427 if (param.s_handle > param.e_handle)
432 return GATTC_Discover (conn_id, disc_type, ¶m);
435 /*******************************************************************************
437 ** Function bta_gattc_start_disc_include_srvc
439 ** Description Start discovery for included service
441 ** Returns status of the operation.
443 *******************************************************************************/
444 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
446 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
448 /*******************************************************************************
450 ** Function bta_gattc_start_disc_char
452 ** Description Start discovery for characteristic
454 ** Returns status of the operation.
456 *******************************************************************************/
457 tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
459 p_srvc_cb->total_char = 0;
461 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
463 /*******************************************************************************
465 ** Function bta_gattc_start_disc_char_dscp
467 ** Description Start discovery for characteristic descriptor
471 *******************************************************************************/
472 void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
474 APPL_TRACE_DEBUG("starting discover characteristics descriptor");
476 if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0)
477 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
480 /*******************************************************************************
482 ** Function bta_gattc_explore_srvc
484 ** Description process the service discovery complete event
488 *******************************************************************************/
489 static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
491 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
492 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
494 APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
496 p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
500 APPL_TRACE_ERROR("unknown connection ID");
503 /* start expore a service if there is service not been explored */
504 if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc)
506 /* add the first service into cache */
507 if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
512 p_rec->srvc_inst_id) == 0)
514 /* start discovering included services */
515 bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
519 /* no service found at all, the end of server discovery*/
520 LOG_WARN(LOG_TAG, "%s no more services found", __func__);
522 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
523 bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
525 /* save cache to NV */
526 p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
527 bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
530 /*******************************************************************************
532 ** Function bta_gattc_incl_srvc_disc_cmpl
534 ** Description process the relationship discovery complete event
538 *******************************************************************************/
539 static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
541 p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
543 /* start discoverying characteristic */
544 bta_gattc_start_disc_char(conn_id, p_srvc_cb);
546 /*******************************************************************************
548 ** Function bta_gattc_char_disc_cmpl
550 ** Description process the characteristic discovery complete event
554 *******************************************************************************/
555 static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
557 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
559 /* if there are characteristic needs to be explored */
560 if (p_srvc_cb->total_char > 0)
562 /* add the first characteristic into cache */
563 bta_gattc_add_attr_to_cache (p_srvc_cb,
567 BTA_GATTC_ATTR_TYPE_CHAR);
569 /* start discoverying characteristic descriptor , if failed, disc for next char*/
570 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
572 else /* otherwise start with next service */
574 p_srvc_cb->cur_srvc_idx ++;
576 bta_gattc_explore_srvc (conn_id, p_srvc_cb);
579 /*******************************************************************************
581 ** Function bta_gattc_char_dscpt_disc_cmpl
583 ** Description process the char descriptor discovery complete event
587 *******************************************************************************/
588 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
590 tBTA_GATTC_ATTR_REC *p_rec = NULL;
592 if (-- p_srvc_cb->total_char > 0)
594 p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
595 /* add the next characteristic into cache */
596 bta_gattc_add_attr_to_cache (p_srvc_cb,
600 BTA_GATTC_ATTR_TYPE_CHAR);
602 /* start discoverying next characteristic for char descriptor */
603 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
606 /* all characteristic has been explored, start with next service if any */
608 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
609 APPL_TRACE_ERROR("all char has been explored");
611 p_srvc_cb->cur_srvc_idx ++;
612 bta_gattc_explore_srvc (conn_id, p_srvc_cb);
616 static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
617 UINT16 e_handle, tBT_UUID uuid)
619 tBTA_GATTC_ATTR_REC *p_rec = NULL;
621 BOOLEAN exist_srvc = FALSE;
624 if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle))
626 APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
631 for (i = 0; i < p_srvc_cb->next_avail_idx; i ++)
633 p_rec = p_srvc_cb->p_srvc_list + i;
635 /* a new service should not have any overlap with other service handle range */
636 if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle)
645 /*******************************************************************************
647 ** Function bta_gattc_add_srvc_to_list
649 ** Description Add a service into explore pending list
653 *******************************************************************************/
654 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
655 UINT16 s_handle, UINT16 e_handle,
656 tBT_UUID uuid, BOOLEAN is_primary)
658 tBTA_GATTC_ATTR_REC *p_rec = NULL;
659 tBTA_GATT_STATUS status = BTA_GATT_OK;
661 if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
663 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
665 APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x",
666 __func__, s_handle, uuid.uu.uuid16);
668 p_rec->s_handle = s_handle;
669 p_rec->e_handle = e_handle;
670 p_rec->is_primary = is_primary;
671 p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid);
672 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
674 p_srvc_cb->total_srvc ++;
675 p_srvc_cb->next_avail_idx ++;
678 { /* allocate bigger buffer ?? */
679 status = GATT_DB_FULL;
681 APPL_TRACE_ERROR("service not added, no resources or wrong state");
685 /*******************************************************************************
687 ** Function bta_gattc_add_char_to_list
689 ** Description Add a characteristic into explore pending list
693 *******************************************************************************/
694 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
695 UINT16 decl_handle, UINT16 value_handle,
696 tBT_UUID uuid, UINT8 property)
698 tBTA_GATTC_ATTR_REC *p_rec = NULL;
699 tBTA_GATT_STATUS status = BTA_GATT_OK;
701 if (p_srvc_cb->p_srvc_list == NULL)
703 APPL_TRACE_ERROR("No service available, unexpected char discovery result");
704 status = BTA_GATT_INTERNAL_ERROR;
706 else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
709 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
711 p_srvc_cb->total_char ++;
713 p_rec->s_handle = value_handle;
714 p_rec->property = property;
715 p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
716 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
718 /* update the endind handle of pervious characteristic if available */
719 if (p_srvc_cb->total_char > 1)
722 p_rec->e_handle = decl_handle - 1;
724 p_srvc_cb->next_avail_idx ++;
728 APPL_TRACE_ERROR("char not added, no resources");
729 /* allocate bigger buffer ?? */
730 status = BTA_GATT_DB_FULL;
736 /*******************************************************************************
738 ** Function bta_gattc_sdp_callback
740 ** Description Process the discovery result from sdp
744 *******************************************************************************/
745 void bta_gattc_sdp_callback(UINT16 sdp_status, void* user_data)
747 tSDP_DISC_REC *p_sdp_rec = NULL;
748 tBT_UUID service_uuid;
749 tSDP_PROTOCOL_ELEM pe;
750 UINT16 start_handle = 0, end_handle = 0;
751 tBTA_GATTC_CB_DATA *cb_data = user_data;
752 tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
754 if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL)
758 /* find a service record, report it */
759 p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
762 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
765 if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
767 start_handle = (UINT16) pe.params[0];
768 end_handle = (UINT16) pe.params[1];
770 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
771 APPL_TRACE_EVENT("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
772 service_uuid.uu.uuid16, start_handle, end_handle);
775 if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle)&&
778 /* discover services result, add services into a service list */
779 bta_gattc_add_srvc_to_list(p_srvc_cb,
787 APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
788 start_handle, end_handle);
798 if ( p_srvc_cb != NULL)
800 /* start discover primary service */
801 bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
805 APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
808 /* both were allocated in bta_gattc_sdp_service_disc */
809 osi_free(cb_data->p_sdp_db);
812 /*******************************************************************************
814 ** Function bta_gattc_sdp_service_disc
816 ** Description Start DSP Service Discovert
820 *******************************************************************************/
821 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
824 UINT16 num_attrs = 2;
827 memset (&uuid, 0, sizeof(tSDP_UUID));
829 uuid.len = LEN_UUID_16;
830 uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
833 * On success, cb_data will be freed inside bta_gattc_sdp_callback,
834 * otherwise it will be freed within this function.
836 tBTA_GATTC_CB_DATA *cb_data =
837 (tBTA_GATTC_CB_DATA *)osi_malloc(sizeof(tBTA_GATTC_CB_DATA));
839 cb_data->p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(BTA_GATT_SDP_DB_SIZE);
840 attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
841 attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
843 SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
844 &uuid, num_attrs, attr_list);
846 if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda,
847 cb_data->p_sdp_db, &bta_gattc_sdp_callback, cb_data))
849 osi_free(cb_data->p_sdp_db);
851 return BTA_GATT_ERROR;
854 cb_data->sdp_conn_id = conn_id;
857 /*******************************************************************************
859 ** Function bta_gattc_disc_res_cback
860 ** bta_gattc_disc_cmpl_cback
862 ** Description callback functions to GATT client stack.
866 *******************************************************************************/
867 void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
869 tBTA_GATTC_SERV * p_srvc_cb = NULL;
871 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
873 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
875 if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST)
879 case GATT_DISC_SRVC_ALL:
880 /* discover services result, add services into a service list */
881 bta_gattc_add_srvc_to_list(p_srvc_cb,
883 p_data->value.group_value.e_handle,
884 p_data->value.group_value.service_type,
888 case GATT_DISC_SRVC_BY_UUID:
889 bta_gattc_add_srvc_to_list(p_srvc_cb,
891 p_data->value.group_value.e_handle,
892 p_data->value.group_value.service_type,
896 case GATT_DISC_INC_SRVC:
897 /* add included service into service list if it's secondary or it never showed up
898 in the primary service search */
899 pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
900 p_data->value.incl_service.s_handle,
901 p_data->value.incl_service.e_handle,
902 p_data->value.incl_service.service_type);
905 bta_gattc_add_srvc_to_list(p_srvc_cb,
906 p_data->value.incl_service.s_handle,
907 p_data->value.incl_service.e_handle,
908 p_data->value.incl_service.service_type,
910 /* add into database */
911 bta_gattc_add_attr_to_cache(p_srvc_cb,
913 &p_data->value.incl_service.service_type,
915 BTA_GATTC_ATTR_TYPE_INCL_SRVC);
919 /* add char value into database */
920 bta_gattc_add_char_to_list(p_srvc_cb,
922 p_data->value.dclr_value.val_handle,
923 p_data->value.dclr_value.char_uuid,
924 p_data->value.dclr_value.char_prop);
927 case GATT_DISC_CHAR_DSCPT:
928 bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
929 BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
934 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
936 tBTA_GATTC_SERV * p_srvc_cb;
937 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
939 if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
941 if (status == GATT_SUCCESS)
942 p_clcb->status = status;
943 bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
946 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
948 if (p_srvc_cb != NULL)
952 case GATT_DISC_SRVC_ALL:
953 case GATT_DISC_SRVC_BY_UUID:
954 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
955 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
957 bta_gattc_explore_srvc(conn_id, p_srvc_cb);
960 case GATT_DISC_INC_SRVC:
961 bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
966 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
967 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
969 bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
972 case GATT_DISC_CHAR_DSCPT:
973 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
978 /*******************************************************************************
980 ** Function bta_gattc_id2handle
982 ** Description map GATT ID to handle in a given cache.
984 ** Returns the handle mapped. 0 if not found.
986 *******************************************************************************/
987 UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
988 tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid)
991 BOOLEAN char_map = FALSE, done = FALSE;
993 if (!p_service_id || !p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
996 for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
997 sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
998 tBTA_GATTC_CACHE *p_cache = list_node(sn);
1003 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1004 APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
1005 p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
1006 p_cache->service_uuid.id.inst_id);
1008 if (!bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
1011 if (!p_cache->p_attr || list_is_empty(p_cache->p_attr))
1014 for (list_node_t *an = list_begin(p_cache->p_attr);
1015 an != list_end(p_cache->p_attr); an = list_next(an)) {
1016 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1018 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1019 APPL_TRACE_DEBUG("\t Attr handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
1020 p_attr->attr_handle, p_attr->uuid.uu.uuid16,
1021 p_attr->inst_id, p_attr->attr_type);
1024 if (bta_gattc_uuid_compare(&p_char_id->uuid, &p_attr->uuid, TRUE) &&
1025 p_char_id->inst_id == p_attr->inst_id) {
1026 if (p_descr_uuid == NULL) {
1027 handle = p_attr->attr_handle;
1031 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1032 APPL_TRACE_DEBUG("found matching characteristic for the descriptor");
1037 else if (char_map == TRUE) {
1038 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
1039 if (p_descr_uuid != NULL &&
1040 bta_gattc_uuid_compare(&p_descr_uuid->uuid, &p_attr->uuid, TRUE) &&
1041 p_descr_uuid->inst_id == p_attr->inst_id) {
1042 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1043 APPL_TRACE_DEBUG("found descriptor!!");
1045 handle = p_attr->attr_handle;
1049 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1050 APPL_TRACE_DEBUG("descriptor UUID not matching");
1055 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1056 APPL_TRACE_DEBUG("no matching descptr found!!start of next characteristic");
1068 /*******************************************************************************
1070 ** Function bta_gattc_handle2id
1072 ** Description map a handle to GATT ID in a given cache.
1074 ** Returns FALSE if map can not be found.
1076 *******************************************************************************/
1078 BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
1079 tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
1082 tBTA_GATTC_CACHE_ATTR *p_char = NULL;
1084 memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
1085 memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
1086 memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
1088 if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
1091 for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
1092 sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
1093 tBTA_GATTC_CACHE *p_cache = list_node(sn);
1095 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1096 APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
1097 p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
1098 p_cache->service_uuid.id.inst_id);
1100 /* a service found */
1101 if (p_cache->s_handle == handle) {
1102 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
1106 if (!p_cache->p_attr || list_is_empty(p_cache->p_attr))
1109 for (list_node_t *an = list_begin(p_cache->p_attr);
1110 an != list_end(p_cache->p_attr); an = list_next(an)) {
1111 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1112 /* start looking for attributes within the service */
1114 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1115 APPL_TRACE_DEBUG("\t Attr handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
1116 p_attr->attr_handle, p_attr->uuid.uu.uuid16,
1117 p_attr->inst_id, p_attr->attr_type);
1119 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
1122 if (handle == p_attr->attr_handle) {
1123 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
1125 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
1126 memcpy(&p_descr_type->uuid, &p_attr->uuid, sizeof(tBT_UUID));
1127 p_descr_type->inst_id = p_attr->inst_id;
1129 if (p_char != NULL) {
1130 memcpy(&p_char_id->uuid, &p_char->uuid, sizeof(tBT_UUID));
1131 p_char_id->inst_id = p_char->inst_id;
1133 APPL_TRACE_ERROR("descptr does not belong to any chracteristic");
1136 /* is a characterisitc value or included service */
1137 memcpy(&p_char_id->uuid, &p_attr->uuid, sizeof(tBT_UUID));
1138 p_char_id->inst_id =p_attr->inst_id;
1148 /*******************************************************************************
1150 ** Function bta_gattc_search_service
1152 ** Description search local cache for matching service record.
1154 ** Returns FALSE if map can not be found.
1156 *******************************************************************************/
1157 void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
1161 if (!p_clcb->p_srcb->p_srvc_cache || list_is_empty(p_clcb->p_srcb->p_srvc_cache))
1164 for (list_node_t *sn = list_begin(p_clcb->p_srcb->p_srvc_cache);
1165 sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) {
1166 tBTA_GATTC_CACHE *p_cache = list_node(sn);
1168 if (!bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE))
1171 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1172 APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
1173 p_cache->service_uuid.id.uuid.uu.uuid16,
1174 p_cache->service_uuid.id.inst_id,
1177 if (!p_clcb->p_rcb->p_cback)
1180 memset(&cb_data, 0, sizeof(tBTA_GATTC));
1182 cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
1183 memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid,
1184 sizeof(tBTA_GATT_SRVC_ID));
1186 (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
1189 /*******************************************************************************
1191 ** Function bta_gattc_find_record
1193 ** Description search local cache for matching attribute record.
1195 ** Parameter p_result: output parameter to store the characteristic/
1196 ** included service GATT ID.
1198 ** Returns GATT_ERROR is no recording found. BTA_GATT_OK if record found.
1200 *******************************************************************************/
1201 static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
1202 tBTA_GATTC_ATTR_TYPE attr_type,
1203 tBTA_GATT_SRVC_ID *p_service_id,
1204 tBTA_GATT_ID *p_start_rec,
1205 tBT_UUID * p_uuid_cond,
1206 tBTA_GATT_ID *p_result,
1209 tBTA_GATT_STATUS status = BTA_GATT_ERROR;
1210 BOOLEAN char_found = FALSE, descr_found = FALSE;
1211 tBTA_GATT_ID *p_descr_id = (tBTA_GATT_ID *)p_param;;
1213 if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
1216 for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
1217 sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
1218 tBTA_GATTC_CACHE *p_cache = list_node(sn);
1220 if (status == BTA_GATT_OK)
1223 if (!bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
1226 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1227 APPL_TRACE_DEBUG("found matching service [0x%04x], inst[%d]",
1228 p_cache->service_uuid.id.uuid.uu.uuid16,
1229 p_cache->service_uuid.id.inst_id);
1231 if (!p_cache->p_attr || list_is_empty(p_cache->p_attr))
1234 for (list_node_t *an = list_begin(p_cache->p_attr);
1235 an != list_end(p_cache->p_attr); an = list_next(an)) {
1236 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1238 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1239 APPL_TRACE_DEBUG("\t Attr handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
1240 p_attr->attr_handle,
1241 p_attr->uuid.uu.uuid16,
1245 memcpy(&p_result->uuid, &p_attr->uuid, sizeof(tBT_UUID));
1247 if (p_start_rec != NULL && char_found == FALSE) {
1248 /* find the starting record first */
1249 if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
1250 p_start_rec->inst_id == p_attr->inst_id &&
1251 (attr_type == p_attr->attr_type ||
1252 /* find descriptor would look for characteristic first */
1253 (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
1254 p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
1257 /* if looking for descriptor, here is the where the descrptor to be found */
1258 if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
1259 /* next characeteristic already, return error */
1260 if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
1263 /* find starting descriptor */
1264 if (p_descr_id != NULL && !descr_found) {
1265 if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
1266 && p_descr_id->inst_id == p_attr->inst_id)
1269 /* with matching descriptor */
1270 if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE))
1272 p_result->inst_id = p_attr->inst_id;
1273 status = BTA_GATT_OK;
1278 if (!bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) ||
1279 attr_type != p_attr->attr_type)
1282 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1283 APPL_TRACE_DEBUG("found char handle mapping characteristic");
1285 p_result->inst_id = p_attr->inst_id;
1287 if (p_param != NULL && (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
1288 attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC))
1289 *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
1291 status = BTA_GATT_OK;
1296 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1298 APPL_TRACE_ERROR("In the given service, can not find matching record");
1304 /*******************************************************************************
1306 ** Function bta_gattc_query_cache
1308 ** Description search local cache for matching attribute record.
1310 ** Parameters conn_id: connection ID which identify the server.
1311 ** p_srvc_id: the service ID of which the characteristic is belonged to.
1312 ** *p_start_rec: start the search from the next record
1313 ** after the one identified by *p_start_rec.
1314 ** p_uuid_cond: UUID, if NULL find the first available
1315 ** characteristic/included service.
1316 ** p_output: output parameter which will store the GATT ID
1317 ** of the characteristic /included service found.
1319 ** Returns BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
1321 *******************************************************************************/
1322 tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
1323 tBTA_GATTC_ATTR_TYPE query_type,
1324 tBTA_GATT_SRVC_ID *p_srvc_id,
1325 tBTA_GATT_ID *p_start_rec,
1326 tBT_UUID *p_uuid_cond,
1327 tBTA_GATT_ID *p_output,
1330 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1331 tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
1333 if (p_clcb != NULL )
1335 if (p_clcb->state == BTA_GATTC_CONN_ST)
1337 if (p_clcb->p_srcb &&
1338 !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
1339 p_clcb->p_srcb->p_srvc_cache)
1341 status = bta_gattc_find_record(p_clcb->p_srcb,
1351 status = BTA_GATT_ERROR;
1352 APPL_TRACE_ERROR("No server cache available");
1357 APPL_TRACE_ERROR("server cache not available, CLCB state = %d", p_clcb->state);
1359 status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
1364 APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
1370 /*******************************************************************************
1372 ** Function bta_gattc_fill_gatt_db_el
1374 ** Description fill a btgatt_db_element_t value
1378 *******************************************************************************/
1379 void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr,
1380 bt_gatt_db_attribute_type_t type,
1382 UINT16 s_handle, UINT16 e_handle,
1383 UINT8 id, tBT_UUID uuid, UINT8 prop)
1385 p_attr->type = type;
1386 p_attr->attribute_handle = att_handle;
1387 p_attr->start_handle = s_handle;
1388 p_attr->end_handle = e_handle;
1390 p_attr->properties = prop;
1391 bta_to_btif_uuid(&p_attr->uuid, &uuid);
1394 /*******************************************************************************
1396 ** Function bta_gattc_get_gatt_db_impl
1398 ** Description copy the server GATT database into db parameter.
1400 ** Parameters p_srvc_cb: server.
1401 ** db: output parameter which will contain GATT database copy.
1402 ** Caller is responsible for freeing it.
1403 ** count: output parameter which will contain number of
1404 ** elements in database.
1408 *******************************************************************************/
1409 static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
1410 UINT16 start_handle, UINT16 end_handle,
1411 btgatt_db_element_t **db,
1414 APPL_TRACE_DEBUG(LOG_TAG, "%s", __func__);
1418 if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
1424 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
1425 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1426 tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
1428 if (p_cur_srvc->s_handle < start_handle)
1431 if (p_cur_srvc->e_handle > end_handle)
1435 if (p_cur_srvc->p_attr)
1436 db_size += list_length(p_cur_srvc->p_attr);
1439 void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
1440 btgatt_db_element_t *curr_db_attr = buffer;
1442 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
1443 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1444 tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
1446 if (p_cur_srvc->s_handle < start_handle)
1449 if (p_cur_srvc->e_handle > end_handle)
1452 bta_gattc_fill_gatt_db_el(curr_db_attr,
1453 p_cur_srvc->service_uuid.is_primary ?
1454 BTGATT_DB_PRIMARY_SERVICE :
1455 BTGATT_DB_SECONDARY_SERVICE,
1457 p_cur_srvc->s_handle,
1458 p_cur_srvc->e_handle,
1459 p_cur_srvc->service_uuid.id.inst_id,
1460 p_cur_srvc->service_uuid.id.uuid,
1464 if (!p_cur_srvc->p_attr || list_is_empty(p_cur_srvc->p_attr))
1467 for (list_node_t *an = list_begin(p_cur_srvc->p_attr);
1468 an != list_end(p_cur_srvc->p_attr); an = list_next(an)) {
1469 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1471 bt_gatt_db_attribute_type_t type;
1472 switch (p_attr->attr_type)
1474 case BTA_GATTC_ATTR_TYPE_CHAR:
1475 type = BTGATT_DB_CHARACTERISTIC;
1478 case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
1479 type = BTGATT_DB_DESCRIPTOR;
1482 case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
1483 type = BTGATT_DB_INCLUDED_SERVICE;
1487 LOG_ERROR(LOG_TAG, "%s unknown gatt db attribute type: %d",
1488 __func__, p_attr->attr_type);
1492 bta_gattc_fill_gatt_db_el(curr_db_attr,
1494 p_attr->attr_handle,
1508 /*******************************************************************************
1510 ** Function bta_gattc_get_gatt_db
1512 ** Description copy the server GATT database into db parameter.
1514 ** Parameters conn_id: connection ID which identify the server.
1515 ** db: output parameter which will contain GATT database copy.
1516 ** Caller is responsible for freeing it.
1517 ** count: number of elements in database.
1521 *******************************************************************************/
1522 void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, int *count)
1524 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1526 LOG_DEBUG(LOG_TAG, "%s", __func__);
1527 if (p_clcb == NULL) {
1528 APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
1532 if (p_clcb->state != BTA_GATTC_CONN_ST) {
1533 APPL_TRACE_ERROR("server cache not available, CLCB state = %d",
1538 if (!p_clcb->p_srcb || p_clcb->p_srcb->p_srvc_list || /* no active discovery */
1539 !p_clcb->p_srcb->p_srvc_cache) {
1540 APPL_TRACE_ERROR("No server cache available");
1543 bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db, count);
1546 /*******************************************************************************
1548 ** Function bta_gattc_rebuild_cache
1550 ** Description rebuild server cache from NV cache.
1556 *******************************************************************************/
1557 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
1558 tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index)
1560 /* first attribute loading, initialize buffer */
1561 APPL_TRACE_ERROR("%s: bta_gattc_rebuild_cache", __func__);
1562 if (attr_index == 0)
1564 if (p_srvc_cb->p_srvc_cache)
1565 list_free(p_srvc_cb->p_srvc_cache);
1566 p_srvc_cb->p_srvc_cache = NULL;
1567 p_srvc_cb->p_cur_srvc = NULL;
1570 while (num_attr > 0 && p_attr != NULL)
1572 switch (p_attr->attr_type)
1574 case BTA_GATTC_ATTR_TYPE_SRVC:
1575 bta_gattc_add_srvc_to_cache(p_srvc_cb,
1583 case BTA_GATTC_ATTR_TYPE_CHAR:
1584 case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
1585 case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
1586 bta_gattc_add_attr_to_cache(p_srvc_cb,
1598 /*******************************************************************************
1600 ** Function bta_gattc_fill_nv_attr
1602 ** Description fill a NV attribute entry value
1606 *******************************************************************************/
1607 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
1608 UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop,
1611 p_attr->s_handle = s_handle;
1612 p_attr->e_handle = e_handle;
1613 p_attr->attr_type = type;
1614 p_attr->is_primary = is_primary;
1616 p_attr->prop = prop;
1618 memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
1620 /*******************************************************************************
1622 ** Function bta_gattc_cache_save
1624 ** Description save the server cache into NV
1628 *******************************************************************************/
1629 BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
1633 tBTA_GATTC_NV_ATTR nv_attr[BTA_GATTC_NV_LOAD_MAX];
1635 if (p_srvc_cb->p_srvc_cache && !list_is_empty(p_srvc_cb->p_srvc_cache)) {
1636 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
1637 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
1638 tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
1640 if (i >= BTA_GATTC_NV_LOAD_MAX)
1643 if (offset ++ >= p_srvc_cb->attr_index)
1644 bta_gattc_fill_nv_attr(&nv_attr[i++],
1645 BTA_GATTC_ATTR_TYPE_SRVC,
1646 p_cur_srvc->s_handle,
1647 p_cur_srvc->e_handle,
1648 p_cur_srvc->service_uuid.id.inst_id,
1649 p_cur_srvc->service_uuid.id.uuid,
1651 p_cur_srvc->service_uuid.is_primary);
1653 if (!p_cur_srvc->p_attr || list_is_empty(p_cur_srvc->p_attr))
1656 for (list_node_t *an = list_begin(p_cur_srvc->p_attr);
1657 an != list_end(p_cur_srvc->p_attr); an = list_next(an)) {
1658 tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
1660 if (i >= BTA_GATTC_NV_LOAD_MAX)
1663 if (offset++ >= p_srvc_cb->attr_index) {
1664 bta_gattc_fill_nv_attr(&nv_attr[i++],
1666 p_attr->attr_handle,
1678 bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i,
1679 nv_attr, p_srvc_cb->attr_index, conn_id);
1681 p_srvc_cb->attr_index += i;
1688 #endif /* BTA_GATT_INCLUDED */