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