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