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