OSDN Git Service

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