Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2008-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  this file contains the main ATT functions
     22  *
     23  ******************************************************************************/
     24 
     25 #include "bt_target.h"
     26 
     27 #if BLE_INCLUDED == TRUE
     28 
     29 #include "gki.h"
     30 #include "gatt_int.h"
     31 #include "l2c_api.h"
     32 #include "btm_int.h"
     33 #include "btm_ble_int.h"
     34 
     35 /* Configuration flags. */
     36 #define GATT_L2C_CFG_IND_DONE   (1<<0)
     37 #define GATT_L2C_CFG_CFM_DONE   (1<<1)
     38 
     39 /* minimum GATT MTU size over BR/EDR link
     40 */
     41 #define GATT_MIN_BR_MTU_SIZE       48
     42 
     43 /********************************************************************************/
     44 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
     45 /********************************************************************************/
     46 static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason);
     47 static void gatt_le_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
     48 
     49 static void gatt_l2cif_connect_ind_cback (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
     50 static void gatt_l2cif_connect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
     51 static void gatt_l2cif_config_ind_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
     52 static void gatt_l2cif_config_cfm_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
     53 static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed);
     54 static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
     55 static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg);
     56 static void gatt_send_conn_cback (tGATT_TCB *p_tcb);
     57 
     58 static const tL2CAP_APPL_INFO dyn_info =
     59 {
     60     gatt_l2cif_connect_ind_cback,
     61     gatt_l2cif_connect_cfm_cback,
     62     NULL,
     63     gatt_l2cif_config_ind_cback,
     64     gatt_l2cif_config_cfm_cback,
     65     gatt_l2cif_disconnect_ind_cback,
     66     gatt_l2cif_disconnect_cfm_cback,
     67     NULL,
     68     gatt_l2cif_data_ind_cback,
     69     NULL
     70 } ;
     71 
     72 #if GATT_DYNAMIC_MEMORY == FALSE
     73 tGATT_CB  gatt_cb;
     74 #endif
     75 
     76 /*******************************************************************************
     77 **
     78 ** Function         gatt_init
     79 **
     80 ** Description      This function is enable the GATT profile on the device.
     81 **                  It clears out the control blocks, and registers with L2CAP.
     82 **
     83 ** Returns          void
     84 **
     85 *******************************************************************************/
     86 void gatt_init (void)
     87 {
     88     tL2CAP_FIXED_CHNL_REG  fixed_reg;
     89 
     90     GATT_TRACE_DEBUG0("gatt_init()");
     91 
     92     memset (&gatt_cb, 0, sizeof(tGATT_CB));
     93 
     94 #if defined(GATT_INITIAL_TRACE_LEVEL)
     95     gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL;
     96 #else
     97     gatt_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
     98 #endif
     99     gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE;
    100     GKI_init_q (&gatt_cb.sign_op_queue);
    101     /* First, register fixed L2CAP channel for ATT over BLE */
    102     fixed_reg.fixed_chnl_opts.mode         = L2CAP_FCR_BASIC_MODE;
    103     fixed_reg.fixed_chnl_opts.max_transmit = 0xFF;
    104     fixed_reg.fixed_chnl_opts.rtrans_tout  = 2000;
    105     fixed_reg.fixed_chnl_opts.mon_tout     = 12000;
    106     fixed_reg.fixed_chnl_opts.mps          = 670;
    107     fixed_reg.fixed_chnl_opts.tx_win_sz    = 1;
    108 
    109     fixed_reg.pL2CA_FixedConn_Cb = gatt_le_connect_cback;
    110     fixed_reg.pL2CA_FixedData_Cb = gatt_le_data_ind;
    111     fixed_reg.default_idle_tout  = 0xffff;                  /* 0xffff default idle timeout */
    112 
    113     L2CA_RegisterFixedChannel (L2CAP_ATT_CID, &fixed_reg);
    114 
    115     /* Now, register with L2CAP for ATT PSM over BR/EDR */
    116     if (!L2CA_Register (BT_PSM_ATT, (tL2CAP_APPL_INFO *) &dyn_info))
    117     {
    118         GATT_TRACE_ERROR0 ("ATT Dynamic Registration failed");
    119     }
    120 
    121     BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0);
    122     BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0);
    123 
    124     gatt_cb.hdl_cfg.gatt_start_hdl = GATT_GATT_START_HANDLE;
    125     gatt_cb.hdl_cfg.gap_start_hdl  = GATT_GAP_START_HANDLE;
    126     gatt_cb.hdl_cfg.app_start_hdl  = GATT_APP_START_HANDLE;
    127     gatt_profile_db_init();
    128 
    129 }
    130 
    131 
    132 
    133 /*******************************************************************************
    134 **
    135 ** Function         gatt_connect
    136 **
    137 ** Description      This function is called to initiate a connection to a peer device.
    138 **
    139 ** Parameter        rem_bda: remote device address to connect to.
    140 **
    141 ** Returns          TRUE if connection is started, otherwise return FALSE.
    142 **
    143 *******************************************************************************/
    144 BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb)
    145 {
    146     BOOLEAN             gatt_ret = FALSE;
    147 
    148     if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN)
    149         gatt_set_ch_state(p_tcb, GATT_CH_CONN);
    150 
    151     /* select the physical link for GATT connection */
    152     if (BTM_UseLeLink(rem_bda))
    153     {
    154         p_tcb->att_lcid = L2CAP_ATT_CID;
    155         gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda);
    156     }
    157     else
    158     {
    159         if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) != 0)
    160             gatt_ret = TRUE;
    161     }
    162 
    163     return gatt_ret;
    164 }
    165 
    166 /*******************************************************************************
    167 **
    168 ** Function         gatt_disconnect
    169 **
    170 ** Description      This function is called to disconnect to an ATT device.
    171 **
    172 ** Parameter        rem_bda: remote device address to disconnect from.
    173 **
    174 ** Returns          TRUE: if connection found and to be disconnected; otherwise
    175 **                  return FALSE.
    176 **
    177 *******************************************************************************/
    178 BOOLEAN gatt_disconnect (BD_ADDR rem_bda)
    179 {
    180     tGATT_TCB           *p_tcb = gatt_find_tcb_by_addr(rem_bda);
    181     BOOLEAN             ret = FALSE;
    182     tGATT_CH_STATE      ch_state;
    183     GATT_TRACE_DEBUG0 ("gatt_disconnect ");
    184 
    185     if (p_tcb != NULL)
    186     {
    187         ret = TRUE;
    188         if ( (ch_state = gatt_get_ch_state(p_tcb)) != GATT_CH_CLOSING )
    189         {
    190             if (p_tcb->att_lcid == L2CAP_ATT_CID)
    191             {
    192                 if (ch_state == GATT_CH_OPEN)
    193                 {
    194                     /* only LCB exist between remote device and local */
    195                     ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, rem_bda);
    196                 }
    197                 else
    198                 {
    199                     gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
    200                     ret = L2CA_CancelBleConnectReq (rem_bda);
    201                 }
    202             }
    203             else
    204             {
    205                 ret = L2CA_DisconnectReq(p_tcb->att_lcid);
    206             }
    207         }
    208         else
    209         {
    210             GATT_TRACE_DEBUG0 ("gatt_disconnect already in closing state");
    211         }
    212     }
    213 
    214     return ret;
    215 }
    216 
    217 /*******************************************************************************
    218 **
    219 ** Function         gatt_update_app_hold_link_status
    220 **
    221 ** Description      Update the application use link status
    222 **
    223 ** Returns          void.
    224 **
    225 *******************************************************************************/
    226 void gatt_update_app_hold_link_status (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
    227 {
    228     UINT8 i;
    229     BOOLEAN found=FALSE;
    230 
    231     if (p_tcb == NULL)
    232     {
    233         GATT_TRACE_ERROR0("gatt_update_app_hold_link_status p_tcb=NULL");
    234         return;
    235     }
    236 
    237 
    238     for (i=0; i<GATT_MAX_APPS; i++)
    239     {
    240         if (p_tcb->app_hold_link[i] ==  gatt_if)
    241         {
    242             found = TRUE;
    243             if (!is_add)
    244             {
    245                 p_tcb->app_hold_link[i] = 0;
    246                 break;
    247             }
    248         }
    249     }
    250 
    251     if (!found && is_add)
    252     {
    253         for (i=0; i<GATT_MAX_APPS; i++)
    254         {
    255             if (p_tcb->app_hold_link[i] ==  0)
    256             {
    257                 p_tcb->app_hold_link[i] = gatt_if;
    258                 found = TRUE;
    259                 break;
    260             }
    261         }
    262     }
    263 
    264     GATT_TRACE_DEBUG4("gatt_update_app_hold_link_status found=%d[1-found] idx=%d gatt_if=%d is_add=%d", found, i, gatt_if, is_add);
    265 
    266 }
    267 
    268 /*******************************************************************************
    269 **
    270 ** Function         gatt_update_app_use_link_flag
    271 **
    272 ** Description      Update the application use link flag and optional to check the acl link
    273 **                  if the link is up then set the idle time out accordingly
    274 **
    275 ** Returns          void.
    276 **
    277 *******************************************************************************/
    278 void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link)
    279 {
    280     GATT_TRACE_DEBUG2("gatt_update_app_use_link_flag  is_add=%d chk_link=%d",
    281                       is_add, check_acl_link);
    282 
    283     gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add);
    284 
    285     if (check_acl_link &&
    286         p_tcb &&
    287         (BTM_GetHCIConnHandle(p_tcb->peer_bda) != GATT_INVALID_ACL_HANDLE))
    288     {
    289         if (is_add)
    290         {
    291             GATT_TRACE_DEBUG0("GATT disables link idle timer");
    292             /* acl link is connected disable the idle timeout */
    293             GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT);
    294         }
    295         else
    296         {
    297             if (!gatt_num_apps_hold_link(p_tcb))
    298             {
    299                 /* acl link is connected but no application needs to use the link
    300                    so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
    301                 GATT_TRACE_DEBUG1("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
    302                 GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
    303             }
    304 
    305         }
    306     }
    307 }
    308 
    309 /*******************************************************************************
    310 **
    311 ** Function         gatt_act_connect
    312 **
    313 ** Description      GATT connection initiation.
    314 **
    315 ** Returns          void.
    316 **
    317 *******************************************************************************/
    318 BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr)
    319 {
    320     BOOLEAN     ret = FALSE;
    321     tGATT_TCB   *p_tcb;
    322     UINT8       st;
    323 
    324     GATT_TRACE_DEBUG0("gatt_act_connect");
    325 
    326     if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
    327     {
    328         ret = TRUE;
    329         st = gatt_get_ch_state(p_tcb);
    330 
    331         /* before link down, another app try to open a GATT connection */
    332         if(st == GATT_CH_OPEN &&  gatt_num_apps_hold_link(p_tcb) == 0 &&
    333             /* only connection on fix channel when the l2cap channel is already open */
    334             p_tcb->att_lcid == L2CAP_ATT_CID )
    335         {
    336             if (!gatt_connect(bd_addr,  p_tcb))
    337                 ret = FALSE;
    338         }
    339         else if(st == GATT_CH_CLOSING)
    340         {
    341             /* need to complete the closing first */
    342             ret = FALSE;
    343         }
    344     }
    345     else
    346     {
    347         if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL)
    348         {
    349             if (!gatt_connect(bd_addr,  p_tcb))
    350             {
    351                 GATT_TRACE_ERROR0("gatt_connect failed");
    352                 memset(p_tcb, 0, sizeof(tGATT_TCB));
    353             }
    354             else
    355                 ret = TRUE;
    356         }
    357         else
    358         {
    359             ret = 0;
    360             GATT_TRACE_ERROR1("Max TCB for gatt_if [%d] reached.", p_reg->gatt_if);
    361         }
    362     }
    363 
    364     if (ret)
    365     {
    366         gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
    367     }
    368 
    369     return ret;
    370 }
    371 
    372 /*******************************************************************************
    373 **
    374 ** Function         gatt_le_connect_cback
    375 **
    376 ** Description      This callback function is called by L2CAP to indicate that
    377 **                  the ATT fixed channel for LE is
    378 **                      connected (conn = TRUE)/disconnected (conn = FALSE).
    379 **
    380 *******************************************************************************/
    381 static void gatt_le_connect_cback (BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason)
    382 {
    383 
    384     tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr);
    385 
    386     BOOLEAN                 check_srv_chg = FALSE;
    387     tGATTS_SRV_CHG          *p_srv_chg_clt=NULL;
    388 
    389     GATT_TRACE_DEBUG3 ("GATT   ATT protocol channel with BDA: %08x%04x is %s",
    390                        (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
    391                        (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected");
    392 
    393 
    394     if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL)
    395     {
    396         check_srv_chg = TRUE;
    397     }
    398     else
    399     {
    400         if (btm_sec_is_a_bonded_dev(bd_addr))
    401             gatt_add_a_bonded_dev_for_srv_chg(bd_addr);
    402     }
    403 
    404     if (connected)
    405     {
    406         GATT_TRACE_DEBUG1("connected is TRUE reason=%d",reason );
    407         /* BR/EDR lik, ignore this callback */
    408         if (reason == 0)
    409             return;
    410 
    411         /* do we have a channel initiating a connection? */
    412         if (p_tcb)
    413         {
    414             if (check_srv_chg)
    415                 gatt_chk_srv_chg (p_srv_chg_clt);
    416             /* we are initiating connection */
    417             if ( gatt_get_ch_state(p_tcb) == GATT_CH_CONN)
    418             {
    419                 /* send callback */
    420                 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
    421                 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
    422 
    423                 gatt_send_conn_cback(p_tcb);
    424             }
    425         }
    426         /* this is incoming connection or background connection callback */
    427         else
    428         {
    429             if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL)
    430             {
    431                 p_tcb->att_lcid = L2CAP_ATT_CID;
    432 
    433                 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
    434 
    435                 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
    436 
    437                 gatt_send_conn_cback (p_tcb);
    438                 if (check_srv_chg)
    439                 {
    440                     gatt_chk_srv_chg (p_srv_chg_clt);
    441                 }
    442             }
    443             else
    444             {
    445                 GATT_TRACE_ERROR0("CCB max out, no rsources");
    446             }
    447         }
    448     }
    449     else
    450     {
    451         gatt_cleanup_upon_disc(bd_addr, reason);
    452         GATT_TRACE_DEBUG0 ("ATT disconnected");
    453     }
    454 }
    455 
    456 /*******************************************************************************
    457 **
    458 ** Function         gatt_le_data_ind
    459 **
    460 ** Description      This function is called when data is received from L2CAP.
    461 **                  if we are the originator of the connection, we are the ATT
    462 **                  client, and the received message is queued up for the client.
    463 **
    464 **                  If we are the destination of the connection, we are the ATT
    465 **                  server, so the message is passed to the server processing
    466 **                  function.
    467 **
    468 ** Returns          void
    469 **
    470 *******************************************************************************/
    471 static void gatt_le_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf)
    472 {
    473     tGATT_TCB    *p_tcb;
    474 
    475     /* Find CCB based on bd addr */
    476     if ((p_tcb = gatt_find_tcb_by_addr (bd_addr)) != NULL &&
    477         gatt_get_ch_state(p_tcb) >= GATT_CH_OPEN)
    478     {
    479         gatt_data_process(p_tcb, p_buf);
    480     }
    481     else
    482     {
    483         GKI_freebuf (p_buf);
    484 
    485         if (p_tcb != NULL)
    486         {
    487             GATT_TRACE_WARNING1 ("ATT - Ignored L2CAP data while in state: %d",
    488                                  gatt_get_ch_state(p_tcb));
    489         }
    490     }
    491 }
    492 
    493 /*******************************************************************************
    494 **
    495 ** Function         gatt_l2cif_connect_ind
    496 **
    497 ** Description      This function handles an inbound connection indication
    498 **                  from L2CAP. This is the case where we are acting as a
    499 **                  server.
    500 **
    501 ** Returns          void
    502 **
    503 *******************************************************************************/
    504 static void gatt_l2cif_connect_ind_cback (BD_ADDR  bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
    505 {
    506     /* do we already have a control channel for this peer? */
    507     UINT8       result = L2CAP_CONN_OK;
    508     tL2CAP_CFG_INFO cfg;
    509     tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr);
    510 
    511     GATT_TRACE_ERROR1("Connection indication cid = %d", lcid);
    512     /* new connection ? */
    513     if (p_tcb == NULL)
    514     {
    515         /* allocate tcb */
    516         if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) == NULL)
    517         {
    518             /* no tcb available, reject L2CAP connection */
    519             result = L2CAP_CONN_NO_RESOURCES;
    520         }
    521         else
    522             p_tcb->att_lcid = lcid;
    523 
    524     }
    525     else /* existing connection , reject it */
    526     {
    527         result = L2CAP_CONN_NO_RESOURCES;
    528     }
    529 
    530     /* Send L2CAP connect rsp */
    531     L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
    532 
    533     /* if result ok, proceed with connection */
    534     if (result == L2CAP_CONN_OK)
    535     {
    536         /* transition to configuration state */
    537         gatt_set_ch_state(p_tcb, GATT_CH_CFG);
    538 
    539         /* Send L2CAP config req */
    540         memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
    541         cfg.mtu_present = TRUE;
    542         cfg.mtu = GATT_MAX_MTU_SIZE;
    543 
    544         L2CA_ConfigReq(lcid, &cfg);
    545     }
    546 }
    547 
    548 /*******************************************************************************
    549 **
    550 ** Function         gatt_l2c_connect_cfm_cback
    551 **
    552 ** Description      This is the L2CAP connect confirm callback function.
    553 **
    554 **
    555 ** Returns          void
    556 **
    557 *******************************************************************************/
    558 void gatt_l2cif_connect_cfm_cback(UINT16 lcid, UINT16 result)
    559 {
    560     tGATT_TCB       *p_tcb;
    561     tL2CAP_CFG_INFO cfg;
    562 
    563     /* look up clcb for this channel */
    564     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
    565     {
    566         GATT_TRACE_DEBUG3("gatt_l2c_connect_cfm_cback result: %d ch_state: %d, lcid:0x%x", result, gatt_get_ch_state(p_tcb), p_tcb->att_lcid);
    567 
    568         /* if in correct state */
    569         if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN)
    570         {
    571             /* if result successful */
    572             if (result == L2CAP_CONN_OK)
    573             {
    574                 /* set channel state */
    575                 gatt_set_ch_state(p_tcb, GATT_CH_CFG);
    576 
    577                 /* Send L2CAP config req */
    578                 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
    579                 cfg.mtu_present = TRUE;
    580                 cfg.mtu = GATT_MAX_MTU_SIZE;
    581                 L2CA_ConfigReq(lcid, &cfg);
    582             }
    583             /* else initiating connection failure */
    584             else
    585             {
    586                 gatt_cleanup_upon_disc(p_tcb->peer_bda, GATT_CONN_L2C_FAILURE);
    587             }
    588         }
    589         else /* wrong state, disconnect it */
    590         {
    591             if (result == L2CAP_CONN_OK)
    592             {
    593                 /* just in case the peer also accepts our connection - Send L2CAP disconnect req */
    594                 L2CA_DisconnectReq(lcid);
    595             }
    596         }
    597     }
    598 }
    599 
    600 /*******************************************************************************
    601 **
    602 ** Function         gatt_l2cif_config_cfm_cback
    603 **
    604 ** Description      This is the L2CAP config confirm callback function.
    605 **
    606 **
    607 ** Returns          void
    608 **
    609 *******************************************************************************/
    610 void gatt_l2cif_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
    611 {
    612     tGATT_TCB       *p_tcb;
    613     tGATTS_SRV_CHG  *p_srv_chg_clt=NULL;
    614 
    615     /* look up clcb for this channel */
    616     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
    617     {
    618         /* if in correct state */
    619         if ( gatt_get_ch_state(p_tcb) == GATT_CH_CFG)
    620         {
    621             /* if result successful */
    622             if (p_cfg->result == L2CAP_CFG_OK)
    623             {
    624                 /* update flags */
    625                 p_tcb->ch_flags |= GATT_L2C_CFG_CFM_DONE;
    626 
    627                 /* if configuration complete */
    628                 if (p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE)
    629                 {
    630                     gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
    631 
    632                     if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
    633                     {
    634                         gatt_chk_srv_chg(p_srv_chg_clt);
    635                     }
    636                     else
    637                     {
    638                         if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
    639                             gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
    640                     }
    641 
    642                     /* send callback */
    643                     gatt_send_conn_cback(p_tcb);
    644                 }
    645             }
    646             /* else failure */
    647             else
    648             {
    649                 /* Send L2CAP disconnect req */
    650                 L2CA_DisconnectReq(lcid);
    651             }
    652         }
    653     }
    654 }
    655 
    656 /*******************************************************************************
    657 **
    658 ** Function         gatt_l2cif_config_ind_cback
    659 **
    660 ** Description      This is the L2CAP config indication callback function.
    661 **
    662 **
    663 ** Returns          void
    664 **
    665 *******************************************************************************/
    666 void gatt_l2cif_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
    667 {
    668     tGATT_TCB       *p_tcb;
    669     tGATTS_SRV_CHG  *p_srv_chg_clt=NULL;
    670     /* look up clcb for this channel */
    671     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
    672     {
    673         /* GATT uses the smaller of our MTU and peer's MTU  */
    674         if ( p_cfg->mtu_present &&
    675              (p_cfg->mtu >= GATT_MIN_BR_MTU_SIZE && p_cfg->mtu < L2CAP_DEFAULT_MTU))
    676             p_tcb->payload_size = p_cfg->mtu;
    677         else
    678             p_tcb->payload_size = L2CAP_DEFAULT_MTU;
    679 
    680         /* send L2CAP configure response */
    681         memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
    682         p_cfg->result = L2CAP_CFG_OK;
    683         L2CA_ConfigRsp(lcid, p_cfg);
    684 
    685         /* if first config ind */
    686         if ((p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) == 0)
    687         {
    688             /* update flags */
    689             p_tcb->ch_flags |= GATT_L2C_CFG_IND_DONE;
    690 
    691             /* if configuration complete */
    692             if (p_tcb->ch_flags & GATT_L2C_CFG_CFM_DONE)
    693             {
    694                 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
    695                 if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
    696                 {
    697                     gatt_chk_srv_chg(p_srv_chg_clt);
    698                 }
    699                 else
    700                 {
    701                     if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
    702                         btm_sec_is_le_capable_dev(p_tcb->peer_bda))
    703                     {
    704                         gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
    705                     }
    706                 }
    707 
    708                 /* send callback */
    709                 gatt_send_conn_cback(p_tcb);
    710             }
    711         }
    712     }
    713 }
    714 
    715 /*******************************************************************************
    716 **
    717 ** Function         gatt_l2cif_disconnect_ind_cback
    718 **
    719 ** Description      This is the L2CAP disconnect indication callback function.
    720 **
    721 **
    722 ** Returns          void
    723 **
    724 *******************************************************************************/
    725 void gatt_l2cif_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
    726 {
    727     tGATT_TCB       *p_tcb;
    728     UINT16          reason;
    729 
    730     /* look up clcb for this channel */
    731     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
    732     {
    733         if (ack_needed)
    734         {
    735             /* send L2CAP disconnect response */
    736             L2CA_DisconnectRsp(lcid);
    737         }
    738 
    739         if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL)
    740         {
    741             if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
    742                 btm_sec_is_le_capable_dev(p_tcb->peer_bda))
    743                 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
    744         }
    745 
    746         /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
    747         if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
    748             reason = GATT_CONN_TERMINATE_PEER_USER;
    749 
    750         /* send disconnect callback */
    751         gatt_cleanup_upon_disc(p_tcb->peer_bda, reason);
    752     }
    753 }
    754 
    755 /*******************************************************************************
    756 **
    757 ** Function         gatt_l2cif_disconnect_cfm_cback
    758 **
    759 ** Description      This is the L2CAP disconnect confirm callback function.
    760 **
    761 **
    762 ** Returns          void
    763 **
    764 *******************************************************************************/
    765 void gatt_l2cif_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
    766 {
    767     tGATT_TCB       *p_tcb;
    768     UINT16          reason;
    769 
    770     /* look up clcb for this channel */
    771     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
    772     {
    773         /* If the device is not in the service changed client list, add it... */
    774         if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL)
    775         {
    776             if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
    777                 btm_sec_is_le_capable_dev(p_tcb->peer_bda))
    778                 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
    779         }
    780 
    781         /* send disconnect callback */
    782         /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
    783         if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
    784             reason = GATT_CONN_TERMINATE_LOCAL_HOST;
    785 
    786         gatt_cleanup_upon_disc(p_tcb->peer_bda, reason);
    787     }
    788 }
    789 
    790 /*******************************************************************************
    791 **
    792 ** Function         gatt_l2cif_data_ind_cback
    793 **
    794 ** Description      This is the L2CAP data indication callback function.
    795 **
    796 **
    797 ** Returns          void
    798 **
    799 *******************************************************************************/
    800 void gatt_l2cif_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
    801 {
    802     tGATT_TCB       *p_tcb;
    803 
    804     /* look up clcb for this channel */
    805     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL &&
    806         gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
    807     {
    808         /* process the data */
    809         gatt_data_process(p_tcb, p_buf);
    810     }
    811     else /* prevent buffer leak */
    812         GKI_freebuf(p_buf);
    813 }
    814 
    815 /*******************************************************************************
    816 **
    817 ** Function         gatt_send_conn_cback
    818 **
    819 ** Description      Callback used to notify layer above about a connection.
    820 **
    821 **
    822 ** Returns          void
    823 **
    824 *******************************************************************************/
    825 static void gatt_send_conn_cback(tGATT_TCB *p_tcb)
    826 {
    827     UINT8               i;
    828     tGATT_REG           *p_reg;
    829     tGATT_BG_CONN_DEV   *p_bg_dev=NULL;
    830     UINT16              conn_id;
    831 
    832     p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
    833 
    834     /* notifying all applications for the connection up event */
    835     for (i = 0,  p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++)
    836     {
    837         if (p_reg->in_use)
    838         {
    839             if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if))
    840                 gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE);
    841 
    842             if (p_reg->app_cb.p_conn_cb)
    843             {
    844                 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
    845                 (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, TRUE, 0);
    846             }
    847         }
    848     }
    849 
    850 
    851     if (gatt_num_apps_hold_link(p_tcb))
    852     {
    853         /* disable idle timeout if one or more clients are holding the link disable the idle timer */
    854         GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT);
    855     }
    856 }
    857 
    858 /*******************************************************************************
    859 **
    860 ** Function         gatt_le_data_ind
    861 **
    862 ** Description      This function is called when data is received from L2CAP.
    863 **                  if we are the originator of the connection, we are the ATT
    864 **                  client, and the received message is queued up for the client.
    865 **
    866 **                  If we are the destination of the connection, we are the ATT
    867 **                  server, so the message is passed to the server processing
    868 **                  function.
    869 **
    870 ** Returns          void
    871 **
    872 *******************************************************************************/
    873 void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf)
    874 {
    875     UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
    876     UINT8   op_code, pseudo_op_code;
    877     UINT16  msg_len;
    878 
    879 
    880     if (p_buf->len > 0)
    881     {
    882         msg_len = p_buf->len - 1;
    883         STREAM_TO_UINT8(op_code, p);
    884 
    885         /* remove the two MSBs associated with sign write and write cmd */
    886         pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK);
    887 
    888         if (pseudo_op_code < GATT_OP_CODE_MAX)
    889         {
    890             if (op_code == GATT_SIGN_CMD_WRITE)
    891             {
    892                 gatt_verify_signature(p_tcb, p_buf);
    893                 return;
    894             }
    895             else
    896             {
    897                 /* message from client */
    898                 if ((op_code % 2) == 0)
    899                     gatt_server_handle_client_req (p_tcb, op_code, msg_len, p);
    900                 else
    901                     gatt_client_handle_server_rsp (p_tcb, op_code, msg_len, p);
    902             }
    903         }
    904         else
    905         {
    906             GATT_TRACE_ERROR1 ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x", op_code);
    907         }
    908     }
    909     else
    910     {
    911         GATT_TRACE_ERROR0 ("invalid data length, ignore");
    912     }
    913 
    914     GKI_freebuf (p_buf);
    915 }
    916 
    917 /*******************************************************************************
    918 **
    919 ** Function         gatt_add_a_bonded_dev_for_srv_chg
    920 **
    921 ** Description      Add a bonded dev to the service changed client list
    922 **
    923 ** Returns          void
    924 **
    925 *******************************************************************************/
    926 void gatt_add_a_bonded_dev_for_srv_chg (BD_ADDR bda)
    927 {
    928     tGATTS_SRV_CHG *p_buf;
    929     tGATTS_SRV_CHG_REQ req;
    930     tGATTS_SRV_CHG srv_chg_clt;
    931 
    932     memcpy(srv_chg_clt.bda, bda, BD_ADDR_LEN);
    933     srv_chg_clt.srv_changed = FALSE;
    934     if ((p_buf = gatt_add_srv_chg_clt(&srv_chg_clt)) != NULL)
    935     {
    936         memcpy(req.srv_chg.bda, bda, BD_ADDR_LEN);
    937         req.srv_chg.srv_changed = FALSE;
    938         if (gatt_cb.cb_info.p_srv_chg_callback)
    939             (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req, NULL);
    940     }
    941 
    942 }
    943 
    944 /*******************************************************************************
    945 **
    946 ** Function         gatt_send_srv_chg_ind
    947 **
    948 ** Description      This function is called to send a service chnaged indication to
    949 **                  the specified bd address
    950 **
    951 ** Returns          void
    952 **
    953 *******************************************************************************/
    954 void gatt_send_srv_chg_ind (BD_ADDR peer_bda)
    955 {
    956     UINT8   handle_range[GATT_SIZE_OF_SRV_CHG_HNDL_RANGE];
    957     UINT8   *p = handle_range;
    958     UINT16  conn_id;
    959 
    960     GATT_TRACE_DEBUG0("gatt_send_srv_chg_ind");
    961 
    962     if (gatt_cb.handle_of_h_r)
    963     {
    964         if ((conn_id = gatt_profile_find_conn_id_by_bd_addr(peer_bda)) != GATT_INVALID_CONN_ID)
    965         {
    966             UINT16_TO_STREAM (p, 1);
    967             UINT16_TO_STREAM (p, 0xFFFF);
    968             GATTS_HandleValueIndication (conn_id,
    969                                          gatt_cb.handle_of_h_r,
    970                                          GATT_SIZE_OF_SRV_CHG_HNDL_RANGE,
    971                                          handle_range);
    972         }
    973         else
    974         {
    975             GATT_TRACE_ERROR2("Unable to find conn_id for  %08x%04x ",
    976                               (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
    977                               (peer_bda[4]<<8)+peer_bda[5] );
    978         }
    979     }
    980 }
    981 
    982 /*******************************************************************************
    983 **
    984 ** Function         gatt_chk_srv_chg
    985 **
    986 ** Description      Check sending service chnaged Indication is required or not
    987 **                  if required then send the Indication
    988 **
    989 ** Returns          void
    990 **
    991 *******************************************************************************/
    992 void gatt_chk_srv_chg(tGATTS_SRV_CHG *p_srv_chg_clt)
    993 {
    994     GATT_TRACE_DEBUG1("gatt_chk_srv_chg srv_changed=%d", p_srv_chg_clt->srv_changed );
    995 
    996     if (p_srv_chg_clt->srv_changed)
    997     {
    998         gatt_send_srv_chg_ind(p_srv_chg_clt->bda);
    999     }
   1000 }
   1001 
   1002 /*******************************************************************************
   1003 **
   1004 ** Function         gatt_init_srv_chg
   1005 **
   1006 ** Description      This function is used to initialize the service changed
   1007 **                  attribute value
   1008 **
   1009 ** Returns          void
   1010 **
   1011 *******************************************************************************/
   1012 void gatt_init_srv_chg (void)
   1013 {
   1014     tGATTS_SRV_CHG_REQ req;
   1015     tGATTS_SRV_CHG_RSP rsp;
   1016     BOOLEAN status;
   1017     UINT8 num_clients,i;
   1018     tGATTS_SRV_CHG  srv_chg_clt;
   1019 
   1020     GATT_TRACE_DEBUG0("gatt_init_srv_chg");
   1021     if (gatt_cb.cb_info.p_srv_chg_callback)
   1022     {
   1023         status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_NUM_CLENTS, NULL, &rsp);
   1024 
   1025         if (status && rsp.num_clients)
   1026         {
   1027             GATT_TRACE_DEBUG1("gatt_init_srv_chg num_srv_chg_clt_clients=%d", rsp.num_clients);
   1028             num_clients = rsp.num_clients;
   1029             i = 1; /* use one based index */
   1030             while ((i <= num_clients) && status)
   1031             {
   1032                 req.client_read_index = i;
   1033                 if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)) == TRUE)
   1034                 {
   1035                     memcpy(&srv_chg_clt, &rsp.srv_chg ,sizeof(tGATTS_SRV_CHG));
   1036                     if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL)
   1037                     {
   1038                         GATT_TRACE_ERROR0("Unable to add a service change client");
   1039                         status = FALSE;
   1040                     }
   1041                 }
   1042                 i++;
   1043             }
   1044         }
   1045     }
   1046     else
   1047     {
   1048         GATT_TRACE_DEBUG0("gatt_init_srv_chg callback not registered yet");
   1049     }
   1050 }
   1051 
   1052 /*******************************************************************************
   1053 **
   1054 ** Function         gatt_proc_srv_chg
   1055 **
   1056 ** Description      This function is process the service changed request
   1057 **
   1058 ** Returns          void
   1059 **
   1060 *******************************************************************************/
   1061 void gatt_proc_srv_chg (void)
   1062 {
   1063     UINT8               start_idx, found_idx;
   1064     BD_ADDR             bda;
   1065     BOOLEAN             srv_chg_ind_pending=FALSE;
   1066     tGATT_TCB           *p_tcb;
   1067 
   1068     GATT_TRACE_DEBUG0 ("gatt_proc_srv_chg");
   1069 
   1070     if (gatt_cb.cb_info.p_srv_chg_callback && gatt_cb.handle_of_h_r)
   1071     {
   1072         gatt_set_srv_chg();
   1073         start_idx =0;
   1074         while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
   1075         {
   1076             p_tcb = &gatt_cb.tcb[found_idx];;
   1077             srv_chg_ind_pending  = gatt_is_srv_chg_ind_pending(p_tcb);
   1078 
   1079             if (!srv_chg_ind_pending)
   1080             {
   1081                 gatt_send_srv_chg_ind(bda);
   1082             }
   1083             else
   1084             {
   1085                 GATT_TRACE_DEBUG0 ("discard srv chg - already has one in the queue");
   1086             }
   1087             start_idx = ++found_idx;
   1088         }
   1089     }
   1090 }
   1091 
   1092 /*******************************************************************************
   1093 **
   1094 ** Function         gatt_set_ch_state
   1095 **
   1096 ** Description      This function set the ch_state in tcb
   1097 **
   1098 ** Returns          none
   1099 **
   1100 *******************************************************************************/
   1101 void gatt_set_ch_state(tGATT_TCB *p_tcb, tGATT_CH_STATE ch_state)
   1102 {
   1103     if (p_tcb)
   1104     {
   1105         GATT_TRACE_DEBUG2 ("gatt_set_ch_state: old=%d new=%d", p_tcb->ch_state, ch_state);
   1106         p_tcb->ch_state = ch_state;
   1107     }
   1108 }
   1109 
   1110 /*******************************************************************************
   1111 **
   1112 ** Function         gatt_get_ch_state
   1113 **
   1114 ** Description      This function get the ch_state in tcb
   1115 **
   1116 ** Returns          none
   1117 **
   1118 *******************************************************************************/
   1119 tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB *p_tcb)
   1120 {
   1121     tGATT_CH_STATE ch_state = GATT_CH_CLOSE;
   1122     if (p_tcb)
   1123     {
   1124         GATT_TRACE_DEBUG1 ("gatt_get_ch_state: ch_state=%d", p_tcb->ch_state);
   1125         ch_state = p_tcb->ch_state;
   1126     }
   1127     return ch_state;
   1128 }
   1129 
   1130 #endif /* BLE_INCLUDED */
   1131