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