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 "bt_target.h"
27
28 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
29
30 #include <string.h>
31 #include "utl.h"
32 #include "gki.h"
33 #include "bta_sys.h"
34 #include "sdp_api.h"
35 #include "sdpdefs.h"
36 #include "bta_gattc_int.h"
37 #include "btm_api.h"
38 #include "btm_ble_api.h"
39
40 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
41 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
42
43 #define BTA_GATT_SDP_DB_SIZE 4096
44
45 /*****************************************************************************
46 ** Constants
47 *****************************************************************************/
48
49 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
50 static char *bta_gattc_attr_type[] =
51 {
52 "I", /* Included Service */
53 "C", /* Characteristic */
54 "D" /* Characteristic Descriptor */
55 };
56 /* utility functions */
57
58 /*******************************************************************************
59 **
60 ** Function bta_gattc_display_cache_server
61 **
62 ** Description debug function to display the server cache.
63 **
64 ** Returns none.
65 **
66 *******************************************************************************/
bta_gattc_display_cache_server(tBTA_GATTC_CACHE * p_cache)67 static void bta_gattc_display_cache_server(tBTA_GATTC_CACHE *p_cache)
68 {
69 UINT8 i = 0, j;
70 tBTA_GATTC_CACHE *p_cur_srvc = p_cache;
71 tBTA_GATTC_CACHE_ATTR *p_attr;
72
73 APPL_TRACE_ERROR("<================Start Server Cache =============>");
74
75 while (p_cur_srvc)
76 {
77 APPL_TRACE_ERROR("Service[%d]: handle[%d ~ %d] %s[0x%04x] inst[%d]",
78 i, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
79 ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
80 p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
81 p_cur_srvc->service_uuid.id.inst_id);
82 i ++;
83
84 p_attr = p_cur_srvc->p_attr;
85
86 for (j = 0; p_attr; j ++ )
87 {
88 APPL_TRACE_ERROR("\t Attr[0x%04x] handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]",
89 j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id,
90 bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
91
92 p_attr = p_attr->p_next;
93 }
94 p_cur_srvc = p_cur_srvc->p_next;
95 }
96
97 APPL_TRACE_ERROR("<================End Server Cache =============>");
98 APPL_TRACE_ERROR(" ");
99 }
100
101 /*******************************************************************************
102 **
103 ** Function bta_gattc_display_explore_record
104 **
105 ** Description debug function to display the exploration list
106 **
107 ** Returns none.
108 **
109 *******************************************************************************/
bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC * p_rec,UINT8 num_rec)110 static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
111 {
112 UINT8 i;
113 tBTA_GATTC_ATTR_REC *pp = p_rec;
114
115 APPL_TRACE_ERROR("<================Start Explore Queue =============>");
116 for (i = 0; i < num_rec; i ++, pp ++)
117 {
118 APPL_TRACE_ERROR("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
119 i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
120 }
121 APPL_TRACE_ERROR("<================ End Explore Queue =============>");
122 APPL_TRACE_ERROR(" ");
123
124 }
125 #endif /* BTA_GATT_DEBUG == TRUE */
126
127
128 /*******************************************************************************
129 **
130 ** Function bta_gattc_alloc_cache_buf
131 **
132 ** Description Allocate a GKI buffer for database cache.
133 **
134 ** Returns status
135 **
136 *******************************************************************************/
bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV * p_srvc_cb)137 BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb)
138 {
139 BT_HDR *p_buf;
140
141 if ((p_buf = (BT_HDR *)GKI_getpoolbuf(GATT_DB_POOL_ID)) == NULL)
142 {
143 APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
144 utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
145 p_srvc_cb->free_byte = 0;
146 }
147 else
148 {
149 memset(p_buf, 0, GKI_get_buf_size(p_buf));
150 p_srvc_cb->p_free = (UINT8 *) p_buf;
151 p_srvc_cb->free_byte = GKI_get_buf_size(p_buf);
152
153 /* link into buffer queue */
154 GKI_enqueue(&p_srvc_cb->cache_buffer, p_buf);
155 }
156 #if BTA_GATT_DEBUG== TRUE
157 APPL_TRACE_DEBUG("allocating new buffer: free byte = %d", p_srvc_cb->free_byte);
158 #endif
159 return p_buf;
160 }
161 /*******************************************************************************
162 **
163 ** Function bta_gattc_init_cache
164 **
165 ** Description Initialize the database cache and discovery related resources.
166 **
167 ** Returns status
168 **
169 *******************************************************************************/
bta_gattc_init_cache(tBTA_GATTC_SERV * p_srvc_cb)170 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
171 {
172 tBTA_GATT_STATUS status = BTA_GATT_OK;
173
174 while (p_srvc_cb->cache_buffer.p_first)
175 GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
176
177 utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
178
179 if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC*)GKI_getbuf(BTA_GATTC_ATTR_LIST_SIZE)) == NULL)
180 {
181 APPL_TRACE_DEBUG("No resources: GKI buffer allocation failed.");
182 status = GATT_NO_RESOURCES;
183 }
184 else
185 {
186 p_srvc_cb->total_srvc = 0;
187 p_srvc_cb->cur_srvc_idx =
188 p_srvc_cb->cur_char_idx =
189 p_srvc_cb->next_avail_idx = 0;
190
191 if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
192 {
193 status = GATT_NO_RESOURCES;
194 }
195 else
196 {
197 p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
198 }
199 }
200
201 return status;
202 }
203 /*******************************************************************************
204 **
205 ** Function bta_gattc_get_srvc_inst_id
206 **
207 ** Description get service instance number
208 **
209 ** Returns instance ID of the service.
210 **
211 *******************************************************************************/
bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV * p_srvc_cb,tBT_UUID uuid)212 static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid)
213 {
214 UINT8 i = 0, inst = 0;
215 tBTA_GATTC_ATTR_REC *p_srvc_rec;
216
217 for (i = 0; i < p_srvc_cb->total_srvc; i ++)
218 /*
219 for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/
220 {
221 p_srvc_rec = p_srvc_cb->p_srvc_list + i;
222
223 if (bta_gattc_uuid_compare(&p_srvc_rec->uuid, &uuid, TRUE))
224 inst ++;
225 }
226 return inst ;
227 }
228 /*******************************************************************************
229 **
230 ** Function bta_gattc_get_char_inst_id
231 **
232 ** Description get characteristic instance number
233 **
234 ** Returns characteristic instance ID.
235 **
236 *******************************************************************************/
bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE * p_service_cache,tBT_UUID * p_uuid)237 static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID *p_uuid)
238 {
239 UINT8 inst = 0;
240 tBTA_GATTC_CACHE_ATTR *p_attr;
241 tBT_UUID attr_uuid;
242
243 p_attr = p_service_cache->p_attr;
244
245 while (p_attr)
246 {
247 bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
248
249 if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
250 inst ++;
251
252 p_attr = p_attr->p_next;
253 }
254
255 return inst ;
256 }
257 /*******************************************************************************
258 **
259 ** Function bta_gattc_get_char_descr_inst_id
260 **
261 ** Description get characteristic descriptor instance number
262 **
263 ** Returns characteristic instance ID.
264 **
265 *******************************************************************************/
bta_gattc_get_char_descr_inst_id(tBTA_GATTC_CACHE_ATTR * p_char_attr,tBT_UUID * p_uuid)266 static UINT8 bta_gattc_get_char_descr_inst_id(tBTA_GATTC_CACHE_ATTR *p_char_attr, tBT_UUID *p_uuid)
267 {
268 UINT8 inst = 0;
269 tBT_UUID attr_uuid;
270
271 if (p_char_attr != NULL)
272 p_char_attr = p_char_attr->p_next;
273
274 while (p_char_attr)
275 {
276 bta_gattc_pack_attr_uuid(p_char_attr, &attr_uuid);
277
278 if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
279 inst ++;
280
281 p_char_attr = p_char_attr->p_next;
282 }
283 return inst ;
284 }
285
286 /*******************************************************************************
287 **
288 ** Function bta_gattc_add_srvc_to_cache
289 **
290 ** Description Add a service into database cache.
291 **
292 ** Returns status
293 **
294 *******************************************************************************/
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,UINT8 srvc_inst)295 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
296 UINT16 s_handle, UINT16 e_handle,
297 tBT_UUID *p_uuid,
298 BOOLEAN is_primary, UINT8 srvc_inst)
299 {
300 tBTA_GATTC_CACHE *p_new_srvc = NULL;
301 tBTA_GATT_STATUS status = BTA_GATT_OK;
302
303 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
304 APPL_TRACE_DEBUG("Add a service into Service");
305 APPL_TRACE_DEBUG("free byte = %d, req %d bytes.", p_srvc_cb->free_byte, sizeof(tBTA_GATTC_CACHE))
306 #endif
307
308 if (p_srvc_cb->free_byte < sizeof(tBTA_GATTC_CACHE))
309 {
310 if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
311 return GATT_NO_RESOURCES;
312 }
313
314 p_new_srvc = (tBTA_GATTC_CACHE *)p_srvc_cb->p_free;
315 /* update service information */
316 p_new_srvc->s_handle = s_handle;
317 p_new_srvc->e_handle = e_handle;
318 p_new_srvc->service_uuid.is_primary = is_primary;
319 memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
320 p_new_srvc->service_uuid.id.inst_id = srvc_inst;
321 p_new_srvc->p_next = NULL;
322
323 if (p_srvc_cb->p_cur_srvc != NULL)
324 p_srvc_cb->p_cur_srvc->p_next = p_new_srvc;
325 p_srvc_cb->p_cur_srvc = p_new_srvc;
326 p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
327
328 /* first service */
329 if (p_srvc_cb->p_srvc_cache == NULL)
330 p_srvc_cb->p_srvc_cache = p_new_srvc;
331
332 /* update buffer managament info */
333 p_srvc_cb->p_free += sizeof(tBTA_GATTC_CACHE);
334 p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE);
335
336
337 return status;
338 }
339 /*******************************************************************************
340 **
341 ** Function bta_gattc_add_attr_to_cache
342 **
343 ** Description Add an attribute into database cache buffer.
344 **
345 ** Returns status
346 **
347 *******************************************************************************/
bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV * p_srvc_cb,UINT16 handle,tBT_UUID * p_uuid,UINT8 property,tBTA_GATTC_ATTR_TYPE type)348 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
349 UINT16 handle,
350 tBT_UUID *p_uuid,
351 UINT8 property,
352 tBTA_GATTC_ATTR_TYPE type)
353 {
354 tBTA_GATTC_CACHE_ATTR *p_attr;
355 tBTA_GATT_STATUS status = BTA_GATT_OK;
356 UINT16 len = sizeof(tBTA_GATTC_CACHE_ATTR) + p_uuid->len;
357 UINT8 *pp;
358
359 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
360 APPL_TRACE_DEBUG("bta_gattc_add_attr_to_cache: Add a [%s] into Service", bta_gattc_attr_type[type]);
361 APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
362 APPL_TRACE_DEBUG("free byte = %d, req %d bytes.", p_srvc_cb->free_byte, len);
363 #endif
364
365 if (p_srvc_cb->p_cur_srvc == NULL)
366 {
367 APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc before adding a service!");
368 return GATT_WRONG_STATE;
369 }
370
371 if (p_srvc_cb->free_byte < len)
372 {
373 if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
374 return GATT_NO_RESOURCES;
375 }
376
377 p_attr = (tBTA_GATTC_CACHE_ATTR *)p_srvc_cb->p_free;
378
379 p_attr->attr_handle = handle;
380 p_attr->attr_type = type;
381 p_attr->property = property;
382 p_attr->uuid_len = p_uuid->len;
383 p_attr->p_uuid = (tBTA_GATTC_UUID *)(p_attr + 1);
384 p_attr->p_next = NULL;
385
386 pp = (UINT8 *)p_attr->p_uuid;
387
388 if (p_uuid->len == LEN_UUID_16)
389 {
390 UINT16_TO_STREAM(pp, p_uuid->uu.uuid16);
391 }
392 else if (p_uuid->len == LEN_UUID_128)
393 {
394 memcpy(pp, p_uuid->uu.uuid128, LEN_UUID_128);
395 }
396
397 if (type == BTA_GATTC_ATTR_TYPE_CHAR)
398 {
399 p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, p_uuid);
400 p_srvc_cb->p_cur_srvc->p_cur_char = p_attr;
401 }
402 else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
403 p_attr->inst_id = bta_gattc_get_char_descr_inst_id(p_srvc_cb->p_cur_srvc->p_cur_char, p_uuid);
404 else /* TODO: --->> temp treat included service as single instance */
405 p_attr->inst_id = 0;
406
407 /* update service information */
408 p_srvc_cb->p_free += len;
409 p_srvc_cb->free_byte -= len;
410
411 /* first attribute within the service, update the attribute pointer */
412 if (p_srvc_cb->p_cur_srvc->p_attr == NULL)
413 {
414 p_srvc_cb->p_cur_srvc->p_attr = p_attr;
415 }
416 if (p_srvc_cb->p_cur_srvc->p_last_attr != NULL)
417 p_srvc_cb->p_cur_srvc->p_last_attr->p_next = p_attr;
418
419 p_srvc_cb->p_cur_srvc->p_last_attr = p_attr;
420
421 return status;
422 }
423
424 /*******************************************************************************
425 **
426 ** Function bta_gattc_get_disc_range
427 **
428 ** Description get discovery stating and ending handle range.
429 **
430 ** Returns None.
431 **
432 *******************************************************************************/
bta_gattc_get_disc_range(tBTA_GATTC_SERV * p_srvc_cb,UINT16 * p_s_hdl,UINT16 * p_e_hdl,BOOLEAN is_srvc)433 void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
434 {
435 tBTA_GATTC_ATTR_REC *p_rec = NULL;
436
437 if (is_srvc)
438 {
439 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
440 *p_s_hdl = p_rec->s_handle;
441 }
442 else
443 {
444 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
445 *p_s_hdl = p_rec->s_handle + 1;
446 }
447
448 *p_e_hdl = p_rec->e_handle;
449 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
450 APPL_TRACE_DEBUG("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle);
451 #endif
452 return;
453 }
454 /*******************************************************************************
455 **
456 ** Function bta_gattc_discover_pri_service
457 **
458 ** Description Start primary service discovery
459 **
460 ** Returns status of the operation.
461 **
462 *******************************************************************************/
bta_gattc_discover_pri_service(UINT16 conn_id,tBTA_GATTC_SERV * p_server_cb,UINT8 disc_type)463 tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
464 UINT8 disc_type)
465 {
466 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
467 tBTA_GATT_STATUS status = BTA_GATT_ERROR;
468
469 if (p_clcb)
470 {
471 if (p_clcb->transport == BTA_TRANSPORT_LE)
472 status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
473 else
474 status = bta_gattc_sdp_service_disc(conn_id, p_server_cb);
475 }
476
477 return status;
478 }
479 /*******************************************************************************
480 **
481 ** Function bta_gattc_discover_procedure
482 **
483 ** Description Start a particular type of discovery procedure on server.
484 **
485 ** Returns status of the operation.
486 **
487 *******************************************************************************/
bta_gattc_discover_procedure(UINT16 conn_id,tBTA_GATTC_SERV * p_server_cb,UINT8 disc_type)488 tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb,
489 UINT8 disc_type)
490 {
491 tGATT_DISC_PARAM param;
492 BOOLEAN is_service = TRUE;
493
494 memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
495
496 if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID)
497 {
498 param.s_handle = 1;
499 param.e_handle = 0xFFFF;
500 }
501 else
502 {
503 if (disc_type == GATT_DISC_CHAR_DSCPT)
504 is_service = FALSE;
505
506 bta_gattc_get_disc_range(p_server_cb, ¶m.s_handle, ¶m.e_handle, is_service);
507
508 if (param.s_handle > param.e_handle)
509 {
510 return GATT_ERROR;
511 }
512 }
513 return GATTC_Discover (conn_id, disc_type, ¶m);
514
515 }
516 /*******************************************************************************
517 **
518 ** Function bta_gattc_start_disc_include_srvc
519 **
520 ** Description Start discovery for included service
521 **
522 ** Returns status of the operation.
523 **
524 *******************************************************************************/
bta_gattc_start_disc_include_srvc(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)525 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
526 {
527 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
528 }
529 /*******************************************************************************
530 **
531 ** Function bta_gattc_start_disc_char
532 **
533 ** Description Start discovery for characteristic
534 **
535 ** Returns status of the operation.
536 **
537 *******************************************************************************/
bta_gattc_start_disc_char(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)538 tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
539 {
540 p_srvc_cb->total_char = 0;
541
542 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
543 }
544 /*******************************************************************************
545 **
546 ** Function bta_gattc_start_disc_char_dscp
547 **
548 ** Description Start discovery for characteristic descriptor
549 **
550 ** Returns none.
551 **
552 *******************************************************************************/
bta_gattc_start_disc_char_dscp(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)553 void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
554 {
555 APPL_TRACE_DEBUG("starting discover characteristics descriptor");
556
557 if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0)
558 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
559
560 }
561 /*******************************************************************************
562 **
563 ** Function bta_gattc_explore_srvc
564 **
565 ** Description process the service discovery complete event
566 **
567 ** Returns status
568 **
569 *******************************************************************************/
bta_gattc_explore_srvc(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)570 static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
571 {
572 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
573 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
574
575 APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
576
577 p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
578
579 if (p_clcb == NULL)
580 {
581 APPL_TRACE_ERROR("unknown connection ID");
582 return;
583 }
584 /* start expore a service if there is service not been explored */
585 if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc)
586 {
587 /* add the first service into cache */
588 if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
589 p_rec->s_handle,
590 p_rec->e_handle,
591 &p_rec->uuid,
592 p_rec->is_primary,
593 p_rec->srvc_inst_id) == 0)
594 {
595 /* start discovering included services */
596 bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
597 return;
598 }
599 }
600 /* no service found at all, the end of server discovery*/
601 APPL_TRACE_ERROR("No More Service found");
602
603 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
604 bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
605 #endif
606 /* save cache to NV */
607 p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
608 bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
609 conn_id, TRUE);
610 }
611 /*******************************************************************************
612 **
613 ** Function bta_gattc_incl_srvc_disc_cmpl
614 **
615 ** Description process the relationship discovery complete event
616 **
617 ** Returns status
618 **
619 *******************************************************************************/
bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)620 static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
621 {
622 p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
623
624 /* start discoverying characteristic */
625 bta_gattc_start_disc_char(conn_id, p_srvc_cb);
626 }
627 /*******************************************************************************
628 **
629 ** Function bta_gattc_char_disc_cmpl
630 **
631 ** Description process the characteristic discovery complete event
632 **
633 ** Returns status
634 **
635 *******************************************************************************/
bta_gattc_char_disc_cmpl(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)636 static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
637 {
638 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
639
640 /* if there are characteristic needs to be explored */
641 if (p_srvc_cb->total_char > 0)
642 {
643 /* add the first characteristic into cache */
644 bta_gattc_add_attr_to_cache (p_srvc_cb,
645 p_rec->s_handle,
646 &p_rec->uuid,
647 p_rec->property,
648 BTA_GATTC_ATTR_TYPE_CHAR);
649
650 /* start discoverying characteristic descriptor , if failed, disc for next char*/
651 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
652 }
653 else /* otherwise start with next service */
654 {
655 p_srvc_cb->cur_srvc_idx ++;
656
657 bta_gattc_explore_srvc (conn_id, p_srvc_cb);
658 }
659 }
660 /*******************************************************************************
661 **
662 ** Function bta_gattc_char_dscpt_disc_cmpl
663 **
664 ** Description process the char descriptor discovery complete event
665 **
666 ** Returns status
667 **
668 *******************************************************************************/
bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id,tBTA_GATTC_SERV * p_srvc_cb)669 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
670 {
671 tBTA_GATTC_ATTR_REC *p_rec = NULL;
672
673 if (-- p_srvc_cb->total_char > 0)
674 {
675 p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
676 /* add the next characteristic into cache */
677 bta_gattc_add_attr_to_cache (p_srvc_cb,
678 p_rec->s_handle,
679 &p_rec->uuid,
680 p_rec->property,
681 BTA_GATTC_ATTR_TYPE_CHAR);
682
683 /* start discoverying next characteristic for char descriptor */
684 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
685 }
686 else
687 /* all characteristic has been explored, start with next service if any */
688 {
689 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
690 APPL_TRACE_ERROR("all char has been explored");
691 #endif
692 p_srvc_cb->cur_srvc_idx ++;
693 bta_gattc_explore_srvc (conn_id, p_srvc_cb);
694 }
695
696 }
bta_gattc_srvc_in_list(tBTA_GATTC_SERV * p_srvc_cb,UINT16 s_handle,UINT16 e_handle,tBT_UUID uuid)697 static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
698 UINT16 e_handle, tBT_UUID uuid)
699 {
700 tBTA_GATTC_ATTR_REC *p_rec = NULL;
701 UINT8 i;
702 BOOLEAN exist_srvc = FALSE;
703 UNUSED(uuid);
704
705 if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle))
706 {
707 APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
708 exist_srvc = TRUE;
709 }
710 else
711 {
712 for (i = 0; i < p_srvc_cb->next_avail_idx; i ++)
713 {
714 p_rec = p_srvc_cb->p_srvc_list + i;
715
716 /* a new service should not have any overlap with other service handle range */
717 if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle)
718 {
719 exist_srvc = TRUE;
720 break;
721 }
722 }
723 }
724 return exist_srvc;
725 }
726 /*******************************************************************************
727 **
728 ** Function bta_gattc_add_srvc_to_list
729 **
730 ** Description Add a service into explore pending list
731 **
732 ** Returns status
733 **
734 *******************************************************************************/
bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV * p_srvc_cb,UINT16 s_handle,UINT16 e_handle,tBT_UUID uuid,BOOLEAN is_primary)735 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
736 UINT16 s_handle, UINT16 e_handle,
737 tBT_UUID uuid, BOOLEAN is_primary)
738 {
739 tBTA_GATTC_ATTR_REC *p_rec = NULL;
740 tBTA_GATT_STATUS status = BTA_GATT_OK;
741
742 if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
743 {
744 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
745
746 p_srvc_cb->total_srvc ++;
747
748 APPL_TRACE_DEBUG("bta_gattc_add_srvc_to_list handle = %d, service type = 0x%04x",
749 s_handle, uuid.uu.uuid16);
750
751 p_rec->s_handle = s_handle;
752 p_rec->e_handle = e_handle;
753 p_rec->is_primary = is_primary;
754 p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid);
755 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
756
757 p_srvc_cb->next_avail_idx ++;
758
759 }
760 else
761 { /* allocate bigger buffer ?? */
762 status = GATT_DB_FULL;
763
764 APPL_TRACE_ERROR("service not added, no resources or wrong state");
765 }
766 return status;
767 }
768 /*******************************************************************************
769 **
770 ** Function bta_gattc_add_char_to_list
771 **
772 ** Description Add a characteristic into explore pending list
773 **
774 ** Returns status
775 **
776 *******************************************************************************/
bta_gattc_add_char_to_list(tBTA_GATTC_SERV * p_srvc_cb,UINT16 decl_handle,UINT16 value_handle,tBT_UUID uuid,UINT8 property)777 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
778 UINT16 decl_handle, UINT16 value_handle,
779 tBT_UUID uuid, UINT8 property)
780 {
781 tBTA_GATTC_ATTR_REC *p_rec = NULL;
782 tBTA_GATT_STATUS status = BTA_GATT_OK;
783
784 if (p_srvc_cb->p_srvc_list == NULL)
785 {
786 APPL_TRACE_ERROR("No service available, unexpected char discovery result");
787 status = BTA_GATT_INTERNAL_ERROR;
788 }
789 else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
790 {
791
792 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
793
794 p_srvc_cb->total_char ++;
795
796 p_rec->s_handle = value_handle;
797 p_rec->property = property;
798 p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
799 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
800
801 /* update the endind handle of pervious characteristic if available */
802 if (p_srvc_cb->total_char > 1)
803 {
804 p_rec -= 1;
805 p_rec->e_handle = decl_handle - 1;
806 }
807 p_srvc_cb->next_avail_idx ++;
808 }
809 else
810 {
811 APPL_TRACE_ERROR("char not added, no resources");
812 /* allocate bigger buffer ?? */
813 status = BTA_GATT_DB_FULL;
814 }
815 return status;
816
817 }
818 /*******************************************************************************
819 **
820 ** Function bta_gattc_sdp_callback
821 **
822 ** Description Process the discovery result from sdp
823 **
824 ** Returns void
825 **
826 *******************************************************************************/
bta_gattc_sdp_callback(UINT16 sdp_status)827 void bta_gattc_sdp_callback (UINT16 sdp_status)
828 {
829 tSDP_DISC_REC *p_sdp_rec = NULL;
830 tBT_UUID service_uuid;
831 tSDP_PROTOCOL_ELEM pe;
832 UINT16 start_handle = 0, end_handle = 0;
833 tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id);
834
835 if(((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL)
836 {
837 do
838 {
839 /* find a service record, report it */
840 p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db,
841 0, p_sdp_rec);
842 if (p_sdp_rec)
843 {
844 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
845 {
846
847 if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
848 {
849 start_handle = (UINT16) pe.params[0];
850 end_handle = (UINT16) pe.params[1];
851
852 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
853 APPL_TRACE_EVENT("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
854 service_uuid.uu.uuid16, start_handle, end_handle);
855 #endif
856
857 if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle)&&
858 p_srvc_cb != NULL)
859 {
860 /* discover services result, add services into a service list */
861 bta_gattc_add_srvc_to_list(p_srvc_cb,
862 start_handle,
863 end_handle,
864 service_uuid,
865 TRUE);
866 }
867 else
868 {
869 APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d",
870 start_handle, end_handle);
871 }
872 }
873
874
875 }
876 }
877 } while (p_sdp_rec);
878 }
879
880 if ( p_srvc_cb != NULL)
881 /* start discover primary service */
882 bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb);
883 else
884 {
885 APPL_TRACE_ERROR("GATT service discovery is done on unknown connection");
886 }
887
888 GKI_freebuf(bta_gattc_cb.p_sdp_db);
889 bta_gattc_cb.p_sdp_db = NULL;
890 bta_gattc_cb.sdp_conn_id = 0;
891 }
892 /*******************************************************************************
893 **
894 ** Function bta_gattc_sdp_service_disc
895 **
896 ** Description Start DSP Service Discovert
897 **
898 ** Returns void
899 **
900 *******************************************************************************/
bta_gattc_sdp_service_disc(UINT16 conn_id,tBTA_GATTC_SERV * p_server_cb)901 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
902 {
903 tSDP_UUID uuid;
904 UINT16 num_attrs = 2;
905 UINT16 attr_list[2];
906 tBTA_GATT_STATUS status = BTA_GATT_ERROR;
907
908 memset (&uuid, 0, sizeof(tSDP_UUID));
909
910 uuid.len = LEN_UUID_16;
911 uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
912
913 if((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_GATT_SDP_DB_SIZE)) != NULL)
914 {
915 attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
916 attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
917
918 SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1,
919 &uuid, num_attrs, attr_list);
920
921 if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda,
922 bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback))
923 {
924 GKI_freebuf(bta_gattc_cb.p_sdp_db);
925 bta_gattc_cb.p_sdp_db = NULL;
926 }
927 else
928 {
929 bta_gattc_cb.sdp_conn_id = conn_id;
930 status = BTA_GATT_OK;
931 }
932 }
933 return status;
934 }
935 /*******************************************************************************
936 **
937 ** Function bta_gattc_disc_res_cback
938 ** bta_gattc_disc_cmpl_cback
939 **
940 ** Description callback functions to GATT client stack.
941 **
942 ** Returns void
943 **
944 *******************************************************************************/
bta_gattc_disc_res_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)945 void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
946 {
947 tBTA_GATTC_SERV * p_srvc_cb = NULL;
948 BOOLEAN pri_srvc;
949 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
950
951 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
952
953 if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST)
954 {
955 switch (disc_type)
956 {
957 case GATT_DISC_SRVC_ALL:
958 /* discover services result, add services into a service list */
959 bta_gattc_add_srvc_to_list(p_srvc_cb,
960 p_data->handle,
961 p_data->value.group_value.e_handle,
962 p_data->value.group_value.service_type,
963 TRUE);
964
965 break;
966 case GATT_DISC_SRVC_BY_UUID:
967 bta_gattc_add_srvc_to_list(p_srvc_cb,
968 p_data->handle,
969 p_data->value.group_value.e_handle,
970 p_data->value.group_value.service_type,
971 TRUE);
972 break;
973
974 case GATT_DISC_INC_SRVC:
975 /* add included service into service list if it's secondary or it never showed up
976 in the primary service search */
977 pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
978 p_data->value.incl_service.s_handle,
979 p_data->value.incl_service.e_handle,
980 p_data->value.incl_service.service_type);
981
982 if (!pri_srvc)
983 bta_gattc_add_srvc_to_list(p_srvc_cb,
984 p_data->value.incl_service.s_handle,
985 p_data->value.incl_service.e_handle,
986 p_data->value.incl_service.service_type,
987 FALSE);
988 /* add into database */
989 bta_gattc_add_attr_to_cache(p_srvc_cb,
990 p_data->handle,
991 &p_data->value.incl_service.service_type,
992 pri_srvc,
993 BTA_GATTC_ATTR_TYPE_INCL_SRVC);
994 break;
995
996 case GATT_DISC_CHAR:
997 /* add char value into database */
998 bta_gattc_add_char_to_list(p_srvc_cb,
999 p_data->handle,
1000 p_data->value.dclr_value.val_handle,
1001 p_data->value.dclr_value.char_uuid,
1002 p_data->value.dclr_value.char_prop);
1003 break;
1004
1005 case GATT_DISC_CHAR_DSCPT:
1006 bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
1007 BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
1008 break;
1009 }
1010 }
1011 }
bta_gattc_disc_cmpl_cback(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_STATUS status)1012 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
1013 {
1014 tBTA_GATTC_SERV * p_srvc_cb;
1015 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1016
1017 if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
1018 {
1019 if (p_clcb->status == GATT_SUCCESS)
1020 p_clcb->status = status;
1021 bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
1022 return;
1023 }
1024 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
1025
1026 if (p_srvc_cb != NULL)
1027 {
1028 switch (disc_type)
1029 {
1030 case GATT_DISC_SRVC_ALL:
1031 case GATT_DISC_SRVC_BY_UUID:
1032 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1033 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
1034 #endif
1035 bta_gattc_explore_srvc(conn_id, p_srvc_cb);
1036 break;
1037
1038 case GATT_DISC_INC_SRVC:
1039 bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
1040
1041 break;
1042
1043 case GATT_DISC_CHAR:
1044 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1045 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
1046 #endif
1047 bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
1048 break;
1049
1050 case GATT_DISC_CHAR_DSCPT:
1051 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
1052 break;
1053 }
1054 }
1055 }
1056 /*******************************************************************************
1057 **
1058 ** Function bta_gattc_id2handle
1059 **
1060 ** Description map GATT ID to handle in a given cache.
1061 **
1062 ** Returns the handle mapped. 0 if not found.
1063 **
1064 *******************************************************************************/
bta_gattc_id2handle(tBTA_GATTC_SERV * p_srcb,tBTA_GATT_SRVC_ID * p_service_id,tBTA_GATT_ID * p_char_id,tBTA_GATT_ID * p_descr_uuid)1065 UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
1066 tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid)
1067 {
1068 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
1069 tBTA_GATTC_CACHE_ATTR *p_attr;
1070 UINT8 j;
1071 UINT16 handle = 0;
1072 tBT_UUID attr_uuid;
1073 BOOLEAN char_map = FALSE, done = FALSE;
1074
1075 while (p_service_id && p_cache && !done)
1076 {
1077 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1078 APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
1079 p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
1080 p_cache->service_uuid.id.inst_id);
1081 #endif
1082 p_attr = p_cache->p_attr;
1083
1084 if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
1085 {
1086 for (j = 0; p_attr; j ++)
1087 {
1088 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1089 APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
1090 j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
1091 p_attr->inst_id, p_attr->attr_type);
1092 #endif
1093 bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
1094
1095 if (bta_gattc_uuid_compare(&p_char_id->uuid, &attr_uuid, TRUE) &&
1096 p_char_id->inst_id == p_attr->inst_id)
1097 {
1098 if (p_descr_uuid == NULL)
1099 {
1100 handle = p_attr->attr_handle;
1101 done = TRUE;
1102 break;
1103 }
1104 else
1105 {
1106 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1107 APPL_TRACE_DEBUG("found matching characteristic for the descriptor");
1108 #endif
1109 char_map = TRUE;
1110 }
1111 }
1112 else if (char_map == TRUE)
1113 {
1114 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
1115 {
1116
1117 if (p_descr_uuid != NULL &&
1118 bta_gattc_uuid_compare(&p_descr_uuid->uuid, &attr_uuid, TRUE) &&
1119 p_descr_uuid->inst_id == p_attr->inst_id)
1120 {
1121 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1122 APPL_TRACE_DEBUG("found descriptor!!");
1123 #endif
1124 handle = p_attr->attr_handle;
1125 done = TRUE;
1126 break;
1127 }
1128 else
1129 {
1130 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1131 APPL_TRACE_DEBUG("descriptor UUID not matching");
1132 #endif
1133 }
1134 }
1135 else /* another char */
1136 {
1137 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1138 APPL_TRACE_DEBUG("no matching descptr found!!start of next characteristic");
1139 #endif
1140 char_map = FALSE;
1141 done = TRUE;
1142 break;
1143 }
1144 }
1145 p_attr = p_attr->p_next;
1146 }
1147 }
1148 p_cache = p_cache->p_next;
1149 }
1150
1151 return handle;
1152 }
1153 /*******************************************************************************
1154 **
1155 ** Function bta_gattc_handle2id
1156 **
1157 ** Description map a handle to GATT ID in a given cache.
1158 **
1159 ** Returns FALSE if map can not be found.
1160 **
1161 *******************************************************************************/
1162
bta_gattc_handle2id(tBTA_GATTC_SERV * p_srcb,UINT16 handle,tBTA_GATT_SRVC_ID * p_service_id,tBTA_GATT_ID * p_char_id,tBTA_GATT_ID * p_descr_type)1163 BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
1164 tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
1165 {
1166 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
1167 tBTA_GATTC_CACHE_ATTR *p_attr, *p_char = NULL;
1168 UINT8 j;
1169
1170 memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
1171 memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
1172 memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
1173
1174 while (p_cache)
1175 {
1176 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1177 APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x] inst[%d]",
1178 p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
1179 p_cache->service_uuid.id.inst_id);
1180 #endif
1181 /* a service found */
1182 if (p_cache->s_handle == handle)
1183 {
1184 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
1185
1186 return TRUE;
1187 }
1188 else /* start looking for attributes within the service */
1189 {
1190 p_attr = p_cache->p_attr;
1191
1192 for (j = 0; p_attr; j ++)
1193 {
1194 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1195 APPL_TRACE_DEBUG("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
1196 j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16,
1197 p_attr->inst_id, p_attr->attr_type);
1198 #endif
1199 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
1200 p_char = p_attr;
1201
1202 if (handle == p_attr->attr_handle)
1203 {
1204 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
1205
1206 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
1207 {
1208 bta_gattc_pack_attr_uuid(p_attr, &p_descr_type->uuid);
1209 p_descr_type->inst_id = p_attr->inst_id;
1210
1211 if (p_char != NULL)
1212 {
1213 bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid);
1214 p_char_id->inst_id = p_char->inst_id;
1215 }
1216 else
1217 {
1218 APPL_TRACE_ERROR("descptr does not belong to any chracteristic");
1219 }
1220 }
1221 else
1222 /* is a characterisitc value or included service */
1223 {
1224 bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid);
1225 p_char_id->inst_id =p_attr->inst_id;
1226 }
1227 return TRUE;
1228 }
1229 p_attr = p_attr->p_next;
1230 }
1231 }
1232 p_cache = p_cache->p_next;
1233 }
1234
1235 return FALSE;
1236 }
1237
1238 /*******************************************************************************
1239 **
1240 ** Function bta_gattc_search_service
1241 **
1242 ** Description search local cache for matching service record.
1243 **
1244 ** Returns FALSE if map can not be found.
1245 **
1246 *******************************************************************************/
bta_gattc_search_service(tBTA_GATTC_CLCB * p_clcb,tBT_UUID * p_uuid)1247 void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
1248 {
1249 tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
1250 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
1251 tBTA_GATTC cb_data;
1252
1253 while (p_cache)
1254 {
1255 if (bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE))
1256 {
1257 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1258 APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]",
1259 p_cache->service_uuid.id.uuid.uu.uuid16,
1260 p_cache->service_uuid.id.inst_id,
1261 p_cache->s_handle);
1262 #endif
1263 if (p_clcb->p_rcb->p_cback)
1264 {
1265 memset(&cb_data, 0, sizeof(tBTA_GATTC));
1266
1267 cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
1268 memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid,
1269 sizeof(tBTA_GATT_SRVC_ID));
1270
1271 (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
1272 }
1273 }
1274 p_cache = p_cache->p_next;
1275 }
1276 }
1277 /*******************************************************************************
1278 **
1279 ** Function bta_gattc_find_record
1280 **
1281 ** Description search local cache for matching attribute record.
1282 **
1283 ** Parameter p_result: output parameter to store the characteristic/
1284 ** included service GATT ID.
1285 **
1286 ** Returns GATT_ERROR is no recording found. BTA_GATT_OK if record found.
1287 **
1288 *******************************************************************************/
bta_gattc_find_record(tBTA_GATTC_SERV * p_srcb,tBTA_GATTC_ATTR_TYPE attr_type,tBTA_GATT_SRVC_ID * p_service_id,tBTA_GATT_ID * p_start_rec,tBT_UUID * p_uuid_cond,tBTA_GATT_ID * p_result,void * p_param)1289 static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
1290 tBTA_GATTC_ATTR_TYPE attr_type,
1291 tBTA_GATT_SRVC_ID *p_service_id,
1292 tBTA_GATT_ID *p_start_rec,
1293 tBT_UUID * p_uuid_cond,
1294 tBTA_GATT_ID *p_result,
1295 void *p_param)
1296 {
1297 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
1298 tBTA_GATT_STATUS status = BTA_GATT_ERROR;
1299 UINT8 i, j;
1300 tBTA_GATTC_CACHE_ATTR *p_attr;
1301 BOOLEAN char_found = FALSE, descr_found = FALSE;
1302 tBTA_GATT_ID *p_descr_id = (tBTA_GATT_ID *)p_param;;
1303
1304 for (i = 0; p_cache && status != BTA_GATT_OK; i ++)
1305 {
1306 if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
1307 {
1308 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1309 APPL_TRACE_DEBUG("found matching service [0x%04x], inst[%d]",
1310 p_cache->service_uuid.id.uuid.uu.uuid16,
1311 p_cache->service_uuid.id.inst_id);
1312 #endif
1313 p_attr = p_cache->p_attr;
1314
1315 for (j = 0; p_attr; j ++)
1316 {
1317 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1318 APPL_TRACE_DEBUG("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
1319 j + 1, p_attr->attr_handle,
1320 p_attr->p_uuid->uuid16,
1321 p_attr->inst_id,
1322 p_attr->attr_type);
1323 #endif
1324 bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
1325
1326 if (p_start_rec != NULL && char_found == FALSE)
1327 {
1328 /* find the starting record first */
1329 if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
1330 p_start_rec->inst_id == p_attr->inst_id &&
1331 (attr_type == p_attr->attr_type ||
1332 /* find descriptor would look for characteristic first */
1333 (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
1334 p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
1335 {
1336 char_found = TRUE;
1337 }
1338 }
1339 else
1340 {
1341 /* if looking for descriptor, here is the where the descrptor to be found */
1342 if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
1343 {
1344 /* next characeteristic already, return error */
1345 if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
1346 {
1347 break;
1348 }
1349 else
1350 {
1351 /* find starting descriptor */
1352 if (p_descr_id != NULL && !descr_found)
1353 {
1354 if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
1355 && p_descr_id->inst_id == p_attr->inst_id)
1356 {
1357 descr_found = TRUE;
1358 }
1359 }
1360 else
1361 {
1362 /* with matching descriptor */
1363 if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE))
1364 {
1365 p_result->inst_id = p_attr->inst_id;
1366 status = BTA_GATT_OK;
1367 break;
1368 }
1369 }
1370 }
1371 }
1372 else
1373 {
1374 if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) &&
1375 attr_type == p_attr->attr_type)
1376 {
1377
1378 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1379 APPL_TRACE_DEBUG("found char handle mapping characteristic");
1380 #endif
1381 p_result->inst_id = p_attr->inst_id;
1382
1383 if (p_param != NULL)
1384 {
1385 if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
1386 attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC)
1387 {
1388 *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
1389 }
1390 }
1391
1392 status = BTA_GATT_OK;
1393 break;
1394 }
1395 }
1396 }
1397 p_attr = p_attr->p_next;
1398 }
1399 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
1400 if (status)
1401 {
1402 APPL_TRACE_ERROR("In the given service, can not find matching record");
1403 }
1404 #endif
1405 break;
1406 }
1407
1408 p_cache = p_cache->p_next;
1409 }
1410 return status;
1411
1412 }
1413
1414 /*******************************************************************************
1415 **
1416 ** Function bta_gattc_query_cache
1417 **
1418 ** Description search local cache for matching attribute record.
1419 **
1420 ** Parameters conn_id: connection ID which identify the server.
1421 ** p_srvc_id: the service ID of which the characteristic is belonged to.
1422 ** *p_start_rec: start the search from the next record
1423 ** after the one identified by *p_start_rec.
1424 ** p_uuid_cond: UUID, if NULL find the first available
1425 ** characteristic/included service.
1426 ** p_output: output parameter which will store the GATT ID
1427 ** of the characteristic /included service found.
1428 **
1429 ** Returns BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
1430 **
1431 *******************************************************************************/
bta_gattc_query_cache(UINT16 conn_id,tBTA_GATTC_ATTR_TYPE query_type,tBTA_GATT_SRVC_ID * p_srvc_id,tBTA_GATT_ID * p_start_rec,tBT_UUID * p_uuid_cond,tBTA_GATT_ID * p_output,void * p_param)1432 tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
1433 tBTA_GATTC_ATTR_TYPE query_type,
1434 tBTA_GATT_SRVC_ID *p_srvc_id,
1435 tBTA_GATT_ID *p_start_rec,
1436 tBT_UUID *p_uuid_cond,
1437 tBTA_GATT_ID *p_output,
1438 void *p_param)
1439 {
1440 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
1441 tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
1442
1443 if (p_clcb != NULL )
1444 {
1445 if (p_clcb->state == BTA_GATTC_CONN_ST)
1446 {
1447 if (p_clcb->p_srcb &&
1448 !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
1449 p_clcb->p_srcb->p_srvc_cache)
1450 {
1451 status = bta_gattc_find_record(p_clcb->p_srcb,
1452 query_type,
1453 p_srvc_id,
1454 p_start_rec,
1455 p_uuid_cond,
1456 p_output,
1457 p_param);
1458 }
1459 else
1460 {
1461 status = BTA_GATT_ERROR;
1462 APPL_TRACE_ERROR("No server cache available");
1463 }
1464 }
1465 else
1466 {
1467 APPL_TRACE_ERROR("server cache not available, CLCB state = %d", p_clcb->state);
1468
1469 status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
1470 }
1471 }
1472 else
1473 {
1474 APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
1475 }
1476
1477 return status;
1478 }
1479
1480 /*******************************************************************************
1481 **
1482 ** Function bta_gattc_rebuild_cache
1483 **
1484 ** Description rebuild server cache from NV cache.
1485 **
1486 ** Parameters
1487 **
1488 ** Returns None.
1489 **
1490 *******************************************************************************/
bta_gattc_rebuild_cache(tBTA_GATTC_SERV * p_srvc_cb,UINT16 num_attr,tBTA_GATTC_NV_ATTR * p_attr,UINT16 attr_index)1491 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
1492 tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index)
1493 {
1494 /* first attribute loading, initialize buffer */
1495 APPL_TRACE_ERROR("bta_gattc_rebuild_cache");
1496 if (attr_index == 0)
1497 {
1498 while (p_srvc_cb->cache_buffer.p_first)
1499 GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
1500
1501 if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
1502 {
1503 APPL_TRACE_ERROR("allocate cache buffer failed, no resources");
1504 }
1505 else
1506 {
1507 p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
1508 }
1509 }
1510
1511 while (num_attr > 0 && p_attr != NULL)
1512 {
1513 switch (p_attr->attr_type)
1514 {
1515 case BTA_GATTC_ATTR_TYPE_SRVC:
1516 bta_gattc_add_srvc_to_cache(p_srvc_cb,
1517 p_attr->s_handle,
1518 p_attr->e_handle,
1519 &p_attr->uuid,
1520 p_attr->is_primary,
1521 p_attr->id);
1522 break;
1523
1524 case BTA_GATTC_ATTR_TYPE_CHAR:
1525 case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
1526 case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
1527 bta_gattc_add_attr_to_cache(p_srvc_cb,
1528 p_attr->s_handle,
1529 &p_attr->uuid,
1530 p_attr->prop,
1531 p_attr->attr_type);
1532 break;
1533 }
1534 p_attr ++;
1535 num_attr --;
1536 }
1537 }
1538
1539 /*******************************************************************************
1540 **
1541 ** Function bta_gattc_fill_nv_attr
1542 **
1543 ** Description fill a NV attribute entry value
1544 **
1545 ** Returns None.
1546 **
1547 *******************************************************************************/
bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR * p_attr,UINT8 type,UINT16 s_handle,UINT16 e_handle,UINT8 id,tBT_UUID uuid,UINT8 prop,BOOLEAN is_primary)1548 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
1549 UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop,
1550 BOOLEAN is_primary)
1551 {
1552 p_attr->s_handle = s_handle;
1553 p_attr->e_handle = e_handle;
1554 p_attr->attr_type = type;
1555 p_attr->is_primary = is_primary;
1556 p_attr->id = id;
1557 p_attr->prop = prop;
1558
1559 memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
1560 }
1561 /*******************************************************************************
1562 **
1563 ** Function bta_gattc_cache_save
1564 **
1565 ** Description save the server cache into NV
1566 **
1567 ** Returns None.
1568 **
1569 *******************************************************************************/
bta_gattc_cache_save(tBTA_GATTC_SERV * p_srvc_cb,UINT16 conn_id)1570 BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
1571 {
1572 tBTA_GATTC_CACHE *p_cur_srvc = p_srvc_cb->p_srvc_cache;
1573 UINT8 i = 0;
1574 UINT16 offset = 0;
1575 tBTA_GATTC_NV_ATTR nv_attr[BTA_GATTC_NV_LOAD_MAX];
1576 tBTA_GATTC_CACHE_ATTR *p_attr;
1577 tBT_UUID uuid;
1578
1579 while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX)
1580 {
1581 if (offset ++ >= p_srvc_cb->attr_index)
1582 {
1583 bta_gattc_fill_nv_attr(&nv_attr[i++],
1584 BTA_GATTC_ATTR_TYPE_SRVC,
1585 p_cur_srvc->s_handle,
1586 p_cur_srvc->e_handle,
1587 p_cur_srvc->service_uuid.id.inst_id,
1588 p_cur_srvc->service_uuid.id.uuid,
1589 0,
1590 p_cur_srvc->service_uuid.is_primary);
1591 }
1592
1593 p_attr = p_cur_srvc->p_attr;
1594
1595 for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next)
1596 {
1597 if (offset >= p_srvc_cb->attr_index)
1598 {
1599 if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16)
1600 {
1601 uuid.uu.uuid16 = p_attr->p_uuid->uuid16;
1602 }
1603 else
1604 {
1605 memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128);
1606 }
1607
1608 bta_gattc_fill_nv_attr(&nv_attr[i++],
1609 p_attr->attr_type,
1610 p_attr->attr_handle,
1611 0,
1612 p_attr->inst_id,
1613 uuid,
1614 p_attr->property,
1615 FALSE);
1616 }
1617 }
1618 p_cur_srvc = p_cur_srvc->p_next;
1619 }
1620
1621 if (i > 0)
1622 {
1623 bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i,
1624 nv_attr, p_srvc_cb->attr_index, conn_id);
1625
1626 p_srvc_cb->attr_index += i;
1627
1628 return TRUE;
1629 }
1630 else
1631 {
1632 return FALSE;
1633 }
1634 }
1635 #endif /* BTA_GATT_INCLUDED */
1636
1637