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