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