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