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