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