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