OSDN Git Service

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