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