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