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