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