1/******************************************************************************
2 *
3 *  Copyright (C) 2009-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 GATT utility functions
22 *
23 ******************************************************************************/
24#include "bt_target.h"
25#include "bt_utils.h"
26
27#if BLE_INCLUDED == TRUE
28    #include <string.h>
29    #include "stdio.h"
30    #include "bt_common.h"
31
32    #include "l2cdefs.h"
33    #include "gatt_int.h"
34    #include "gatt_api.h"
35    #include "gattdefs.h"
36    #include "sdp_api.h"
37    #include "btm_int.h"
38/* check if [x, y] and [a, b] have overlapping range */
39    #define GATT_VALIDATE_HANDLE_RANGE(x, y, a, b)   (y >= a && x <= b)
40
41    #define GATT_GET_NEXT_VALID_HANDLE(x)    (((x)/10 + 1) * 10)
42
43const char * const op_code_name[] =
44{
45    "UNKNOWN",
46    "ATT_RSP_ERROR",
47    "ATT_REQ_MTU",
48    "ATT_RSP_MTU",
49    "ATT_REQ_READ_INFO",
50    "ATT_RSP_READ_INFO",
51    "ATT_REQ_FIND_TYPE_VALUE",
52    "ATT_RSP_FIND_TYPE_VALUE",
53    "ATT_REQ_READ_BY_TYPE",
54    "ATT_RSP_READ_BY_TYPE",
55    "ATT_REQ_READ",
56    "ATT_RSP_READ",
57    "ATT_REQ_READ_BLOB",
58    "ATT_RSP_READ_BLOB",
59    "GATT_REQ_READ_MULTI",
60    "GATT_RSP_READ_MULTI",
61    "GATT_REQ_READ_BY_GRP_TYPE",
62    "GATT_RSP_READ_BY_GRP_TYPE",
63    "ATT_REQ_WRITE",
64    "ATT_RSP_WRITE",
65    "ATT_CMD_WRITE",
66    "ATT_SIGN_CMD_WRITE",
67    "ATT_REQ_PREPARE_WRITE",
68    "ATT_RSP_PREPARE_WRITE",
69    "ATT_REQ_EXEC_WRITE",
70    "ATT_RSP_EXEC_WRITE",
71    "Reserved",
72    "ATT_HANDLE_VALUE_NOTIF",
73    "Reserved",
74    "ATT_HANDLE_VALUE_IND",
75    "ATT_HANDLE_VALUE_CONF",
76    "ATT_OP_CODE_MAX"
77};
78
79static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
80    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
81
82extern fixed_queue_t *btu_general_alarm_queue;
83
84/*******************************************************************************
85**
86** Function         gatt_free_pending_ind
87**
88** Description    Free all pending indications
89**
90** Returns       None
91**
92*******************************************************************************/
93void gatt_free_pending_ind(tGATT_TCB *p_tcb)
94{
95    GATT_TRACE_DEBUG("%s", __func__);
96
97    if (p_tcb->pending_ind_q == NULL)
98        return;
99
100    /* release all queued indications */
101    while (!fixed_queue_is_empty(p_tcb->pending_ind_q))
102        osi_free(fixed_queue_try_dequeue(p_tcb->pending_ind_q));
103    fixed_queue_free(p_tcb->pending_ind_q, NULL);
104    p_tcb->pending_ind_q = NULL;
105}
106
107/*******************************************************************************
108**
109** Function         gatt_free_pending_enc_queue
110**
111** Description       Free all buffers in pending encyption queue
112**
113** Returns       None
114**
115*******************************************************************************/
116void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb)
117{
118    GATT_TRACE_DEBUG("%s", __func__);
119
120    if (p_tcb->pending_enc_clcb == NULL)
121        return;
122
123    /* release all queued indications */
124    while (!fixed_queue_is_empty(p_tcb->pending_enc_clcb))
125        osi_free(fixed_queue_try_dequeue(p_tcb->pending_enc_clcb));
126    fixed_queue_free(p_tcb->pending_enc_clcb, NULL);
127    p_tcb->pending_enc_clcb = NULL;
128}
129
130/*******************************************************************************
131**
132** Function         gatt_delete_dev_from_srv_chg_clt_list
133**
134** Description    Delete a device from the service changed client lit
135**
136** Returns       None
137**
138*******************************************************************************/
139void gatt_delete_dev_from_srv_chg_clt_list(BD_ADDR bd_addr)
140{
141    GATT_TRACE_DEBUG("gatt_delete_dev_from_srv_chg_clt_list");
142
143    tGATTS_SRV_CHG *p_buf = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr);
144    if (p_buf != NULL)
145    {
146        if (gatt_cb.cb_info.p_srv_chg_callback)
147        {
148            /* delete from NV */
149            tGATTS_SRV_CHG_REQ req;
150            memcpy(req.srv_chg.bda, bd_addr, BD_ADDR_LEN);
151            (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_REMOVE_CLIENT,&req, NULL);
152        }
153        osi_free(fixed_queue_try_remove_from_queue(gatt_cb.srv_chg_clt_q,
154                                                      p_buf));
155    }
156}
157
158/*******************************************************************************
159**
160** Function         gatt_set_srv_chg
161**
162** Description      Set the service changed flag to TRUE
163**
164** Returns        None
165**
166*******************************************************************************/
167void gatt_set_srv_chg(void)
168{
169    GATT_TRACE_DEBUG ("gatt_set_srv_chg");
170
171    if (fixed_queue_is_empty(gatt_cb.srv_chg_clt_q))
172        return;
173
174    list_t *list = fixed_queue_get_list(gatt_cb.srv_chg_clt_q);
175    for (const list_node_t *node = list_begin(list); node != list_end(list);
176         node = list_next(node)) {
177        GATT_TRACE_DEBUG ("found a srv_chg clt");
178
179        tGATTS_SRV_CHG *p_buf = (tGATTS_SRV_CHG *)list_node(node);
180        if (!p_buf->srv_changed)
181        {
182            GATT_TRACE_DEBUG("set srv_changed to TRUE");
183            p_buf->srv_changed = TRUE;
184            tGATTS_SRV_CHG_REQ req;
185            memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
186            if (gatt_cb.cb_info.p_srv_chg_callback)
187                (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
188        }
189    }
190}
191
192/*******************************************************************************
193**
194** Function         gatt_sr_is_new_srv_chg
195**
196** Description     Find the app id in on the new service changed list
197**
198** Returns     Pointer to the found new service changed item othwerwise NULL
199**
200*******************************************************************************/
201tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
202{
203    tGATTS_PENDING_NEW_SRV_START *p_buf = NULL;
204
205    if (fixed_queue_is_empty(gatt_cb.pending_new_srv_start_q))
206        return NULL;
207
208    list_t *list = fixed_queue_get_list(gatt_cb.pending_new_srv_start_q);
209    for (const list_node_t *node = list_begin(list); node != list_end(list);
210         node = list_next(node)) {
211        p_buf = (tGATTS_PENDING_NEW_SRV_START *)list_node(node);
212        tGATTS_HNDL_RANGE *p = p_buf->p_new_srv_start;
213        if (gatt_uuid_compare(*p_app_uuid128, p->app_uuid128)
214            && gatt_uuid_compare (*p_svc_uuid, p->svc_uuid)
215            && (svc_inst == p->svc_inst)) {
216            GATT_TRACE_DEBUG("gatt_sr_is_new_srv_chg: Yes");
217            break;
218        }
219    }
220
221    return p_buf;
222}
223
224
225/*******************************************************************************
226**
227** Function     gatt_add_pending_ind
228**
229** Description  Add a pending indication
230**
231** Returns    Pointer to the current pending indication buffer, NULL no buffer available
232**
233*******************************************************************************/
234tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB  *p_tcb, tGATT_VALUE *p_ind)
235{
236    tGATT_VALUE *p_buf = (tGATT_VALUE *)osi_malloc(sizeof(tGATT_VALUE));
237
238    GATT_TRACE_DEBUG("%s", __func__);
239    GATT_TRACE_DEBUG("enqueue a pending indication");
240
241    memcpy(p_buf, p_ind, sizeof(tGATT_VALUE));
242    fixed_queue_enqueue(p_tcb->pending_ind_q, p_buf);
243
244    return p_buf;
245}
246
247/*******************************************************************************
248**
249** Function     gatt_add_pending_new_srv_start
250**
251** Description  Add a pending new srv start to the new service start queue
252**
253** Returns    Pointer to the new service start buffer, NULL no buffer available
254**
255*******************************************************************************/
256tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start(tGATTS_HNDL_RANGE *p_new_srv_start)
257{
258    tGATTS_PENDING_NEW_SRV_START *p_buf =
259        (tGATTS_PENDING_NEW_SRV_START *)osi_malloc(sizeof(tGATTS_PENDING_NEW_SRV_START));
260
261    GATT_TRACE_DEBUG("%s", __func__);
262    GATT_TRACE_DEBUG("enqueue a new pending new srv start");
263
264    p_buf->p_new_srv_start = p_new_srv_start;
265    fixed_queue_enqueue(gatt_cb.pending_new_srv_start_q, p_buf);
266
267    return p_buf;
268}
269
270
271/*******************************************************************************
272**
273** Function     gatt_add_srv_chg_clt
274**
275** Description  Add a service chnage client to the service change client queue
276**
277** Returns    Pointer to the service change client buffer; Null no buffer available
278**
279*******************************************************************************/
280tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg)
281{
282    tGATTS_SRV_CHG *p_buf = (tGATTS_SRV_CHG *)osi_malloc(sizeof(tGATTS_SRV_CHG));
283
284    GATT_TRACE_DEBUG("%s", __func__);
285    GATT_TRACE_DEBUG("enqueue a srv chg client");
286
287    memcpy(p_buf, p_srv_chg, sizeof(tGATTS_SRV_CHG));
288    fixed_queue_enqueue(gatt_cb.srv_chg_clt_q, p_buf);
289
290    return p_buf;
291}
292
293/*******************************************************************************
294**
295** Function     gatt_alloc_hdl_buffer
296**
297** Description  Allocate a handle buufer
298**
299** Returns    Pointer to the allocated buffer, NULL no buffer available
300**
301*******************************************************************************/
302tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void)
303{
304    UINT8 i;
305    tGATT_CB    *p_cb = &gatt_cb;
306    tGATT_HDL_LIST_ELEM * p_elem= &p_cb->hdl_list[0];
307
308    for (i = 0; i < GATT_MAX_SR_PROFILES; i++, p_elem++)
309    {
310        if (!p_cb->hdl_list[i].in_use)
311        {
312            memset(p_elem, 0, sizeof(tGATT_HDL_LIST_ELEM));
313            p_elem->in_use = TRUE;
314            p_elem->svc_db.svc_buffer = fixed_queue_new(SIZE_MAX);
315            return p_elem;
316        }
317    }
318
319    return NULL;
320}
321
322/*******************************************************************************
323**
324** Function     gatt_find_hdl_buffer_by_handle
325**
326** Description  Find handle range buffer by service handle.
327**
328** Returns    Pointer to the buffer, NULL no buffer available
329**
330*******************************************************************************/
331tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle)
332{
333    tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
334    tGATT_HDL_LIST_ELEM      *p_list = NULL;
335
336    p_list = p_list_info->p_first;
337
338    while (p_list != NULL)
339    {
340        if (p_list->in_use && p_list->asgn_range.s_handle == handle)
341        {
342            return(p_list);
343        }
344        p_list = p_list->p_next;
345    }
346    return NULL;
347}
348/*******************************************************************************
349**
350** Function     gatt_find_hdl_buffer_by_app_id
351**
352** Description  Find handle range buffer by app ID, service and service instance ID.
353**
354** Returns    Pointer to the buffer, NULL no buffer available
355**
356*******************************************************************************/
357tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128,
358                                                     tBT_UUID *p_svc_uuid,
359                                                     UINT16 svc_inst)
360{
361    tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
362    tGATT_HDL_LIST_ELEM      *p_list = NULL;
363
364    p_list = p_list_info->p_first;
365
366    while (p_list != NULL)
367    {
368        if ( gatt_uuid_compare (*p_app_uuid128, p_list->asgn_range.app_uuid128)
369             &&  gatt_uuid_compare (*p_svc_uuid,    p_list->asgn_range.svc_uuid)
370             &&  (svc_inst == p_list->asgn_range.svc_inst) )
371        {
372            GATT_TRACE_DEBUG ("Already allocated handles for this service before!!");
373            return(p_list);
374        }
375        p_list = p_list->p_next;
376    }
377    return NULL;
378}
379/*******************************************************************************
380**
381** Function         gatt_free_hdl_buffer
382**
383** Description     free a handle buffer
384**
385** Returns       None
386**
387*******************************************************************************/
388void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p)
389{
390
391    if (p)
392    {
393        while (!fixed_queue_is_empty(p->svc_db.svc_buffer))
394            osi_free(fixed_queue_try_dequeue(p->svc_db.svc_buffer));
395        fixed_queue_free(p->svc_db.svc_buffer, NULL);
396        memset(p, 0, sizeof(tGATT_HDL_LIST_ELEM));
397    }
398}
399/*******************************************************************************
400**
401** Function         gatt_free_srvc_db_buffer_app_id
402**
403** Description      free the service attribute database buffers by the owner of the
404**                  service app ID.
405**
406** Returns       None
407**
408*******************************************************************************/
409void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id)
410{
411    tGATT_HDL_LIST_ELEM *p_elem =  &gatt_cb.hdl_list[0];
412    UINT8   i;
413
414    for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_elem ++)
415    {
416        if (memcmp(p_app_id, &p_elem->asgn_range.app_uuid128, sizeof(tBT_UUID)) == 0)
417        {
418            while (!fixed_queue_is_empty(p_elem->svc_db.svc_buffer))
419                osi_free(fixed_queue_try_dequeue(p_elem->svc_db.svc_buffer));
420            fixed_queue_free(p_elem->svc_db.svc_buffer, NULL);
421            p_elem->svc_db.svc_buffer = NULL;
422
423            p_elem->svc_db.mem_free = 0;
424            p_elem->svc_db.p_attr_list = p_elem->svc_db.p_free_mem = NULL;
425        }
426    }
427}
428/*******************************************************************************
429**
430** Function         gatt_is_last_attribute
431**
432** Description     Check this is the last attribute of the specified value or not
433**
434** Returns       TRUE - yes this is the last attribute
435**
436*******************************************************************************/
437BOOLEAN gatt_is_last_attribute(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_start, tBT_UUID value)
438{
439    tGATT_SRV_LIST_ELEM *p_srv= p_start->p_next;
440    BOOLEAN              is_last_attribute = TRUE;
441    tGATT_SR_REG        *p_rcb = NULL;
442    tBT_UUID            *p_svc_uuid;
443
444    p_list->p_last_primary = NULL;
445
446    while (p_srv)
447    {
448        p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
449
450        p_svc_uuid = gatts_get_service_uuid (p_rcb->p_db);
451
452        if (gatt_uuid_compare(value, *p_svc_uuid))
453        {
454            is_last_attribute = FALSE;
455            break;
456
457        }
458        p_srv = p_srv->p_next;
459    }
460
461    return is_last_attribute;
462
463}
464
465/*******************************************************************************
466**
467** Function         gatt_update_last_pri_srv_info
468**
469** Description     Update the the last primary info for the service list info
470**
471** Returns       None
472**
473*******************************************************************************/
474void gatt_update_last_pri_srv_info(tGATT_SRV_LIST_INFO *p_list)
475{
476    tGATT_SRV_LIST_ELEM *p_srv= p_list->p_first;
477
478    p_list->p_last_primary = NULL;
479
480    while (p_srv)
481    {
482        if (p_srv->is_primary)
483        {
484            p_list->p_last_primary = p_srv;
485        }
486        p_srv = p_srv->p_next;
487    }
488
489}
490/*******************************************************************************
491**
492** Function         gatts_update_srv_list_elem
493**
494** Description      update an element in the service list.
495**
496** Returns          None.
497**
498*******************************************************************************/
499void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary)
500{
501    UNUSED(handle);
502
503    gatt_cb.srv_list[i_sreg].in_use         = TRUE;
504    gatt_cb.srv_list[i_sreg].i_sreg    = i_sreg;
505    gatt_cb.srv_list[i_sreg].s_hdl          = gatt_cb.sr_reg[i_sreg].s_hdl;
506    gatt_cb.srv_list[i_sreg].is_primary     = is_primary;
507
508    return;
509}
510/*******************************************************************************
511**
512** Function  gatt_add_a_srv_to_list
513**
514** Description  add an service to the list in ascending
515**              order of the start handle
516**
517** Returns   BOOLEAN TRUE-if add is successful
518**
519*******************************************************************************/
520BOOLEAN gatt_add_a_srv_to_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_new)
521{
522    tGATT_SRV_LIST_ELEM *p_old;
523
524    if (!p_new)
525    {
526        GATT_TRACE_DEBUG("p_new==NULL");
527        return FALSE;
528    }
529
530    if (!p_list->p_first)
531    {
532        /* this is an empty list */
533        p_list->p_first =
534        p_list->p_last  = p_new;
535        p_new->p_next   =
536        p_new->p_prev   = NULL;
537    }
538    else
539    {
540        p_old = p_list->p_first;
541        while (1)
542        {
543            if (p_old == NULL)
544            {
545                p_list->p_last->p_next      = p_new;
546                p_new->p_prev               = p_list->p_last;
547                p_new->p_next               = NULL;
548                p_list->p_last              = p_new;
549                break;
550            }
551            else
552            {
553                if (p_new->s_hdl <  p_old->s_hdl)
554                {
555                    /* if not the first in list */
556                    if (p_old->p_prev != NULL)
557                        p_old->p_prev->p_next   = p_new;
558                    else
559                        p_list->p_first = p_new;
560
561                    p_new->p_prev           = p_old->p_prev;
562                    p_new->p_next           = p_old;
563                    p_old->p_prev           = p_new;
564                    break;
565                }
566            }
567            p_old = p_old->p_next;
568        }
569    }
570    p_list->count++;
571
572    gatt_update_last_pri_srv_info(p_list);
573    return TRUE;
574
575}
576
577/*******************************************************************************
578**
579** Function  gatt_remove_a_srv_from_list
580**
581** Description  Remove a service from the list
582**
583** Returns   BOOLEAN TRUE-if remove is successful
584**
585*******************************************************************************/
586BOOLEAN gatt_remove_a_srv_from_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_remove)
587{
588    if (!p_remove || !p_list->p_first)
589    {
590        GATT_TRACE_DEBUG("p_remove==NULL || p_list->p_first==NULL");
591        return FALSE;
592    }
593
594    if (p_remove->p_prev == NULL)
595    {
596        p_list->p_first             = p_remove->p_next;
597        if (p_remove->p_next)
598            p_remove->p_next->p_prev    = NULL;
599    }
600    else if (p_remove->p_next == NULL)
601    {
602        p_list->p_last              = p_remove->p_prev;
603        p_remove->p_prev->p_next    = NULL;
604    }
605    else
606    {
607        p_remove->p_next->p_prev = p_remove->p_prev;
608        p_remove->p_prev->p_next = p_remove->p_next;
609    }
610    p_list->count--;
611    gatt_update_last_pri_srv_info(p_list);
612    return TRUE;
613
614}
615
616/*******************************************************************************
617**
618** Function  gatt_add_an_item_to_list
619**
620** Description  add an service handle range to the list in decending
621**              order of the start handle
622**
623** Returns   BOOLEAN TRUE-if add is successful
624**
625*******************************************************************************/
626BOOLEAN gatt_add_an_item_to_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIST_ELEM *p_new)
627{
628    tGATT_HDL_LIST_ELEM *p_old;
629    if (!p_new)
630    {
631        GATT_TRACE_DEBUG("p_new==NULL");
632        return FALSE;
633    }
634
635    if (!p_list->p_first)
636    {
637        /* this is an empty list */
638        p_list->p_first =
639        p_list->p_last  = p_new;
640        p_new->p_next   =
641        p_new->p_prev   = NULL;
642    }
643    else
644    {
645        p_old = p_list->p_first;
646        while (1)
647        {
648            if (p_old == NULL)
649            {
650                p_list->p_last->p_next      = p_new;
651                p_new->p_prev               = p_list->p_last;
652                p_new->p_next               = NULL;
653                p_list->p_last              = p_new;
654
655                break;
656
657            }
658            else
659            {
660                if (p_new->asgn_range.s_handle >  p_old->asgn_range.s_handle)
661                {
662                    if (p_old == p_list->p_first)
663                        p_list->p_first = p_new;
664
665                    p_new->p_prev    = p_old->p_prev;
666                    p_new->p_next    = p_old;
667
668
669                    p_old->p_prev    = p_new;
670                    break;
671                }
672            }
673            p_old = p_old->p_next;
674        }
675    }
676    p_list->count++;
677    return TRUE;
678
679}
680
681/*******************************************************************************
682**
683** Function  gatt_remove_an_item_from_list
684**
685** Description  Remove an service handle range from the list
686**
687** Returns   BOOLEAN TRUE-if remove is successful
688**
689*******************************************************************************/
690BOOLEAN gatt_remove_an_item_from_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIST_ELEM *p_remove)
691{
692    if (!p_remove || !p_list->p_first)
693    {
694        GATT_TRACE_DEBUG("p_remove==NULL || p_list->p_first==NULL");
695        return FALSE;
696    }
697
698    if (p_remove->p_prev == NULL)
699    {
700        p_list->p_first             = p_remove->p_next;
701        if (p_remove->p_next)
702            p_remove->p_next->p_prev    = NULL;
703    }
704    else if (p_remove->p_next == NULL)
705    {
706        p_list->p_last              = p_remove->p_prev;
707        p_remove->p_prev->p_next    = NULL;
708    }
709    else
710    {
711        p_remove->p_next->p_prev = p_remove->p_prev;
712        p_remove->p_prev->p_next = p_remove->p_next;
713    }
714    p_list->count--;
715    return TRUE;
716
717}
718
719/*******************************************************************************
720**
721** Function         gatt_find_the_connected_bda
722**
723** Description      This function find the connected bda
724**
725** Returns           TRUE if found
726**
727*******************************************************************************/
728BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found_idx,
729                                    tBT_TRANSPORT *p_transport)
730{
731    UINT8 i;
732    BOOLEAN found = FALSE;
733    GATT_TRACE_DEBUG("gatt_find_the_connected_bda start_idx=%d",start_idx);
734
735    for (i = start_idx ; i < GATT_MAX_PHY_CHANNEL; i ++)
736    {
737        if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].ch_state == GATT_CH_OPEN)
738        {
739            memcpy( bda, gatt_cb.tcb[i].peer_bda, BD_ADDR_LEN);
740            *p_found_idx = i;
741            *p_transport = gatt_cb.tcb[i].transport;
742            found = TRUE;
743            GATT_TRACE_DEBUG("gatt_find_the_connected_bda bda :%02x-%02x-%02x-%02x-%02x-%02x",
744                              bda[0],  bda[1], bda[2],  bda[3], bda[4],  bda[5]);
745            break;
746        }
747    }
748    GATT_TRACE_DEBUG("gatt_find_the_connected_bda found=%d found_idx=%d", found, i);
749    return found;
750}
751
752
753
754/*******************************************************************************
755**
756** Function         gatt_is_srv_chg_ind_pending
757**
758** Description      Check whether a service chnaged is in the indication pending queue
759**                  or waiting for an Ack already
760**
761** Returns         BOOLEAN
762**
763*******************************************************************************/
764BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb)
765{
766    BOOLEAN srv_chg_ind_pending = FALSE;
767
768    GATT_TRACE_DEBUG("gatt_is_srv_chg_ind_pending is_queue_empty=%d",
769                     fixed_queue_is_empty(p_tcb->pending_ind_q));
770
771    if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r)
772    {
773        srv_chg_ind_pending = TRUE;
774    }
775    else if (! fixed_queue_is_empty(p_tcb->pending_ind_q))
776    {
777        list_t *list = fixed_queue_get_list(p_tcb->pending_ind_q);
778        for (const list_node_t *node = list_begin(list);
779             node != list_end(list);
780             node = list_next(node)) {
781            tGATT_VALUE *p_buf = (tGATT_VALUE *)list_node(node);
782            if (p_buf->handle == gatt_cb.handle_of_h_r)
783            {
784                srv_chg_ind_pending = TRUE;
785                break;
786            }
787        }
788    }
789
790    GATT_TRACE_DEBUG("srv_chg_ind_pending = %d", srv_chg_ind_pending);
791    return srv_chg_ind_pending;
792}
793
794
795/*******************************************************************************
796**
797** Function         gatt_is_bda_in_the_srv_chg_clt_list
798**
799** Description      This function check the specified bda is in the srv chg clinet list or not
800**
801** Returns         pointer to the found elemenet otherwise NULL
802**
803*******************************************************************************/
804tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda)
805{
806    tGATTS_SRV_CHG *p_buf = NULL;
807
808    GATT_TRACE_DEBUG("gatt_is_bda_in_the_srv_chg_clt_list :%02x-%02x-%02x-%02x-%02x-%02x",
809                      bda[0],  bda[1], bda[2],  bda[3], bda[4],  bda[5]);
810
811    if (fixed_queue_is_empty(gatt_cb.srv_chg_clt_q))
812        return NULL;
813
814    list_t *list = fixed_queue_get_list(gatt_cb.srv_chg_clt_q);
815    for (const list_node_t *node = list_begin(list); node != list_end(list);
816         node = list_next(node)) {
817        tGATTS_SRV_CHG *p_buf = (tGATTS_SRV_CHG *)list_node(node);
818        if (!memcmp( bda, p_buf->bda, BD_ADDR_LEN))
819        {
820            GATT_TRACE_DEBUG("bda is in the srv chg clt list");
821            break;
822        }
823    }
824
825    return p_buf;
826}
827
828
829/*******************************************************************************
830**
831** Function         gatt_is_bda_connected
832**
833** Description
834**
835** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
836**
837*******************************************************************************/
838BOOLEAN gatt_is_bda_connected(BD_ADDR bda)
839{
840    UINT8 i = 0;
841    BOOLEAN connected=FALSE;
842
843    for ( i=0; i < GATT_MAX_PHY_CHANNEL; i ++)
844    {
845        if (gatt_cb.tcb[i].in_use &&
846            !memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN))
847        {
848            connected = TRUE;
849            break;
850        }
851    }
852    return connected;
853}
854
855/*******************************************************************************
856**
857** Function         gatt_find_i_tcb_by_addr
858**
859** Description      The function searches for an empty tcb entry, and return the index.
860**
861** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
862**
863*******************************************************************************/
864UINT8 gatt_find_i_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport)
865{
866    UINT8 i = 0;
867
868    for ( ; i < GATT_MAX_PHY_CHANNEL; i ++)
869    {
870        if (!memcmp(gatt_cb.tcb[i].peer_bda, bda, BD_ADDR_LEN) &&
871            gatt_cb.tcb[i].transport == transport)
872        {
873            return i;
874        }
875    }
876    return GATT_INDEX_INVALID;
877}
878
879
880/*******************************************************************************
881**
882** Function         gatt_get_tcb_by_idx
883**
884** Description      The function get TCB using the TCB index
885**
886** Returns           NULL if not found. Otherwise index to the tcb.
887**
888*******************************************************************************/
889tGATT_TCB * gatt_get_tcb_by_idx(UINT8 tcb_idx)
890{
891    tGATT_TCB   *p_tcb = NULL;
892
893    if ( (tcb_idx < GATT_MAX_PHY_CHANNEL) && gatt_cb.tcb[tcb_idx].in_use)
894        p_tcb = &gatt_cb.tcb[tcb_idx];
895
896    return p_tcb;
897}
898
899/*******************************************************************************
900**
901** Function         gatt_find_tcb_by_addr
902**
903** Description      The function searches for an empty tcb entry, and return pointer.
904**
905** Returns           NULL if not found. Otherwise index to the tcb.
906**
907*******************************************************************************/
908tGATT_TCB * gatt_find_tcb_by_addr(BD_ADDR bda, tBT_TRANSPORT transport)
909{
910    tGATT_TCB   *p_tcb = NULL;
911    UINT8 i = 0;
912
913    if ((i = gatt_find_i_tcb_by_addr(bda, transport)) != GATT_INDEX_INVALID)
914        p_tcb = &gatt_cb.tcb[i];
915
916    return p_tcb;
917}
918/*******************************************************************************
919**
920** Function         gatt_find_i_tcb_free
921**
922** Description      The function searches for an empty tcb entry, and return the index.
923**
924** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
925**
926*******************************************************************************/
927UINT8 gatt_find_i_tcb_free(void)
928{
929    UINT8 i = 0, j = GATT_INDEX_INVALID;
930
931    for (i = 0; i < GATT_MAX_PHY_CHANNEL; i ++)
932    {
933        if (!gatt_cb.tcb[i].in_use)
934        {
935            j = i;
936            break;
937        }
938    }
939    return j;
940}
941/*******************************************************************************
942**
943** Function         gatt_allocate_tcb_by_bdaddr
944**
945** Description      The function locate or allocate new tcb entry for matching bda.
946**
947** Returns           GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
948**
949*******************************************************************************/
950tGATT_TCB * gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport)
951{
952    UINT8 i = 0;
953    BOOLEAN allocated = FALSE;
954    tGATT_TCB    *p_tcb = NULL;
955
956    /* search for existing tcb with matching bda    */
957    i = gatt_find_i_tcb_by_addr(bda, transport);
958    /* find free tcb */
959    if (i == GATT_INDEX_INVALID)
960    {
961        i = gatt_find_i_tcb_free();
962        allocated = TRUE;
963    }
964    if (i != GATT_INDEX_INVALID)
965    {
966        p_tcb = &gatt_cb.tcb[i];
967
968        if (allocated)
969        {
970            memset(p_tcb, 0, sizeof(tGATT_TCB));
971            p_tcb->pending_enc_clcb = fixed_queue_new(SIZE_MAX);
972            p_tcb->pending_ind_q = fixed_queue_new(SIZE_MAX);
973            p_tcb->conf_timer = alarm_new("gatt.conf_timer");
974            p_tcb->ind_ack_timer = alarm_new("gatt.ind_ack_timer");
975            p_tcb->sr_cmd.multi_rsp_q = fixed_queue_new(SIZE_MAX);
976            p_tcb->in_use = TRUE;
977            p_tcb->tcb_idx = i;
978            p_tcb->transport = transport;
979        }
980        memcpy(p_tcb->peer_bda, bda, BD_ADDR_LEN);
981    }
982    return p_tcb;
983}
984
985/*******************************************************************************
986**
987** Function         gatt_convert_uuid16_to_uuid128
988**
989** Description      Convert a 16 bits UUID to be an standard 128 bits one.
990**
991** Returns          TRUE if two uuid match; FALSE otherwise.
992**
993*******************************************************************************/
994void gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
995{
996    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
997
998    memcpy (uuid_128, base_uuid, LEN_UUID_128);
999
1000    UINT16_TO_STREAM(p, uuid_16);
1001}
1002
1003/*******************************************************************************
1004**
1005** Function         gatt_convert_uuid32_to_uuid128
1006**
1007** Description      Convert a 32 bits UUID to be an standard 128 bits one.
1008**
1009** Returns          TRUE if two uuid match; FALSE otherwise.
1010**
1011*******************************************************************************/
1012void gatt_convert_uuid32_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT32 uuid_32)
1013{
1014    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
1015
1016    memcpy (uuid_128, base_uuid, LEN_UUID_128);
1017
1018    UINT32_TO_STREAM(p, uuid_32);
1019}
1020/*******************************************************************************
1021**
1022** Function         gatt_uuid_compare
1023**
1024** Description      Compare two UUID to see if they are the same.
1025**
1026** Returns          TRUE if two uuid match; FALSE otherwise.
1027**
1028*******************************************************************************/
1029BOOLEAN gatt_uuid_compare (tBT_UUID src, tBT_UUID tar)
1030{
1031    UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
1032    UINT8  *ps, *pt;
1033
1034    /* any of the UUID is unspecified */
1035    if (src.len == 0 || tar.len == 0)
1036    {
1037        return TRUE;
1038    }
1039
1040    /* If both are 16-bit, we can do a simple compare */
1041    if (src.len == LEN_UUID_16 && tar.len == LEN_UUID_16)
1042    {
1043        return src.uu.uuid16 == tar.uu.uuid16;
1044    }
1045
1046    /* If both are 32-bit, we can do a simple compare */
1047    if (src.len == LEN_UUID_32 && tar.len == LEN_UUID_32)
1048    {
1049        return src.uu.uuid32 == tar.uu.uuid32;
1050    }
1051
1052    /* One or both of the UUIDs is 128-bit */
1053    if (src.len == LEN_UUID_16)
1054    {
1055        /* convert a 16 bits UUID to 128 bits value */
1056        gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
1057        ps = su;
1058    }
1059    else if (src.len == LEN_UUID_32)
1060    {
1061        gatt_convert_uuid32_to_uuid128(su, src.uu.uuid32);
1062        ps = su;
1063    }
1064    else
1065        ps = src.uu.uuid128;
1066
1067    if (tar.len == LEN_UUID_16)
1068    {
1069        /* convert a 16 bits UUID to 128 bits value */
1070        gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
1071        pt = tu;
1072    }
1073    else if (tar.len == LEN_UUID_32)
1074    {
1075        /* convert a 32 bits UUID to 128 bits value */
1076        gatt_convert_uuid32_to_uuid128(tu, tar.uu.uuid32);
1077        pt = tu;
1078    }
1079    else
1080        pt = tar.uu.uuid128;
1081
1082    return(memcmp(ps, pt, LEN_UUID_128) == 0);
1083}
1084
1085/*******************************************************************************
1086**
1087** Function         gatt_build_uuid_to_stream
1088**
1089** Description      Add UUID into stream.
1090**
1091** Returns          UUID length.
1092**
1093*******************************************************************************/
1094UINT8 gatt_build_uuid_to_stream(UINT8 **p_dst, tBT_UUID uuid)
1095{
1096    UINT8   *p = *p_dst;
1097    UINT8   len = 0;
1098
1099    if (uuid.len == LEN_UUID_16)
1100    {
1101        UINT16_TO_STREAM (p, uuid.uu.uuid16);
1102        len = LEN_UUID_16;
1103    }
1104    else if (uuid.len == LEN_UUID_32) /* always convert 32 bits into 128 bits as alwats */
1105    {
1106        gatt_convert_uuid32_to_uuid128(p, uuid.uu.uuid32);
1107        p += LEN_UUID_128;
1108        len = LEN_UUID_128;
1109    }
1110    else if (uuid.len == LEN_UUID_128)
1111    {
1112        ARRAY_TO_STREAM (p, uuid.uu.uuid128, LEN_UUID_128);
1113        len = LEN_UUID_128;
1114    }
1115
1116    *p_dst = p;
1117    return len;
1118}
1119
1120/*******************************************************************************
1121**
1122** Function         gatt_parse_uuid_from_cmd
1123**
1124** Description      Convert a 128 bits UUID into a 16 bits UUID.
1125**
1126** Returns          TRUE if command sent, otherwise FALSE.
1127**
1128*******************************************************************************/
1129BOOLEAN gatt_parse_uuid_from_cmd(tBT_UUID *p_uuid_rec, UINT16 uuid_size, UINT8 **p_data)
1130{
1131    BOOLEAN is_base_uuid, ret = TRUE;
1132    UINT8  xx;
1133    UINT8 *p_uuid = *p_data;
1134
1135    memset(p_uuid_rec, 0, sizeof(tBT_UUID));
1136
1137    switch (uuid_size)
1138    {
1139        case LEN_UUID_16:
1140            p_uuid_rec->len = uuid_size;
1141            STREAM_TO_UINT16 (p_uuid_rec->uu.uuid16, p_uuid);
1142            *p_data += LEN_UUID_16;
1143            break;
1144
1145        case LEN_UUID_128:
1146            /* See if we can compress his UUID down to 16 or 32bit UUIDs */
1147            is_base_uuid = TRUE;
1148            for (xx = 0; xx < LEN_UUID_128 - 4; xx++)
1149            {
1150                if (p_uuid[xx] != base_uuid[xx])
1151                {
1152                    is_base_uuid = FALSE;
1153                    break;
1154                }
1155            }
1156            if (is_base_uuid)
1157            {
1158                if ((p_uuid[LEN_UUID_128 - 1] == 0) && (p_uuid[LEN_UUID_128 - 2] == 0))
1159                {
1160                    p_uuid += (LEN_UUID_128 - 4);
1161                    p_uuid_rec->len = LEN_UUID_16;
1162                    STREAM_TO_UINT16(p_uuid_rec->uu.uuid16, p_uuid);
1163                }
1164                else
1165                {
1166                    p_uuid += (LEN_UUID_128 - LEN_UUID_32);
1167                    p_uuid_rec->len = LEN_UUID_32;
1168                    STREAM_TO_UINT32(p_uuid_rec->uu.uuid32, p_uuid);
1169                }
1170            }
1171            if (!is_base_uuid)
1172            {
1173                p_uuid_rec->len = LEN_UUID_128;
1174                memcpy(p_uuid_rec->uu.uuid128, p_uuid, LEN_UUID_128);
1175            }
1176            *p_data += LEN_UUID_128;
1177            break;
1178
1179        /* do not allow 32 bits UUID in ATT PDU now */
1180        case LEN_UUID_32:
1181            GATT_TRACE_ERROR("DO NOT ALLOW 32 BITS UUID IN ATT PDU");
1182        case 0:
1183        default:
1184            if (uuid_size != 0) ret = FALSE;
1185            GATT_TRACE_WARNING("gatt_parse_uuid_from_cmd invalid uuid size");
1186            break;
1187    }
1188
1189    return( ret);
1190}
1191
1192/*******************************************************************************
1193**
1194** Function         gatt_start_rsp_timer
1195**
1196** Description      Start a wait_for_response timer.
1197**
1198** Returns          void
1199**
1200*******************************************************************************/
1201void gatt_start_rsp_timer(UINT16 clcb_idx)
1202{
1203    tGATT_CLCB *p_clcb = &gatt_cb.clcb[clcb_idx];
1204    period_ms_t timeout_ms = GATT_WAIT_FOR_RSP_TIMEOUT_MS;
1205
1206    if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
1207        p_clcb->op_subtype == GATT_DISC_SRVC_ALL) {
1208        timeout_ms = GATT_WAIT_FOR_DISC_RSP_TIMEOUT_MS;
1209    }
1210
1211    // TODO: The tGATT_CLCB memory and state management needs cleanup,
1212    // and then the timers can be allocated elsewhere.
1213    if (p_clcb->gatt_rsp_timer_ent == NULL) {
1214        p_clcb->gatt_rsp_timer_ent = alarm_new("gatt.gatt_rsp_timer_ent");
1215    }
1216    alarm_set_on_queue(p_clcb->gatt_rsp_timer_ent, timeout_ms,
1217                       gatt_rsp_timeout, p_clcb, btu_general_alarm_queue);
1218}
1219
1220/*******************************************************************************
1221**
1222** Function         gatt_start_conf_timer
1223**
1224** Description      Start a wait_for_confirmation timer.
1225**
1226** Returns          void
1227**
1228*******************************************************************************/
1229void gatt_start_conf_timer(tGATT_TCB *p_tcb)
1230{
1231    alarm_set_on_queue(p_tcb->conf_timer, GATT_WAIT_FOR_RSP_TIMEOUT_MS,
1232                       gatt_indication_confirmation_timeout, p_tcb,
1233                       btu_general_alarm_queue);
1234}
1235
1236/*******************************************************************************
1237**
1238** Function         gatt_start_ind_ack_timer
1239**
1240** Description      start the application ack timer
1241**
1242** Returns          void
1243**
1244*******************************************************************************/
1245void gatt_start_ind_ack_timer(tGATT_TCB *p_tcb)
1246{
1247    /* start notification cache timer */
1248    alarm_set_on_queue(p_tcb->ind_ack_timer, GATT_WAIT_FOR_RSP_TIMEOUT_MS,
1249                       gatt_ind_ack_timeout, p_tcb, btu_general_alarm_queue);
1250}
1251
1252/*******************************************************************************
1253**
1254** Function         gatt_rsp_timeout
1255**
1256** Description      Called when GATT wait for ATT command response timer expires
1257**
1258** Returns          void
1259**
1260*******************************************************************************/
1261void gatt_rsp_timeout(void *data)
1262{
1263    tGATT_CLCB *p_clcb = (tGATT_CLCB *)data;
1264
1265    if (p_clcb == NULL || p_clcb->p_tcb == NULL)
1266    {
1267        GATT_TRACE_WARNING("%s clcb is already deleted", __func__);
1268        return;
1269    }
1270    if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
1271        p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
1272        p_clcb->retry_count < GATT_REQ_RETRY_LIMIT)
1273    {
1274        UINT8 rsp_code;
1275        GATT_TRACE_WARNING("%s retry discovery primary service", __func__);
1276        if (p_clcb != gatt_cmd_dequeue(p_clcb->p_tcb, &rsp_code))
1277        {
1278            GATT_TRACE_ERROR("%s command queue out of sync, disconnect",
1279                             __func__);
1280        }
1281        else
1282        {
1283            p_clcb->retry_count++;
1284            gatt_act_discovery(p_clcb);
1285            return;
1286        }
1287    }
1288
1289    GATT_TRACE_WARNING("%s disconnecting...", __func__);
1290    gatt_disconnect (p_clcb->p_tcb);
1291}
1292
1293/*******************************************************************************
1294**
1295** Function         gatt_indication_confirmation_timeout
1296**
1297** Description      Called when the indication confirmation timer expires
1298**
1299** Returns          void
1300**
1301*******************************************************************************/
1302void gatt_indication_confirmation_timeout(void *data)
1303{
1304    tGATT_TCB *p_tcb = (tGATT_TCB *)data;
1305
1306    GATT_TRACE_WARNING("%s disconnecting...", __func__);
1307    gatt_disconnect(p_tcb);
1308}
1309
1310/*******************************************************************************
1311**
1312** Function         gatt_ind_ack_timeout
1313**
1314** Description      Called when GATT wait for ATT handle confirmation timeout
1315**
1316** Returns          void
1317**
1318*******************************************************************************/
1319void gatt_ind_ack_timeout(void *data)
1320{
1321    tGATT_TCB *p_tcb = (tGATT_TCB *)data;
1322
1323    GATT_TRACE_WARNING("%s send ack now", __func__);
1324
1325    if (p_tcb != NULL)
1326        p_tcb->ind_count = 0;
1327
1328    attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
1329}
1330/*******************************************************************************
1331**
1332** Function         gatt_sr_find_i_rcb_by_handle
1333**
1334** Description      The function searches for a service that owns a specific handle.
1335**
1336** Returns          GATT_MAX_SR_PROFILES if not found. Otherwise index of th eservice.
1337**
1338*******************************************************************************/
1339UINT8 gatt_sr_find_i_rcb_by_handle(UINT16 handle)
1340{
1341    UINT8  i_rcb = 0;
1342
1343    for ( ; i_rcb < GATT_MAX_SR_PROFILES; i_rcb++)
1344    {
1345        if (gatt_cb.sr_reg[i_rcb].in_use &&
1346            gatt_cb.sr_reg[i_rcb].s_hdl <= handle &&
1347            gatt_cb.sr_reg[i_rcb].e_hdl >= handle )
1348        {
1349            break;
1350        }
1351    }
1352    return i_rcb;
1353}
1354
1355/*******************************************************************************
1356**
1357** Function         gatt_sr_find_i_rcb_by_handle
1358**
1359** Description      The function searches for a service that owns a specific handle.
1360**
1361** Returns          0 if not found. Otherwise index of th eservice.
1362**
1363*******************************************************************************/
1364UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
1365{
1366    UINT8           i_rcb = 0;
1367    tGATT_SR_REG    *p_sreg;
1368    tBT_UUID        *p_this_uuid;
1369
1370    for (i_rcb = 0, p_sreg = gatt_cb.sr_reg; i_rcb < GATT_MAX_SR_PROFILES; i_rcb++, p_sreg++)
1371    {
1372        if ( p_sreg->in_use )
1373        {
1374            p_this_uuid = gatts_get_service_uuid (p_sreg->p_db);
1375
1376            if (p_this_uuid &&
1377                gatt_uuid_compare (*p_app_uuid128, p_sreg->app_uuid ) &&
1378                gatt_uuid_compare (*p_svc_uuid, *p_this_uuid) &&
1379                (svc_inst == p_sreg->service_instance))
1380            {
1381                GATT_TRACE_ERROR ("Active Service Found ");
1382                gatt_dbg_display_uuid(*p_svc_uuid);
1383
1384                break;
1385            }
1386        }
1387    }
1388    return i_rcb;
1389}
1390/*******************************************************************************
1391**
1392** Function         gatt_sr_find_i_rcb_by_handle
1393**
1394** Description      The function searches for a service that owns a specific handle.
1395**
1396** Returns          0 if not found. Otherwise index of th eservice.
1397**
1398*******************************************************************************/
1399UINT8 gatt_sr_alloc_rcb(tGATT_HDL_LIST_ELEM *p_list )
1400{
1401    UINT8   ii = 0;
1402    tGATT_SR_REG    *p_sreg = NULL;
1403
1404    /*this is a new application servoce start */
1405    for (ii = 0, p_sreg = gatt_cb.sr_reg; ii < GATT_MAX_SR_PROFILES; ii++, p_sreg++)
1406    {
1407        if (!p_sreg->in_use)
1408        {
1409            memset (p_sreg, 0, sizeof(tGATT_SR_REG));
1410
1411            p_sreg->in_use = TRUE;
1412            memcpy (&p_sreg->app_uuid, &p_list->asgn_range.app_uuid128, sizeof(tBT_UUID));
1413
1414            p_sreg->service_instance    = p_list->asgn_range.svc_inst;
1415            p_sreg->type                = p_list->asgn_range.is_primary ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
1416            p_sreg->s_hdl               = p_list->asgn_range.s_handle;
1417            p_sreg->e_hdl               = p_list->asgn_range.e_handle;
1418            p_sreg->p_db                = &p_list->svc_db;
1419
1420            GATT_TRACE_DEBUG("total buffer in db [%d]",
1421                             fixed_queue_length(p_sreg->p_db->svc_buffer));
1422            break;
1423        }
1424    }
1425
1426    return ii;
1427}
1428/*******************************************************************************
1429**
1430** Function         gatt_sr_get_sec_info
1431**
1432** Description      Get the security flag and key size information for the peer
1433**                  device.
1434**
1435** Returns          void
1436**
1437*******************************************************************************/
1438void gatt_sr_get_sec_info(BD_ADDR rem_bda, tBT_TRANSPORT transport, UINT8 *p_sec_flag, UINT8 *p_key_size)
1439{
1440    UINT8           sec_flag = 0;
1441
1442    BTM_GetSecurityFlagsByTransport(rem_bda, &sec_flag, transport);
1443
1444    sec_flag &= (GATT_SEC_FLAG_LKEY_UNAUTHED | GATT_SEC_FLAG_LKEY_AUTHED | GATT_SEC_FLAG_ENCRYPTED);
1445
1446    *p_key_size = btm_ble_read_sec_key_size(rem_bda);
1447    *p_sec_flag = sec_flag;
1448}
1449/*******************************************************************************
1450**
1451** Function         gatt_sr_send_req_callback
1452**
1453** Description
1454**
1455**
1456** Returns          void
1457**
1458*******************************************************************************/
1459void gatt_sr_send_req_callback(UINT16 conn_id,
1460                               UINT32 trans_id,
1461                               tGATTS_REQ_TYPE type, tGATTS_DATA *p_data)
1462{
1463    tGATT_IF        gatt_if = GATT_GET_GATT_IF(conn_id);
1464    tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1465
1466    if (!p_reg )
1467    {
1468        GATT_TRACE_ERROR ("p_reg not found discard request");
1469        return;
1470    }
1471
1472    if ( p_reg->in_use &&
1473         p_reg->app_cb.p_req_cb)
1474    {
1475        (*p_reg->app_cb.p_req_cb)(conn_id, trans_id, type, p_data);
1476    }
1477    else
1478    {
1479        GATT_TRACE_WARNING("Call back not found for application conn_id=%d", conn_id);
1480    }
1481
1482}
1483
1484/*******************************************************************************
1485**
1486** Function         gatt_send_error_rsp
1487**
1488** Description      This function sends an error response.
1489**
1490** Returns          void
1491**
1492*******************************************************************************/
1493tGATT_STATUS gatt_send_error_rsp (tGATT_TCB *p_tcb, UINT8 err_code, UINT8 op_code,
1494                                  UINT16 handle, BOOLEAN deq)
1495{
1496    tGATT_ERROR      error;
1497    tGATT_STATUS     status;
1498    BT_HDR           *p_buf;
1499
1500    error.cmd_code = op_code;
1501    error.reason = err_code;
1502    error.handle =handle;
1503
1504    if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_ERROR, (tGATT_SR_MSG *)&error)) != NULL)
1505    {
1506        status = attp_send_sr_msg (p_tcb, p_buf);
1507    }
1508    else
1509        status = GATT_INSUF_RESOURCE;
1510
1511    if (deq)
1512        gatt_dequeue_sr_cmd(p_tcb);
1513
1514    return status;
1515}
1516
1517
1518/*******************************************************************************
1519**
1520** Function         gatt_add_sdp_record
1521**
1522** Description      This function add a SDP record for a GATT primary service
1523**
1524** Returns          0 if error else sdp handle for the record.
1525**
1526*******************************************************************************/
1527UINT32 gatt_add_sdp_record (tBT_UUID *p_uuid, UINT16 start_hdl, UINT16 end_hdl)
1528{
1529    tSDP_PROTOCOL_ELEM  proto_elem_list[2];
1530    UINT32              sdp_handle;
1531    UINT16              list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
1532    UINT8               buff[60];
1533    UINT8               *p = buff;
1534
1535    GATT_TRACE_DEBUG("gatt_add_sdp_record s_hdl=0x%x  s_hdl=0x%x",start_hdl, end_hdl);
1536
1537    if ((sdp_handle = SDP_CreateRecord()) == 0)
1538        return 0;
1539
1540    switch (p_uuid->len)
1541    {
1542        case LEN_UUID_16:
1543            SDP_AddServiceClassIdList(sdp_handle, 1, &p_uuid->uu.uuid16);
1544            break;
1545
1546        case LEN_UUID_32:
1547            UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
1548            UINT32_TO_BE_STREAM (p, p_uuid->uu.uuid32);
1549            SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST, DATA_ELE_SEQ_DESC_TYPE,
1550                              (UINT32) (p - buff), buff);
1551            break;
1552
1553        case LEN_UUID_128:
1554            UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
1555            ARRAY_TO_BE_STREAM_REVERSE (p, p_uuid->uu.uuid128, LEN_UUID_128);
1556            SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_CLASS_ID_LIST, DATA_ELE_SEQ_DESC_TYPE,
1557                              (UINT32) (p - buff), buff);
1558            break;
1559
1560        default:
1561            GATT_TRACE_ERROR("inavlid UUID len=%d", p_uuid->len);
1562            SDP_DeleteRecord(sdp_handle);
1563            return 0;
1564            break;
1565    }
1566
1567    /*** Fill out the protocol element sequence for SDP ***/
1568    proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
1569    proto_elem_list[0].num_params    = 1;
1570    proto_elem_list[0].params[0]     = BT_PSM_ATT;
1571    proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_ATT;
1572    proto_elem_list[1].num_params    = 2;
1573    proto_elem_list[1].params[0]     = start_hdl;
1574    proto_elem_list[1].params[1]     = end_hdl;
1575
1576    SDP_AddProtocolList(sdp_handle, 2, proto_elem_list);
1577
1578    /* Make the service browseable */
1579    SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list);
1580
1581    return(sdp_handle);
1582}
1583
1584
1585    #if GATT_CONFORMANCE_TESTING == TRUE
1586/*******************************************************************************
1587**
1588** Function         gatt_set_err_rsp
1589**
1590** Description      This function is called to set the test confirm value
1591**
1592** Returns          void
1593**
1594*******************************************************************************/
1595void gatt_set_err_rsp(BOOLEAN enable, UINT8 req_op_code, UINT8 err_status)
1596{
1597    GATT_TRACE_DEBUG("gatt_set_err_rsp enable=%d op_code=%d, err_status=%d", enable, req_op_code, err_status);
1598    gatt_cb.enable_err_rsp  = enable;
1599    gatt_cb.req_op_code     = req_op_code;
1600    gatt_cb.err_status      = err_status;
1601}
1602    #endif
1603
1604
1605
1606/*******************************************************************************
1607**
1608** Function         gatt_get_regcb
1609**
1610** Description      The function returns the registration control block.
1611**
1612** Returns          pointer to the registration control block or NULL
1613**
1614*******************************************************************************/
1615tGATT_REG *gatt_get_regcb (tGATT_IF gatt_if)
1616{
1617    UINT8           ii = (UINT8)gatt_if;
1618    tGATT_REG       *p_reg = NULL;
1619
1620    if (ii < 1 || ii > GATT_MAX_APPS) {
1621        GATT_TRACE_WARNING("gatt_if out of range [ = %d]", ii);
1622        return NULL;
1623    }
1624
1625    // Index for cl_rcb is always 1 less than gatt_if.
1626    p_reg = &gatt_cb.cl_rcb[ii - 1];
1627
1628    if (!p_reg->in_use) {
1629        GATT_TRACE_WARNING("gatt_if found but not in use.");
1630        return NULL;
1631    }
1632
1633    return p_reg;
1634}
1635
1636
1637/*******************************************************************************
1638**
1639** Function         gatt_is_clcb_allocated
1640**
1641** Description      The function check clcb for conn_id is allocated or not
1642**
1643** Returns           True already allocated
1644**
1645*******************************************************************************/
1646
1647BOOLEAN gatt_is_clcb_allocated (UINT16 conn_id)
1648{
1649    UINT8         i = 0;
1650    BOOLEAN       is_allocated= FALSE;
1651
1652    for (i = 0; i < GATT_CL_MAX_LCB; i++)
1653    {
1654        if (gatt_cb.clcb[i].in_use && (gatt_cb.clcb[i].conn_id == conn_id))
1655        {
1656            is_allocated = TRUE;
1657            break;
1658        }
1659    }
1660
1661    return is_allocated;
1662}
1663
1664/*******************************************************************************
1665**
1666** Function         gatt_clcb_alloc
1667**
1668** Description      The function allocates a GATT  connection link control block
1669**
1670** Returns           NULL if not found. Otherwise pointer to the connection link block.
1671**
1672*******************************************************************************/
1673tGATT_CLCB *gatt_clcb_alloc (UINT16 conn_id)
1674{
1675    UINT8           i = 0;
1676    tGATT_CLCB      *p_clcb = NULL;
1677    tGATT_IF        gatt_if=GATT_GET_GATT_IF(conn_id);
1678    UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
1679    tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1680    tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1681
1682    for (i = 0; i < GATT_CL_MAX_LCB; i++)
1683    {
1684        if (!gatt_cb.clcb[i].in_use)
1685        {
1686            p_clcb = &gatt_cb.clcb[i];
1687
1688            p_clcb->in_use      = TRUE;
1689            p_clcb->conn_id     = conn_id;
1690            p_clcb->clcb_idx    = i;
1691            p_clcb->p_reg       = p_reg;
1692            p_clcb->p_tcb       = p_tcb;
1693            break;
1694        }
1695    }
1696    return p_clcb;
1697}
1698
1699/*******************************************************************************
1700**
1701** Function         gatt_clcb_dealloc
1702**
1703** Description      The function de allocates a GATT  connection link control block
1704**
1705** Returns         None
1706**
1707*******************************************************************************/
1708void gatt_clcb_dealloc (tGATT_CLCB *p_clcb)
1709{
1710    if (p_clcb && p_clcb->in_use)
1711    {
1712        alarm_free(p_clcb->gatt_rsp_timer_ent);
1713        memset(p_clcb, 0, sizeof(tGATT_CLCB));
1714    }
1715}
1716
1717
1718
1719/*******************************************************************************
1720**
1721** Function         gatt_find_tcb_by_cid
1722**
1723** Description      The function searches for an empty entry
1724**                   in registration info table for GATT client
1725**
1726** Returns           NULL if not found. Otherwise pointer to the rcb.
1727**
1728*******************************************************************************/
1729tGATT_TCB * gatt_find_tcb_by_cid (UINT16 lcid)
1730{
1731    UINT16       xx = 0;
1732    tGATT_TCB    *p_tcb = NULL;
1733
1734    for (xx = 0; xx < GATT_MAX_PHY_CHANNEL; xx++)
1735    {
1736        if (gatt_cb.tcb[xx].in_use && gatt_cb.tcb[xx].att_lcid == lcid)
1737        {
1738            p_tcb = &gatt_cb.tcb[xx];
1739            break;
1740        }
1741    }
1742    return p_tcb;
1743}
1744
1745
1746/*******************************************************************************
1747**
1748** Function         gatt_num_apps_hold_link
1749**
1750** Description      The function find the number of applcaitions is holding the link
1751**
1752** Returns          total number of applications holding this acl link.
1753**
1754*******************************************************************************/
1755UINT8 gatt_num_apps_hold_link(tGATT_TCB *p_tcb)
1756{
1757    UINT8 i, num = 0;
1758
1759    for (i = 0; i < GATT_MAX_APPS; i ++)
1760    {
1761        if (p_tcb->app_hold_link[i])
1762            num ++;
1763    }
1764
1765    GATT_TRACE_DEBUG("gatt_num_apps_hold_link   num=%d",  num);
1766    return num;
1767}
1768
1769
1770/*******************************************************************************
1771**
1772** Function         gatt_num_clcb_by_bd_addr
1773**
1774** Description      The function searches all LCB with macthing bd address
1775**
1776** Returns          total number of clcb found.
1777**
1778*******************************************************************************/
1779UINT8 gatt_num_clcb_by_bd_addr(BD_ADDR bda)
1780{
1781    UINT8 i, num = 0;
1782
1783    for (i = 0; i < GATT_CL_MAX_LCB; i ++)
1784    {
1785        if (gatt_cb.clcb[i].in_use && memcmp(gatt_cb.clcb[i].p_tcb->peer_bda, bda, BD_ADDR_LEN) == 0)
1786            num ++;
1787    }
1788    return num;
1789}
1790
1791/*******************************************************************************
1792**
1793** Function         gatt_sr_update_cback_cnt
1794**
1795** Description      The function searches all LCB with macthing bd address
1796**
1797** Returns          total number of clcb found.
1798**
1799*******************************************************************************/
1800void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB *p_tcb )
1801{
1802    UINT8 i;
1803
1804    if (p_tcb)
1805    {
1806        for (i = 0; i < GATT_MAX_APPS; i ++)
1807        {
1808            if (p_tcb->prep_cnt[i])
1809            {
1810                p_tcb->sr_cmd.cback_cnt[i]=1;
1811            }
1812        }
1813    }
1814
1815}
1816
1817/*******************************************************************************
1818**
1819** Function         gatt_sr_is_cback_cnt_zero
1820**
1821** Description      The function searches all LCB with macthing bd address
1822**
1823** Returns          True if thetotal application callback count is zero
1824**
1825*******************************************************************************/
1826BOOLEAN gatt_sr_is_cback_cnt_zero(tGATT_TCB *p_tcb )
1827{
1828    BOOLEAN status = TRUE;
1829    UINT8   i;
1830
1831    if (p_tcb)
1832    {
1833        for (i = 0; i < GATT_MAX_APPS; i ++)
1834        {
1835            if (p_tcb->sr_cmd.cback_cnt[i])
1836            {
1837                status = FALSE;
1838                break;
1839            }
1840        }
1841    }
1842    else
1843    {
1844        status = FALSE;
1845    }
1846    return status;
1847}
1848
1849/*******************************************************************************
1850**
1851** Function         gatt_sr_is_prep_cnt_zero
1852**
1853** Description      Check the prepare write request count is zero or not
1854**
1855** Returns          True no prepare write request
1856**
1857*******************************************************************************/
1858BOOLEAN gatt_sr_is_prep_cnt_zero(tGATT_TCB *p_tcb)
1859{
1860    BOOLEAN status = TRUE;
1861    UINT8   i;
1862
1863    if (p_tcb)
1864    {
1865        for (i = 0; i < GATT_MAX_APPS; i ++)
1866        {
1867            if (p_tcb->prep_cnt[i])
1868            {
1869                status = FALSE;
1870                break;
1871            }
1872        }
1873    }
1874    else
1875    {
1876        status = FALSE;
1877    }
1878    return status;
1879}
1880
1881
1882/*******************************************************************************
1883**
1884** Function         gatt_sr_reset_cback_cnt
1885**
1886** Description      Reset the application callback count to zero
1887**
1888** Returns         None
1889**
1890*******************************************************************************/
1891void gatt_sr_reset_cback_cnt(tGATT_TCB *p_tcb )
1892{
1893    UINT8 i;
1894
1895    if (p_tcb)
1896    {
1897        for (i = 0; i < GATT_MAX_APPS; i ++)
1898        {
1899            p_tcb->sr_cmd.cback_cnt[i]=0;
1900        }
1901    }
1902}
1903
1904/*******************************************************************************
1905**
1906** Function         gatt_sr_reset_prep_cnt
1907**
1908** Description     Reset the prep write count to zero
1909**
1910** Returns        None
1911**
1912*******************************************************************************/
1913void gatt_sr_reset_prep_cnt(tGATT_TCB *p_tcb )
1914{
1915    UINT8 i;
1916    if (p_tcb)
1917    {
1918        for (i = 0; i < GATT_MAX_APPS; i ++)
1919        {
1920            p_tcb->prep_cnt[i]=0;
1921        }
1922    }
1923}
1924
1925
1926/*******************************************************************************
1927**
1928** Function         gatt_sr_update_cback_cnt
1929**
1930** Description    Update the teh applicaiton callback count
1931**
1932** Returns           None
1933**
1934*******************************************************************************/
1935void gatt_sr_update_cback_cnt(tGATT_TCB *p_tcb, tGATT_IF gatt_if, BOOLEAN is_inc, BOOLEAN is_reset_first)
1936{
1937
1938    UINT8 idx = ((UINT8) gatt_if) - 1 ;
1939
1940    if (p_tcb)
1941    {
1942        if (is_reset_first)
1943        {
1944            gatt_sr_reset_cback_cnt(p_tcb);
1945        }
1946        if (is_inc)
1947        {
1948            p_tcb->sr_cmd.cback_cnt[idx]++;
1949        }
1950        else
1951        {
1952            if ( p_tcb->sr_cmd.cback_cnt[idx])
1953            {
1954                p_tcb->sr_cmd.cback_cnt[idx]--;
1955            }
1956        }
1957    }
1958}
1959
1960
1961/*******************************************************************************
1962**
1963** Function         gatt_sr_update_prep_cnt
1964**
1965** Description    Update the teh prepare write request count
1966**
1967** Returns           None
1968**
1969*******************************************************************************/
1970void gatt_sr_update_prep_cnt(tGATT_TCB *p_tcb, tGATT_IF gatt_if, BOOLEAN is_inc, BOOLEAN is_reset_first)
1971{
1972    UINT8 idx = ((UINT8) gatt_if) - 1 ;
1973
1974    GATT_TRACE_DEBUG("gatt_sr_update_prep_cnt tcb idx=%d gatt_if=%d is_inc=%d is_reset_first=%d",
1975                      p_tcb->tcb_idx, gatt_if, is_inc, is_reset_first);
1976
1977    if (p_tcb)
1978    {
1979        if (is_reset_first)
1980        {
1981            gatt_sr_reset_prep_cnt(p_tcb);
1982        }
1983        if (is_inc)
1984        {
1985            p_tcb->prep_cnt[idx]++;
1986        }
1987        else
1988        {
1989            if (p_tcb->prep_cnt[idx])
1990            {
1991                p_tcb->prep_cnt[idx]--;
1992            }
1993        }
1994    }
1995}
1996/*******************************************************************************
1997**
1998** Function         gatt_cancel_open
1999**
2000** Description      Cancel open request
2001**
2002** Returns         Boolean
2003**
2004*******************************************************************************/
2005BOOLEAN gatt_cancel_open(tGATT_IF gatt_if, BD_ADDR bda)
2006{
2007    tGATT_TCB *p_tcb=NULL;
2008    BOOLEAN status= TRUE;
2009
2010    p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE);
2011
2012    if (p_tcb)
2013    {
2014        if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
2015        {
2016            GATT_TRACE_ERROR("GATT_CancelConnect - link connected Too late to cancel");
2017            status = FALSE;
2018        }
2019        else
2020        {
2021            gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
2022            if (!gatt_num_apps_hold_link(p_tcb))
2023            {
2024                gatt_disconnect(p_tcb);
2025            }
2026        }
2027    }
2028
2029    return status;
2030}
2031
2032/*******************************************************************************
2033**
2034** Function         gatt_find_app_hold_link
2035**
2036** Description      find the applicaiton that is holding the specified link
2037**
2038** Returns         Boolean
2039**
2040*******************************************************************************/
2041BOOLEAN gatt_find_app_hold_link(tGATT_TCB *p_tcb, UINT8 start_idx, UINT8 *p_found_idx, tGATT_IF *p_gatt_if)
2042{
2043    UINT8 i;
2044    BOOLEAN found= FALSE;
2045
2046    for (i = start_idx; i < GATT_MAX_APPS; i ++)
2047    {
2048        if (p_tcb->app_hold_link[i])
2049        {
2050            *p_gatt_if = gatt_cb.clcb[i].p_reg->gatt_if;
2051            *p_found_idx = i;
2052            found = TRUE;
2053            break;
2054        }
2055    }
2056    return found;
2057}
2058
2059/*******************************************************************************
2060**
2061** Function         gatt_cmd_enq
2062**
2063** Description      Enqueue this command.
2064**
2065** Returns          None.
2066**
2067*******************************************************************************/
2068BOOLEAN gatt_cmd_enq(tGATT_TCB *p_tcb, UINT16 clcb_idx, BOOLEAN to_send, UINT8 op_code, BT_HDR *p_buf)
2069{
2070    tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->next_slot_inq];
2071
2072    p_cmd->to_send = to_send; /* waiting to be sent */
2073    p_cmd->op_code  = op_code;
2074    p_cmd->p_cmd    = p_buf;
2075    p_cmd->clcb_idx = clcb_idx;
2076
2077    if (!to_send)
2078    {
2079        p_tcb->pending_cl_req = p_tcb->next_slot_inq;
2080    }
2081
2082    p_tcb->next_slot_inq ++;
2083    p_tcb->next_slot_inq %= GATT_CL_MAX_LCB;
2084
2085    return TRUE;
2086}
2087
2088/*******************************************************************************
2089**
2090** Function         gatt_cmd_dequeue
2091**
2092** Description      dequeue the command in the client CCB command queue.
2093**
2094** Returns          total number of clcb found.
2095**
2096*******************************************************************************/
2097tGATT_CLCB * gatt_cmd_dequeue(tGATT_TCB *p_tcb, UINT8 *p_op_code)
2098{
2099    tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
2100    tGATT_CLCB *p_clcb = NULL;
2101
2102    if (p_tcb->pending_cl_req != p_tcb->next_slot_inq)
2103    {
2104        p_clcb = &gatt_cb.clcb[p_cmd->clcb_idx];
2105
2106        *p_op_code = p_cmd->op_code;
2107
2108        p_tcb->pending_cl_req ++;
2109        p_tcb->pending_cl_req %= GATT_CL_MAX_LCB;
2110    }
2111
2112    return p_clcb;
2113}
2114
2115/*******************************************************************************
2116**
2117** Function         gatt_send_write_msg
2118**
2119** Description      This real function send out the ATT message for write.
2120**
2121** Returns          status code
2122**
2123*******************************************************************************/
2124UINT8 gatt_send_write_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code,
2125                           UINT16 handle, UINT16 len,
2126                           UINT16 offset, UINT8 *p_data)
2127{
2128    tGATT_CL_MSG     msg;
2129
2130    msg.attr_value.handle = handle;
2131    msg.attr_value.len = len;
2132    msg.attr_value.offset = offset;
2133
2134    memcpy (msg.attr_value.value, p_data, len);
2135
2136    /* write by handle */
2137    return attp_send_cl_msg(p_tcb, clcb_idx, op_code, &msg);
2138}
2139
2140/*******************************************************************************
2141**
2142** Function         gatt_act_send_browse
2143**
2144** Description      This function ends a browse command request, including read
2145**                  information request and read by type request.
2146**
2147** Returns          status code
2148**
2149*******************************************************************************/
2150UINT8 gatt_act_send_browse(tGATT_TCB *p_tcb, UINT16 index, UINT8 op, UINT16 s_handle,
2151                           UINT16 e_handle, tBT_UUID uuid)
2152{
2153    tGATT_CL_MSG     msg;
2154
2155    msg.browse.s_handle = s_handle;
2156    msg.browse.e_handle   = e_handle;
2157    memcpy(&msg.browse.uuid, &uuid, sizeof(tBT_UUID));
2158
2159    /* write by handle */
2160    return attp_send_cl_msg(p_tcb, index, op, &msg);
2161}
2162
2163/*******************************************************************************
2164**
2165** Function         gatt_end_operation
2166**
2167** Description      This function ends a discovery, send callback and finalize
2168**                  some control value.
2169**
2170** Returns          16 bits uuid.
2171**
2172*******************************************************************************/
2173void gatt_end_operation(tGATT_CLCB *p_clcb, tGATT_STATUS status, void *p_data)
2174{
2175    tGATT_CL_COMPLETE   cb_data;
2176    tGATT_CMPL_CBACK    *p_cmpl_cb = (p_clcb->p_reg) ? p_clcb->p_reg->app_cb.p_cmpl_cb : NULL;
2177    UINT8               op = p_clcb->operation, disc_type=GATT_DISC_MAX;
2178    tGATT_DISC_CMPL_CB  *p_disc_cmpl_cb = (p_clcb->p_reg) ? p_clcb->p_reg->app_cb.p_disc_cmpl_cb : NULL;
2179    UINT16              conn_id;
2180    UINT8               operation;
2181
2182    GATT_TRACE_DEBUG ("gatt_end_operation status=%d op=%d subtype=%d",
2183                       status, p_clcb->operation, p_clcb->op_subtype);
2184    memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
2185
2186    if (p_cmpl_cb != NULL && p_clcb->operation != 0)
2187    {
2188        if (p_clcb->operation == GATTC_OPTYPE_READ)
2189        {
2190            cb_data.att_value.handle   = p_clcb->s_handle;
2191            cb_data.att_value.len      = p_clcb->counter;
2192
2193            if (p_data && p_clcb->counter)
2194                memcpy (cb_data.att_value.value, p_data, cb_data.att_value.len);
2195        }
2196
2197        if (p_clcb->operation == GATTC_OPTYPE_WRITE)
2198        {
2199            memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
2200            cb_data.handle           =
2201            cb_data.att_value.handle = p_clcb->s_handle;
2202            if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
2203            {
2204                if (p_data)
2205                {
2206                    cb_data.att_value = *((tGATT_VALUE *) p_data);
2207                }
2208                else
2209                {
2210                    GATT_TRACE_DEBUG("Rcv Prepare write rsp but no data");
2211                }
2212            }
2213        }
2214
2215        if (p_clcb->operation == GATTC_OPTYPE_CONFIG)
2216            cb_data.mtu = p_clcb->p_tcb->payload_size;
2217
2218        if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
2219        {
2220            disc_type = p_clcb->op_subtype;
2221        }
2222    }
2223
2224    osi_free_and_reset((void **)&p_clcb->p_attr_buf);
2225
2226    operation =  p_clcb->operation;
2227    conn_id = p_clcb->conn_id;
2228    alarm_cancel(p_clcb->gatt_rsp_timer_ent);
2229
2230    gatt_clcb_dealloc(p_clcb);
2231
2232    if (p_disc_cmpl_cb && (op == GATTC_OPTYPE_DISCOVERY))
2233        (*p_disc_cmpl_cb)(conn_id, disc_type, status);
2234    else if (p_cmpl_cb && op)
2235        (*p_cmpl_cb)(conn_id, op, status, &cb_data);
2236    else
2237        GATT_TRACE_WARNING ("gatt_end_operation not sent out op=%d p_disc_cmpl_cb:%p p_cmpl_cb:%p",
2238                             operation, p_disc_cmpl_cb, p_cmpl_cb);
2239}
2240
2241/*******************************************************************************
2242**
2243** Function         gatt_cleanup_upon_disc
2244**
2245** Description      This function cleans up the control blocks when L2CAP channel
2246**                  disconnect.
2247**
2248** Returns          16 bits uuid.
2249**
2250*******************************************************************************/
2251void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
2252{
2253    tGATT_TCB       *p_tcb = NULL;
2254    tGATT_CLCB      *p_clcb;
2255    UINT8           i;
2256    UINT16          conn_id;
2257    tGATT_REG        *p_reg=NULL;
2258
2259
2260    GATT_TRACE_DEBUG ("gatt_cleanup_upon_disc ");
2261
2262    if ((p_tcb = gatt_find_tcb_by_addr(bda, transport)) != NULL)
2263    {
2264        GATT_TRACE_DEBUG ("found p_tcb ");
2265        gatt_set_ch_state(p_tcb, GATT_CH_CLOSE);
2266        for (i = 0; i < GATT_CL_MAX_LCB; i ++)
2267        {
2268            p_clcb = &gatt_cb.clcb[i];
2269            if (p_clcb->in_use && p_clcb->p_tcb == p_tcb)
2270            {
2271                alarm_cancel(p_clcb->gatt_rsp_timer_ent);
2272                GATT_TRACE_DEBUG ("found p_clcb conn_id=%d clcb_idx=%d", p_clcb->conn_id, p_clcb->clcb_idx);
2273                if (p_clcb->operation != GATTC_OPTYPE_NONE)
2274                    gatt_end_operation(p_clcb, GATT_ERROR, NULL);
2275
2276                gatt_clcb_dealloc(p_clcb);
2277
2278            }
2279        }
2280
2281        alarm_free(p_tcb->ind_ack_timer);
2282        p_tcb->ind_ack_timer = NULL;
2283        alarm_free(p_tcb->conf_timer);
2284        p_tcb->conf_timer = NULL;
2285        gatt_free_pending_ind(p_tcb);
2286        gatt_free_pending_enc_queue(p_tcb);
2287        fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
2288        p_tcb->sr_cmd.multi_rsp_q = NULL;
2289
2290        for (i = 0; i < GATT_MAX_APPS; i ++)
2291        {
2292            p_reg = &gatt_cb.cl_rcb[i];
2293            if (p_reg->in_use && p_reg->app_cb.p_conn_cb)
2294            {
2295                conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
2296                GATT_TRACE_DEBUG ("found p_reg tcb_idx=%d gatt_if=%d  conn_id=0x%x", p_tcb->tcb_idx, p_reg->gatt_if, conn_id);
2297                (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if,  bda, conn_id, FALSE, reason, transport);
2298            }
2299        }
2300        memset(p_tcb, 0, sizeof(tGATT_TCB));
2301
2302    }
2303    GATT_TRACE_DEBUG ("exit gatt_cleanup_upon_disc ");
2304}
2305/*******************************************************************************
2306**
2307** Function         gatt_dbg_req_op_name
2308**
2309** Description      Get op code description name, for debug information.
2310**
2311** Returns          UINT8 *: name of the operation.
2312**
2313*******************************************************************************/
2314UINT8 * gatt_dbg_op_name(UINT8 op_code)
2315{
2316    UINT8 pseduo_op_code_idx = op_code & (~GATT_WRITE_CMD_MASK);
2317
2318    if (op_code == GATT_CMD_WRITE )
2319    {
2320        pseduo_op_code_idx = 0x14; /* just an index to op_code_name */
2321
2322    }
2323
2324    if (op_code == GATT_SIGN_CMD_WRITE)
2325    {
2326        pseduo_op_code_idx = 0x15; /* just an index to op_code_name */
2327    }
2328
2329    if (pseduo_op_code_idx <= GATT_OP_CODE_MAX)
2330        return(UINT8*) op_code_name[pseduo_op_code_idx];
2331    else
2332        return(UINT8 *)"Op Code Exceed Max";
2333}
2334
2335/*******************************************************************************
2336**
2337** Function         gatt_dbg_display_uuid
2338**
2339** Description      Disaplay the UUID
2340**
2341** Returns          None
2342**
2343*******************************************************************************/
2344void gatt_dbg_display_uuid(tBT_UUID bt_uuid)
2345{
2346    char str_buf[50];
2347    int x = 0;
2348
2349    if (bt_uuid.len == LEN_UUID_16)
2350    {
2351        sprintf(str_buf, "0x%04x", bt_uuid.uu.uuid16);
2352    }
2353    else if (bt_uuid.len == LEN_UUID_32)
2354    {
2355        sprintf(str_buf, "0x%08x", (unsigned int)bt_uuid.uu.uuid32);
2356    }
2357    else if (bt_uuid.len == LEN_UUID_128)
2358    {
2359        x += sprintf(&str_buf[x], "0x%02x%02x%02x%02x%02x%02x%02x%02x",
2360                     bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
2361                     bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
2362                     bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
2363                     bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
2364        sprintf(&str_buf[x], "%02x%02x%02x%02x%02x%02x%02x%02x",
2365                bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
2366                bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
2367                bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
2368                bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
2369    }
2370    else
2371        strlcpy(str_buf, "Unknown UUID 0", sizeof(str_buf));
2372
2373    GATT_TRACE_DEBUG ("UUID=[%s]", str_buf);
2374}
2375
2376
2377/*******************************************************************************
2378**
2379** Function         gatt_is_bg_dev_for_app
2380**
2381** Description      find is this one of the background devices for the application
2382**
2383** Returns          TRUE this is one of the background devices for the  application
2384**
2385*******************************************************************************/
2386BOOLEAN gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV *p_dev, tGATT_IF gatt_if)
2387{
2388    UINT8   i;
2389
2390    for (i = 0; i < GATT_MAX_APPS; i ++ )
2391    {
2392        if (p_dev->in_use && (p_dev->gatt_if[i] == gatt_if))
2393        {
2394            return TRUE;
2395        }
2396    }
2397    return FALSE;
2398}
2399/*******************************************************************************
2400**
2401** Function         gatt_find_bg_dev
2402**
2403** Description      find background connection device from the list.
2404**
2405** Returns          pointer to the device record
2406**
2407*******************************************************************************/
2408tGATT_BG_CONN_DEV * gatt_find_bg_dev(BD_ADDR remote_bda)
2409{
2410    tGATT_BG_CONN_DEV    *p_dev_list = &gatt_cb.bgconn_dev[0];
2411    UINT8   i;
2412
2413    for (i = 0; i < GATT_MAX_BG_CONN_DEV; i ++, p_dev_list ++)
2414    {
2415        if (p_dev_list->in_use && !memcmp(p_dev_list->remote_bda, remote_bda, BD_ADDR_LEN))
2416        {
2417            return p_dev_list;
2418        }
2419    }
2420    return NULL;
2421}
2422/*******************************************************************************
2423**
2424** Function         gatt_alloc_bg_dev
2425**
2426** Description      allocate a background connection device record
2427**
2428** Returns          pointer to the device record
2429**
2430*******************************************************************************/
2431tGATT_BG_CONN_DEV * gatt_alloc_bg_dev(BD_ADDR remote_bda)
2432{
2433    tGATT_BG_CONN_DEV    *p_dev_list = &gatt_cb.bgconn_dev[0];
2434    UINT8   i;
2435
2436    for (i = 0; i < GATT_MAX_BG_CONN_DEV; i ++, p_dev_list ++)
2437    {
2438        if (!p_dev_list->in_use)
2439        {
2440            p_dev_list->in_use = TRUE;
2441            memcpy(p_dev_list->remote_bda, remote_bda, BD_ADDR_LEN);
2442
2443            return p_dev_list;
2444        }
2445    }
2446    return NULL;
2447}
2448
2449/*******************************************************************************
2450**
2451** Function         gatt_add_bg_dev_list
2452**
2453** Description      add/remove device from the back ground connection device list
2454**
2455** Returns          TRUE if device added to the list; FALSE failed
2456**
2457*******************************************************************************/
2458BOOLEAN gatt_add_bg_dev_list(tGATT_REG *p_reg,  BD_ADDR bd_addr, BOOLEAN is_initator)
2459{
2460    tGATT_IF gatt_if =  p_reg->gatt_if;
2461    tGATT_BG_CONN_DEV   *p_dev = NULL;
2462    UINT8       i;
2463    BOOLEAN      ret = FALSE;
2464
2465    if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
2466    {
2467        p_dev = gatt_alloc_bg_dev(bd_addr);
2468    }
2469
2470    if (p_dev)
2471    {
2472        for (i = 0; i < GATT_MAX_APPS; i ++)
2473        {
2474            if (is_initator)
2475            {
2476                if (p_dev->gatt_if[i] == gatt_if)
2477                {
2478                    GATT_TRACE_ERROR("device already in iniator white list");
2479                    return TRUE;
2480                }
2481                else if (p_dev->gatt_if[i] == 0)
2482                {
2483                    p_dev->gatt_if[i] = gatt_if;
2484                    if (i == 0)
2485                        ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
2486                    else
2487                        ret = TRUE;
2488                    break;
2489                }
2490            }
2491            else
2492            {
2493                if (p_dev->listen_gif[i] == gatt_if)
2494                {
2495                    GATT_TRACE_ERROR("device already in adv white list");
2496                    return TRUE;
2497                }
2498                else if (p_dev->listen_gif[i] == 0)
2499                {
2500                    if (p_reg->listening == GATT_LISTEN_TO_ALL)
2501                        p_reg->listening = GATT_LISTEN_TO_NONE;
2502
2503                    p_reg->listening ++;
2504                    p_dev->listen_gif[i] = gatt_if;
2505
2506                    if (i == 0)
2507                        ret = BTM_BleUpdateAdvWhitelist(TRUE, bd_addr);
2508                    else
2509                        ret = TRUE;
2510                    break;
2511                }
2512            }
2513        }
2514    }
2515    else
2516    {
2517        GATT_TRACE_ERROR("no device record available");
2518    }
2519
2520    return ret;
2521}
2522
2523/*******************************************************************************
2524**
2525** Function         gatt_remove_bg_dev_for_app
2526**
2527** Description      Remove the application interface for the specified background device
2528**
2529** Returns          Boolean
2530**
2531*******************************************************************************/
2532BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr)
2533{
2534    tGATT_TCB    *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
2535    BOOLEAN       status;
2536
2537    if (p_tcb)
2538        gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
2539    status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr, TRUE);
2540    return status;
2541}
2542
2543
2544/*******************************************************************************
2545**
2546** Function         gatt_get_num_apps_for_bg_dev
2547**
2548** Description      Gte the number of applciations for the specified background device
2549**
2550** Returns          UINT8 total number fo applications
2551**
2552*******************************************************************************/
2553UINT8 gatt_get_num_apps_for_bg_dev(BD_ADDR bd_addr)
2554{
2555    tGATT_BG_CONN_DEV   *p_dev = NULL;
2556    UINT8   i;
2557    UINT8   cnt = 0;
2558
2559    if ((p_dev = gatt_find_bg_dev(bd_addr)) != NULL)
2560    {
2561        for (i = 0; i < GATT_MAX_APPS; i ++)
2562        {
2563            if (p_dev->gatt_if[i])
2564                cnt++;
2565        }
2566    }
2567    return cnt;
2568}
2569
2570/*******************************************************************************
2571**
2572** Function         gatt_find_app_for_bg_dev
2573**
2574** Description      find the application interface for the specified background device
2575**
2576** Returns          Boolean
2577**
2578*******************************************************************************/
2579BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if)
2580{
2581    tGATT_BG_CONN_DEV   *p_dev = NULL;
2582    UINT8   i;
2583    BOOLEAN ret = FALSE;
2584
2585    if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
2586    {
2587        return ret;
2588    }
2589
2590    for (i = 0; i < GATT_MAX_APPS; i ++)
2591    {
2592        if (p_dev->gatt_if[i] != 0 )
2593        {
2594            *p_gatt_if = p_dev->gatt_if[i];
2595            ret = TRUE;
2596            break;
2597        }
2598    }
2599    return ret;
2600}
2601
2602
2603/*******************************************************************************
2604**
2605** Function         gatt_remove_bg_dev_from_list
2606**
2607** Description      add/remove device from the back ground connection device list or
2608**                  listening to advertising list.
2609**
2610** Returns          pointer to the device record
2611**
2612*******************************************************************************/
2613BOOLEAN gatt_remove_bg_dev_from_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_initiator)
2614{
2615    tGATT_IF gatt_if = p_reg->gatt_if;
2616    tGATT_BG_CONN_DEV   *p_dev = NULL;
2617    UINT8   i, j;
2618    BOOLEAN ret = FALSE;
2619
2620    if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
2621    {
2622        return ret;
2623    }
2624
2625    for (i = 0; i < GATT_MAX_APPS && (p_dev->gatt_if[i] > 0 || p_dev->listen_gif[i]); i ++)
2626    {
2627        if (is_initiator)
2628        {
2629            if (p_dev->gatt_if[i] == gatt_if)
2630            {
2631                p_dev->gatt_if[i] = 0;
2632                /* move all element behind one forward */
2633                for (j = i + 1; j < GATT_MAX_APPS; j ++)
2634                    p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
2635
2636                if (p_dev->gatt_if[0] == 0)
2637                    ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
2638                else
2639                    ret = TRUE;
2640
2641                break;
2642            }
2643        }
2644        else
2645        {
2646            if (p_dev->listen_gif[i] == gatt_if)
2647            {
2648                p_dev->listen_gif[i] = 0;
2649                p_reg->listening --;
2650                /* move all element behind one forward */
2651                for (j = i + 1; j < GATT_MAX_APPS; j ++)
2652                    p_dev->listen_gif[j - 1] = p_dev->listen_gif[j];
2653
2654                if (p_dev->listen_gif[0] == 0)
2655                    ret = BTM_BleUpdateAdvWhitelist(FALSE, p_dev->remote_bda);
2656                else
2657                    ret = TRUE;
2658                break;
2659            }
2660        }
2661    }
2662
2663    if (i != GATT_MAX_APPS && p_dev->gatt_if[0] == 0 && p_dev->listen_gif[0] == 0)
2664    {
2665        memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
2666    }
2667
2668    return ret;
2669}
2670/*******************************************************************************
2671**
2672** Function         gatt_deregister_bgdev_list
2673**
2674** Description      deregister all related back ground connetion device.
2675**
2676** Returns          pointer to the device record
2677**
2678*******************************************************************************/
2679void gatt_deregister_bgdev_list(tGATT_IF gatt_if)
2680{
2681    tGATT_BG_CONN_DEV    *p_dev_list = &gatt_cb.bgconn_dev[0];
2682    UINT8 i , j, k;
2683    tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
2684
2685    /* update the BG conn device list */
2686    for (i = 0 ; i <GATT_MAX_BG_CONN_DEV; i ++, p_dev_list ++ )
2687    {
2688        if (p_dev_list->in_use)
2689        {
2690            for (j = 0; j < GATT_MAX_APPS; j ++)
2691            {
2692                if (p_dev_list->gatt_if[j] == 0 && p_dev_list->listen_gif[j] == 0)
2693                    break;
2694
2695                if (p_dev_list->gatt_if[j] == gatt_if)
2696                {
2697                    for (k = j + 1; k < GATT_MAX_APPS; k ++)
2698                        p_dev_list->gatt_if[k - 1] = p_dev_list->gatt_if[k];
2699
2700                    if (p_dev_list->gatt_if[0] == 0)
2701                        BTM_BleUpdateBgConnDev(FALSE, p_dev_list->remote_bda);
2702                }
2703
2704                if (p_dev_list->listen_gif[j] == gatt_if)
2705                {
2706                    p_dev_list->listen_gif[j] = 0;
2707
2708                    if (p_reg != NULL && p_reg->listening > 0)
2709                        p_reg->listening --;
2710
2711                    /* move all element behind one forward */
2712                    for (k = j + 1; k < GATT_MAX_APPS; k ++)
2713                        p_dev_list->listen_gif[k - 1] = p_dev_list->listen_gif[k];
2714
2715                    if (p_dev_list->listen_gif[0] == 0)
2716                        BTM_BleUpdateAdvWhitelist(FALSE, p_dev_list->remote_bda);
2717                }
2718            }
2719        }
2720    }
2721}
2722
2723
2724/*******************************************************************************
2725**
2726** Function         gatt_reset_bgdev_list
2727**
2728** Description      reset bg device list
2729**
2730** Returns          pointer to the device record
2731**
2732*******************************************************************************/
2733void gatt_reset_bgdev_list(void)
2734{
2735    memset(&gatt_cb.bgconn_dev, 0 , sizeof(tGATT_BG_CONN_DEV)*GATT_MAX_BG_CONN_DEV);
2736
2737}
2738/*******************************************************************************
2739**
2740** Function         gatt_update_auto_connect_dev
2741**
2742** Description      This function add or remove a device for background connection
2743**                  procedure.
2744**
2745** Parameters       gatt_if: Application ID.
2746**                  add: add peer device
2747**                  bd_addr: peer device address.
2748**
2749** Returns          TRUE if connection started; FALSE if connection start failure.
2750**
2751*******************************************************************************/
2752BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initator)
2753{
2754    BOOLEAN         ret = FALSE;
2755    tGATT_REG        *p_reg;
2756    tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
2757
2758    GATT_TRACE_API ("gatt_update_auto_connect_dev ");
2759    /* Make sure app is registered */
2760    if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
2761    {
2762        GATT_TRACE_ERROR("gatt_update_auto_connect_dev - gatt_if is not registered", gatt_if);
2763        return(FALSE);
2764    }
2765
2766    if (add)
2767    {
2768        ret = gatt_add_bg_dev_list(p_reg, bd_addr, is_initator);
2769
2770        if (ret && p_tcb != NULL)
2771        {
2772            /* if a connected device, update the link holding number */
2773            gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
2774        }
2775    }
2776    else
2777    {
2778        ret = gatt_remove_bg_dev_from_list(p_reg, bd_addr, is_initator);
2779    }
2780    return ret;
2781}
2782
2783
2784
2785/*******************************************************************************
2786**
2787** Function     gatt_add_pending_new_srv_start
2788**
2789** Description  Add a pending new srv start to the new service start queue
2790**
2791** Returns    Pointer to the new service start buffer, NULL no buffer available
2792**
2793*******************************************************************************/
2794tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb)
2795{
2796    tGATT_PENDING_ENC_CLCB *p_buf =
2797        (tGATT_PENDING_ENC_CLCB *)osi_malloc(sizeof(tGATT_PENDING_ENC_CLCB));
2798
2799    GATT_TRACE_DEBUG ("%s", __func__);
2800    GATT_TRACE_DEBUG("enqueue a new pending encryption channel clcb");
2801
2802    p_buf->p_clcb = p_clcb;
2803    fixed_queue_enqueue(p_tcb->pending_enc_clcb, p_buf);
2804
2805    return p_buf;
2806}
2807/*******************************************************************************
2808**
2809** Function     gatt_update_listen_mode
2810**
2811** Description  update peripheral role listening mode
2812**
2813** Returns    Pointer to the new service start buffer, NULL no buffer available
2814**
2815*******************************************************************************/
2816BOOLEAN gatt_update_listen_mode(void)
2817{
2818    UINT8           ii = 0;
2819    tGATT_REG       *p_reg = &gatt_cb.cl_rcb[0];
2820    UINT8           listening = 0;
2821    UINT16          connectability, window, interval;
2822    BOOLEAN         rt = TRUE;
2823
2824    for (; ii < GATT_MAX_APPS; ii ++, p_reg ++)
2825    {
2826        if ( p_reg->in_use && p_reg->listening > listening)
2827        {
2828            listening = p_reg->listening;
2829        }
2830    }
2831
2832    if (listening == GATT_LISTEN_TO_ALL ||
2833        listening == GATT_LISTEN_TO_NONE)
2834        BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_ALL);
2835    else
2836        BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_WL);
2837
2838    if (rt)
2839    {
2840        connectability = BTM_ReadConnectability (&window, &interval);
2841
2842        if (listening != GATT_LISTEN_TO_NONE)
2843        {
2844            connectability |= BTM_BLE_CONNECTABLE;
2845        }
2846        else
2847        {
2848            if ((connectability & BTM_BLE_CONNECTABLE) == 0)
2849            connectability &= ~BTM_BLE_CONNECTABLE;
2850        }
2851        /* turning on the adv now */
2852        btm_ble_set_connectability(connectability);
2853    }
2854
2855    return rt;
2856
2857}
2858#endif
2859
2860
2861