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  ******************************************************************************/
gatt_init(void)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  ******************************************************************************/
gatt_free(void)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  ******************************************************************************/
gatt_connect(BD_ADDR rem_bda,tGATT_TCB * p_tcb,tBT_TRANSPORT transport,uint8_t initiating_phys)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  ******************************************************************************/
gatt_disconnect(tGATT_TCB * p_tcb)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  ******************************************************************************/
gatt_update_app_hold_link_status(tGATT_IF gatt_if,tGATT_TCB * p_tcb,bool is_add)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  ******************************************************************************/
gatt_update_app_use_link_flag(tGATT_IF gatt_if,tGATT_TCB * p_tcb,bool is_add,bool check_acl_link)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  ******************************************************************************/
gatt_act_connect(tGATT_REG * p_reg,BD_ADDR bd_addr,tBT_TRANSPORT transport,bool opportunistic,int8_t initiating_phys)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  ******************************************************************************/
gatt_le_connect_cback(uint16_t chan,BD_ADDR bd_addr,bool connected,uint16_t reason,tBT_TRANSPORT transport)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  ******************************************************************************/
gatt_channel_congestion(tGATT_TCB * p_tcb,bool congested)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 
gatt_notify_phy_updated(tGATT_TCB * p_tcb,uint8_t tx_phy,uint8_t rx_phy,uint8_t status)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 
gatt_notify_conn_update(uint16_t handle,uint16_t interval,uint16_t latency,uint16_t timeout,uint8_t status)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  ******************************************************************************/
gatt_le_cong_cback(BD_ADDR remote_bda,bool congested)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  ******************************************************************************/
gatt_le_data_ind(uint16_t chan,BD_ADDR bd_addr,BT_HDR * p_buf)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  ******************************************************************************/
gatt_l2cif_connect_ind_cback(BD_ADDR bd_addr,uint16_t lcid,UNUSED_ATTR uint16_t psm,uint8_t id)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  ******************************************************************************/
gatt_l2cif_connect_cfm_cback(uint16_t lcid,uint16_t result)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  ******************************************************************************/
gatt_l2cif_config_cfm_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)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  ******************************************************************************/
gatt_l2cif_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)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  ******************************************************************************/
gatt_l2cif_disconnect_ind_cback(uint16_t lcid,bool ack_needed)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  ******************************************************************************/
gatt_l2cif_disconnect_cfm_cback(uint16_t lcid,UNUSED_ATTR uint16_t result)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  ******************************************************************************/
gatt_l2cif_data_ind_cback(uint16_t lcid,BT_HDR * p_buf)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  ******************************************************************************/
gatt_l2cif_congest_cback(uint16_t lcid,bool congested)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  ******************************************************************************/
gatt_send_conn_cback(tGATT_TCB * p_tcb)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  ******************************************************************************/
gatt_data_process(tGATT_TCB * p_tcb,BT_HDR * p_buf)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  ******************************************************************************/
gatt_add_a_bonded_dev_for_srv_chg(BD_ADDR bda)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  ******************************************************************************/
gatt_send_srv_chg_ind(BD_ADDR peer_bda)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  ******************************************************************************/
gatt_chk_srv_chg(tGATTS_SRV_CHG * p_srv_chg_clt)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  ******************************************************************************/
gatt_init_srv_chg(void)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  ******************************************************************************/
gatt_proc_srv_chg(void)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  ******************************************************************************/
gatt_set_ch_state(tGATT_TCB * p_tcb,tGATT_CH_STATE ch_state)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  ******************************************************************************/
gatt_get_ch_state(tGATT_TCB * p_tcb)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