1 /******************************************************************************
3 * Copyright (C) 2008-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * this file contains the main ATT functions
23 ******************************************************************************/
25 #include "bt_target.h"
27 #if BLE_INCLUDED == TRUE
32 #include "btm_ble_int.h"
33 #include "allocator.h"
35 /* Configuration flags. */
36 #define GATT_L2C_CFG_IND_DONE (1<<0)
37 #define GATT_L2C_CFG_CFM_DONE (1<<1)
39 /* minimum GATT MTU size over BR/EDR link
41 #define GATT_MIN_BR_MTU_SIZE 48
43 /********************************************************************************/
44 /* L O C A L F U N C T I O N P R O T O T Y P E S */
45 /********************************************************************************/
46 static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
47 UINT16 reason, tBT_TRANSPORT transport);
48 static void gatt_le_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf);
49 static void gatt_le_cong_cback(BD_ADDR remote_bda, BOOLEAN congest);
50 #if (CLASSIC_BT_INCLUDED == TRUE)
51 static void gatt_l2cif_connect_ind_cback (BD_ADDR bd_addr, UINT16 l2cap_cid,
52 UINT16 psm, UINT8 l2cap_id);
53 static void gatt_l2cif_connect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
54 static void gatt_l2cif_config_ind_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
55 static void gatt_l2cif_config_cfm_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
56 static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed);
57 static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
58 static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg);
59 #endif ///CLASSIC_BT_INCLUDED == TRUE
60 static void gatt_send_conn_cback (tGATT_TCB *p_tcb);
61 #if (CLASSIC_BT_INCLUDED == TRUE)
62 static void gatt_l2cif_congest_cback (UINT16 cid, BOOLEAN congested);
63 static const tL2CAP_APPL_INFO dyn_info = {
64 gatt_l2cif_connect_ind_cback,
65 gatt_l2cif_connect_cfm_cback,
67 gatt_l2cif_config_ind_cback,
68 gatt_l2cif_config_cfm_cback,
69 gatt_l2cif_disconnect_ind_cback,
70 gatt_l2cif_disconnect_cfm_cback,
72 gatt_l2cif_data_ind_cback,
73 gatt_l2cif_congest_cback,
76 #endif ///SMP_INCLUDED == TRUE
78 #if GATT_DYNAMIC_MEMORY == FALSE
81 tGATT_CB *gatt_cb_ptr;
84 tGATT_DEFAULT gatt_default;
86 /*******************************************************************************
90 ** Description This function is enable the GATT profile on the device.
91 ** It clears out the control blocks, and registers with L2CAP.
95 *******************************************************************************/
98 tL2CAP_FIXED_CHNL_REG fixed_reg;
99 #if GATT_DYNAMIC_MEMORY
100 gatt_cb_ptr = (tGATT_CB *)osi_malloc(sizeof(tGATT_CB));
101 #endif /* #if GATT_DYNAMIC_MEMORY */
102 memset (&gatt_cb, 0, sizeof(tGATT_CB));
103 memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG));
105 #if defined(GATT_INITIAL_TRACE_LEVEL)
106 gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL;
108 gatt_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
110 gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE;
111 gatt_cb.sign_op_queue = fixed_queue_new(SIZE_MAX);
112 gatt_cb.srv_chg_clt_q = fixed_queue_new(SIZE_MAX);
113 gatt_cb.pending_new_srv_start_q = fixed_queue_new(SIZE_MAX);
114 /* First, register fixed L2CAP channel for ATT over BLE */
115 fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE;
116 fixed_reg.fixed_chnl_opts.max_transmit = 0xFF;
117 fixed_reg.fixed_chnl_opts.rtrans_tout = 2000;
118 fixed_reg.fixed_chnl_opts.mon_tout = 12000;
119 fixed_reg.fixed_chnl_opts.mps = 670;
120 fixed_reg.fixed_chnl_opts.tx_win_sz = 1;
122 fixed_reg.pL2CA_FixedConn_Cb = gatt_le_connect_cback;
123 fixed_reg.pL2CA_FixedData_Cb = gatt_le_data_ind;
124 fixed_reg.pL2CA_FixedCong_Cb = gatt_le_cong_cback; /* congestion callback */
125 fixed_reg.default_idle_tout = 0xffff; /* 0xffff default idle timeout */
127 L2CA_RegisterFixedChannel (L2CAP_ATT_CID, &fixed_reg);
128 #if (CLASSIC_BT_INCLUDED == TRUE)
129 /* Now, register with L2CAP for ATT PSM over BR/EDR */
130 if (!L2CA_Register (BT_PSM_ATT, (tL2CAP_APPL_INFO *) &dyn_info)) {
131 GATT_TRACE_ERROR ("ATT Dynamic Registration failed");
133 #endif ///CLASSIC_BT_INCLUDED == TRUE
134 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0);
135 BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0);
137 gatt_cb.hdl_cfg.gatt_start_hdl = GATT_GATT_START_HANDLE;
138 gatt_cb.hdl_cfg.gap_start_hdl = GATT_GAP_START_HANDLE;
139 gatt_cb.hdl_cfg.app_start_hdl = GATT_APP_START_HANDLE;
140 #if (GATTS_INCLUDED == TRUE)
141 gatt_profile_db_init();
142 #endif ///GATTS_INCLUDED == TRUE
143 //init local MTU size
144 gatt_default.local_mtu = GATT_MAX_MTU_SIZE;
148 /*******************************************************************************
150 ** Function gatt_free
152 ** Description This function frees resources used by the GATT profile.
156 *******************************************************************************/
157 #if (GATT_INCLUDED == TRUE)
161 GATT_TRACE_DEBUG("gatt_free()");
162 fixed_queue_free(gatt_cb.sign_op_queue, NULL);
163 gatt_cb.sign_op_queue = NULL;
164 fixed_queue_free(gatt_cb.srv_chg_clt_q, NULL);
165 gatt_cb.srv_chg_clt_q = NULL;
166 fixed_queue_free(gatt_cb.pending_new_srv_start_q, NULL);
167 gatt_cb.pending_new_srv_start_q = NULL;
169 for (i = 0; i < GATT_MAX_PHY_CHANNEL; i++)
171 fixed_queue_free(gatt_cb.tcb[i].pending_enc_clcb, NULL);
172 gatt_cb.tcb[i].pending_enc_clcb = NULL;
174 fixed_queue_free(gatt_cb.tcb[i].pending_ind_q, NULL);
175 gatt_cb.tcb[i].pending_ind_q = NULL;
177 btu_free_timer(&gatt_cb.tcb[i].conf_timer_ent);
178 memset(&gatt_cb.tcb[i].conf_timer_ent, 0, sizeof(TIMER_LIST_ENT));
180 btu_free_timer(&gatt_cb.tcb[i].ind_ack_timer_ent);
181 memset(&gatt_cb.tcb[i].ind_ack_timer_ent, 0, sizeof(TIMER_LIST_ENT));
183 #if (GATTS_INCLUDED == TRUE)
184 fixed_queue_free(gatt_cb.tcb[i].sr_cmd.multi_rsp_q, NULL);
185 gatt_cb.tcb[i].sr_cmd.multi_rsp_q = NULL;
186 #endif /* #if (GATTS_INCLUDED == TRUE) */
189 #if (GATTS_INCLUDED == TRUE)
190 for (i = 0; i < GATT_MAX_SR_PROFILES; i++) {
191 gatt_free_hdl_buffer(&gatt_cb.hdl_list[i]);
193 #endif /* #if (GATTS_INCLUDED == TRUE) */
194 #if GATT_DYNAMIC_MEMORY
195 FREE_AND_RESET(gatt_cb_ptr);
196 #endif /* #if GATT_DYNAMIC_MEMORY */
198 #endif ///GATTS_INCLUDED == TRUE
200 /*******************************************************************************
202 ** Function gatt_connect
204 ** Description This function is called to initiate a connection to a peer device.
206 ** Parameter rem_bda: remote device address to connect to.
208 ** Returns TRUE if connection is started, otherwise return FALSE.
210 *******************************************************************************/
211 BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb, tBT_TRANSPORT transport)
213 BOOLEAN gatt_ret = FALSE;
215 if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN) {
216 gatt_set_ch_state(p_tcb, GATT_CH_CONN);
219 if (transport == BT_TRANSPORT_LE) {
220 p_tcb->att_lcid = L2CAP_ATT_CID;
221 gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda);
222 #if (CLASSIC_BT_INCLUDED == TRUE)
224 if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) != 0) {
227 #endif ///CLASSIC_BT_INCLUDED == TRUE
234 /*******************************************************************************
236 ** Function gatt_disconnect
238 ** Description This function is called to disconnect to an ATT device.
240 ** Parameter p_tcb: pointer to the TCB to disconnect.
242 ** Returns TRUE: if connection found and to be disconnected; otherwise
245 *******************************************************************************/
246 BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb)
249 tGATT_CH_STATE ch_state;
250 GATT_TRACE_DEBUG ("gatt_disconnect ");
254 if ( (ch_state = gatt_get_ch_state(p_tcb)) != GATT_CH_CLOSING ) {
255 if (p_tcb->att_lcid == L2CAP_ATT_CID) {
256 if (ch_state == GATT_CH_OPEN) {
257 /* only LCB exist between remote device and local */
258 ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, p_tcb->peer_bda);
260 gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
261 ret = L2CA_CancelBleConnectReq (p_tcb->peer_bda);
263 #if (CLASSIC_BT_INCLUDED == TRUE)
265 ret = L2CA_DisconnectReq(p_tcb->att_lcid);
266 #endif ///CLASSIC_BT_INCLUDED == TRUE
269 GATT_TRACE_DEBUG ("gatt_disconnect already in closing state");
276 /*******************************************************************************
278 ** Function gatt_update_app_hold_link_status
280 ** Description Update the application use link status
284 *******************************************************************************/
285 void gatt_update_app_hold_link_status (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
288 BOOLEAN found = FALSE;
291 GATT_TRACE_ERROR("gatt_update_app_hold_link_status p_tcb=NULL");
296 for (i = 0; i < GATT_MAX_APPS; i++) {
297 if (p_tcb->app_hold_link[i] == gatt_if) {
300 p_tcb->app_hold_link[i] = 0;
306 if (!found && is_add) {
307 for (i = 0; i < GATT_MAX_APPS; i++) {
308 if (p_tcb->app_hold_link[i] == 0) {
309 p_tcb->app_hold_link[i] = gatt_if;
316 GATT_TRACE_DEBUG("gatt_update_app_hold_link_status found=%d[1-found] idx=%d gatt_if=%d is_add=%d", found, i, gatt_if, is_add);
320 /*******************************************************************************
322 ** Function gatt_update_app_use_link_flag
324 ** Description Update the application use link flag and optional to check the acl link
325 ** if the link is up then set the idle time out accordingly
329 *******************************************************************************/
330 void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link)
332 GATT_TRACE_DEBUG("gatt_update_app_use_link_flag is_add=%d chk_link=%d",
333 is_add, check_acl_link);
335 gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add);
337 if (check_acl_link &&
339 p_tcb->att_lcid == L2CAP_ATT_CID && /* only update link idle timer for fixed channel */
340 (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) != GATT_INVALID_ACL_HANDLE)) {
342 GATT_TRACE_DEBUG("GATT disables link idle timer");
343 /* acl link is connected disable the idle timeout */
344 GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
346 if (!gatt_num_apps_hold_link(p_tcb)) {
347 /* acl link is connected but no application needs to use the link
348 so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
349 GATT_TRACE_DEBUG("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
350 GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, p_tcb->transport);
357 /*******************************************************************************
359 ** Function gatt_act_connect
361 ** Description GATT connection initiation.
365 *******************************************************************************/
366 BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport)
372 if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, transport)) != NULL) {
374 st = gatt_get_ch_state(p_tcb);
376 /* before link down, another app try to open a GATT connection */
377 if (st == GATT_CH_OPEN && gatt_num_apps_hold_link(p_tcb) == 0 &&
378 transport == BT_TRANSPORT_LE ) {
379 if (!gatt_connect(bd_addr, p_tcb, transport)) {
382 } else if (st == GATT_CH_CLOSING) {
383 /* need to complete the closing first */
387 if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, transport)) != NULL) {
388 if (!gatt_connect(bd_addr, p_tcb, transport)) {
389 GATT_TRACE_ERROR("gatt_connect failed");
390 fixed_queue_free(p_tcb->pending_enc_clcb, NULL);
391 fixed_queue_free(p_tcb->pending_ind_q, NULL);
392 memset(p_tcb, 0, sizeof(tGATT_TCB));
398 GATT_TRACE_ERROR("Max TCB for gatt_if [%d] reached.", p_reg->gatt_if);
403 gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
409 /*******************************************************************************
411 ** Function gatt_le_connect_cback
413 ** Description This callback function is called by L2CAP to indicate that
414 ** the ATT fixed channel for LE is
415 ** connected (conn = TRUE)/disconnected (conn = FALSE).
417 *******************************************************************************/
418 static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
419 UINT16 reason, tBT_TRANSPORT transport)
422 tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
423 BOOLEAN check_srv_chg = FALSE;
424 tGATTS_SRV_CHG *p_srv_chg_clt = NULL;
426 /* ignore all fixed channel connect/disconnect on BR/EDR link for GATT */
427 if (transport == BT_TRANSPORT_BR_EDR) {
431 GATT_TRACE_DEBUG ("GATT ATT protocol channel with BDA: %08x%04x is %s",
432 (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
433 (bd_addr[4] << 8) + bd_addr[5], (connected) ? "connected" : "disconnected");
435 if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL) {
436 check_srv_chg = TRUE;
438 if (btm_sec_is_a_bonded_dev(bd_addr)) {
439 gatt_add_a_bonded_dev_for_srv_chg(bd_addr);
444 /* do we have a channel initiating a connection? */
446 /* we are initiating connection */
447 if ( gatt_get_ch_state(p_tcb) == GATT_CH_CONN) {
449 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
450 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
452 gatt_send_conn_cback(p_tcb);
455 #if (GATTS_INCLUDED == TRUE)
456 gatt_chk_srv_chg (p_srv_chg_clt);
457 #endif ///GATTS_INCLUDED == TRUE
460 /* this is incoming connection or background connection callback */
463 if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_LE)) != NULL) {
464 p_tcb->att_lcid = L2CAP_ATT_CID;
466 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
468 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
470 gatt_send_conn_cback (p_tcb);
472 #if (GATTS_INCLUDED == TRUE)
473 gatt_chk_srv_chg (p_srv_chg_clt);
474 #endif ///GATTS_INCLUDED == TRUE
477 GATT_TRACE_ERROR("CCB max out, no rsources");
481 gatt_cleanup_upon_disc(bd_addr, reason, transport);
482 GATT_TRACE_DEBUG ("ATT disconnected");
486 /*******************************************************************************
488 ** Function gatt_channel_congestion
490 ** Description This function is called to process the congestion callback
495 *******************************************************************************/
496 static void gatt_channel_congestion(tGATT_TCB *p_tcb, BOOLEAN congested)
499 tGATT_REG *p_reg = NULL;
501 #if (GATTC_INCLUDED == TRUE)
502 /* if uncongested, check to see if there is any more pending data */
503 if (p_tcb != NULL && congested == FALSE) {
504 gatt_cl_send_next_cmd_inq(p_tcb);
506 #endif ///GATTC_INCLUDED == TRUE
507 /* notifying all applications for the connection up event */
508 for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++) {
510 if (p_reg->app_cb.p_congestion_cb) {
511 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
512 (*p_reg->app_cb.p_congestion_cb)(conn_id, congested);
518 /*******************************************************************************
520 ** Function gatt_le_cong_cback
522 ** Description This function is called when GATT fixed channel is congested
527 *******************************************************************************/
528 static void gatt_le_cong_cback(BD_ADDR remote_bda, BOOLEAN congested)
530 tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(remote_bda, BT_TRANSPORT_LE);
532 /* if uncongested, check to see if there is any more pending data */
534 gatt_channel_congestion(p_tcb, congested);
538 /*******************************************************************************
540 ** Function gatt_le_data_ind
542 ** Description This function is called when data is received from L2CAP.
543 ** if we are the originator of the connection, we are the ATT
544 ** client, and the received message is queued up for the client.
546 ** If we are the destination of the connection, we are the ATT
547 ** server, so the message is passed to the server processing
552 *******************************************************************************/
553 static void gatt_le_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
557 /* Find CCB based on bd addr */
558 if ((p_tcb = gatt_find_tcb_by_addr (bd_addr, BT_TRANSPORT_LE)) != NULL &&
559 gatt_get_ch_state(p_tcb) >= GATT_CH_OPEN) {
560 gatt_data_process(p_tcb, p_buf);
565 GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d\n",
566 gatt_get_ch_state(p_tcb));
571 /*******************************************************************************
573 ** Function gatt_l2cif_connect_ind
575 ** Description This function handles an inbound connection indication
576 ** from L2CAP. This is the case where we are acting as a
581 *******************************************************************************/
582 #if (CLASSIC_BT_INCLUDED == TRUE)
583 static void gatt_l2cif_connect_ind_cback (BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
585 /* do we already have a control channel for this peer? */
586 UINT8 result = L2CAP_CONN_OK;
588 tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_BR_EDR);
591 GATT_TRACE_ERROR("Connection indication cid = %d", lcid);
592 /* new connection ? */
595 if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL) {
596 /* no tcb available, reject L2CAP connection */
597 result = L2CAP_CONN_NO_RESOURCES;
599 p_tcb->att_lcid = lcid;
602 } else { /* existing connection , reject it */
603 result = L2CAP_CONN_NO_RESOURCES;
606 /* Send L2CAP connect rsp */
607 L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
609 /* if result ok, proceed with connection */
610 if (result == L2CAP_CONN_OK) {
611 /* transition to configuration state */
612 gatt_set_ch_state(p_tcb, GATT_CH_CFG);
614 /* Send L2CAP config req */
615 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
616 cfg.mtu_present = TRUE;
617 cfg.mtu = gatt_default.local_mtu;
619 L2CA_ConfigReq(lcid, &cfg);
624 /*******************************************************************************
626 ** Function gatt_l2c_connect_cfm_cback
628 ** Description This is the L2CAP connect confirm callback function.
633 *******************************************************************************/
634 static void gatt_l2cif_connect_cfm_cback(UINT16 lcid, UINT16 result)
639 /* look up clcb for this channel */
640 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) {
641 GATT_TRACE_DEBUG("gatt_l2c_connect_cfm_cback result: %d ch_state: %d, lcid:0x%x", result, gatt_get_ch_state(p_tcb), p_tcb->att_lcid);
643 /* if in correct state */
644 if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN) {
645 /* if result successful */
646 if (result == L2CAP_CONN_OK) {
647 /* set channel state */
648 gatt_set_ch_state(p_tcb, GATT_CH_CFG);
650 /* Send L2CAP config req */
651 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
652 cfg.mtu_present = TRUE;
653 cfg.mtu = gatt_default.local_mtu;
654 L2CA_ConfigReq(lcid, &cfg);
656 /* else initiating connection failure */
658 gatt_cleanup_upon_disc(p_tcb->peer_bda, result, GATT_TRANSPORT_BR_EDR);
660 } else { /* wrong state, disconnect it */
661 if (result == L2CAP_CONN_OK) {
662 /* just in case the peer also accepts our connection - Send L2CAP disconnect req */
663 L2CA_DisconnectReq(lcid);
669 /*******************************************************************************
671 ** Function gatt_l2cif_config_cfm_cback
673 ** Description This is the L2CAP config confirm callback function.
678 *******************************************************************************/
679 void gatt_l2cif_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
682 tGATTS_SRV_CHG *p_srv_chg_clt = NULL;
684 /* look up clcb for this channel */
685 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) {
686 /* if in correct state */
687 if ( gatt_get_ch_state(p_tcb) == GATT_CH_CFG) {
688 /* if result successful */
689 if (p_cfg->result == L2CAP_CFG_OK) {
691 p_tcb->ch_flags |= GATT_L2C_CFG_CFM_DONE;
693 /* if configuration complete */
694 if (p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) {
695 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
697 if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL) {
698 #if (GATTS_INCLUDED == TRUE)
699 gatt_chk_srv_chg(p_srv_chg_clt);
700 #endif ///GATTS_INCLUDED == TRUE
702 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) {
703 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
708 gatt_send_conn_cback(p_tcb);
713 /* Send L2CAP disconnect req */
714 L2CA_DisconnectReq(lcid);
720 /*******************************************************************************
722 ** Function gatt_l2cif_config_ind_cback
724 ** Description This is the L2CAP config indication callback function.
729 *******************************************************************************/
730 void gatt_l2cif_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
733 tGATTS_SRV_CHG *p_srv_chg_clt = NULL;
734 /* look up clcb for this channel */
735 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) {
736 /* GATT uses the smaller of our MTU and peer's MTU */
737 if ( p_cfg->mtu_present &&
738 (p_cfg->mtu >= GATT_MIN_BR_MTU_SIZE && p_cfg->mtu < L2CAP_DEFAULT_MTU)) {
739 p_tcb->payload_size = p_cfg->mtu;
741 p_tcb->payload_size = L2CAP_DEFAULT_MTU;
744 /* send L2CAP configure response */
745 memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
746 p_cfg->result = L2CAP_CFG_OK;
747 L2CA_ConfigRsp(lcid, p_cfg);
749 /* if first config ind */
750 if ((p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) == 0) {
752 p_tcb->ch_flags |= GATT_L2C_CFG_IND_DONE;
754 /* if configuration complete */
755 if (p_tcb->ch_flags & GATT_L2C_CFG_CFM_DONE) {
756 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
757 if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL) {
758 #if (GATTS_INCLUDED == TRUE)
759 gatt_chk_srv_chg(p_srv_chg_clt);
760 #endif ///GATTS_INCLUDED == TRUE
762 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) {
763 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
768 gatt_send_conn_cback(p_tcb);
774 /*******************************************************************************
776 ** Function gatt_l2cif_disconnect_ind_cback
778 ** Description This is the L2CAP disconnect indication callback function.
783 *******************************************************************************/
784 void gatt_l2cif_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
789 /* look up clcb for this channel */
790 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) {
792 /* send L2CAP disconnect response */
793 L2CA_DisconnectRsp(lcid);
795 if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) {
796 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) {
797 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
800 /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
801 if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport)) == 0) {
802 reason = GATT_CONN_TERMINATE_PEER_USER;
805 /* send disconnect callback */
806 gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
810 /*******************************************************************************
812 ** Function gatt_l2cif_disconnect_cfm_cback
814 ** Description This is the L2CAP disconnect confirm callback function.
819 *******************************************************************************/
820 static void gatt_l2cif_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
826 /* look up clcb for this channel */
827 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) {
828 /* If the device is not in the service changed client list, add it... */
829 if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) {
830 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) {
831 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
835 /* send disconnect callback */
836 /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
837 if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport)) == 0) {
838 reason = GATT_CONN_TERMINATE_LOCAL_HOST;
841 gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
845 /*******************************************************************************
847 ** Function gatt_l2cif_data_ind_cback
849 ** Description This is the L2CAP data indication callback function.
854 *******************************************************************************/
855 static void gatt_l2cif_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
859 /* look up clcb for this channel */
860 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL &&
861 gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
862 /* process the data */
863 gatt_data_process(p_tcb, p_buf);
864 } else { /* prevent buffer leak */
870 /*******************************************************************************
872 ** Function gatt_l2cif_congest_cback
874 ** Description L2CAP congestion callback
878 *******************************************************************************/
879 static void gatt_l2cif_congest_cback (UINT16 lcid, BOOLEAN congested)
881 tGATT_TCB *p_tcb = gatt_find_tcb_by_cid(lcid);
884 gatt_channel_congestion(p_tcb, congested);
888 #endif ///CLASSIC_BT_INCLUDED == TRUE
890 /*******************************************************************************
892 ** Function gatt_send_conn_cback
894 ** Description Callback used to notify layer above about a connection.
899 *******************************************************************************/
900 static void gatt_send_conn_cback(tGATT_TCB *p_tcb)
904 tGATT_BG_CONN_DEV *p_bg_dev = NULL;
907 p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
909 /* notifying all applications for the connection up event */
910 for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++) {
912 if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if)) {
913 gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE);
916 if (p_reg->app_cb.p_conn_cb) {
917 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
918 (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id,
919 TRUE, 0, p_tcb->transport);
925 if (gatt_num_apps_hold_link(p_tcb) && p_tcb->att_lcid == L2CAP_ATT_CID ) {
926 /* disable idle timeout if one or more clients are holding the link disable the idle timer */
927 GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
931 /*******************************************************************************
933 ** Function gatt_le_data_ind
935 ** Description This function is called when data is received from L2CAP.
936 ** if we are the originator of the connection, we are the ATT
937 ** client, and the received message is queued up for the client.
939 ** If we are the destination of the connection, we are the ATT
940 ** server, so the message is passed to the server processing
945 *******************************************************************************/
946 void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf)
948 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
949 UINT8 op_code, pseudo_op_code;
950 #if (GATTS_INCLUDED == TRUE) || (GATTC_INCLUDED == TRUE)
952 #endif ///(GATTS_INCLUDED == TRUE) || (GATTC_INCLUDED == TRUE)
955 if (p_buf->len > 0) {
956 #if (GATTS_INCLUDED == TRUE) || (GATTC_INCLUDED == TRUE)
957 msg_len = p_buf->len - 1;
958 #endif ///(GATTS_INCLUDED == TRUE) || (GATTC_INCLUDED == TRUE)
959 STREAM_TO_UINT8(op_code, p);
961 /* remove the two MSBs associated with sign write and write cmd */
962 pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK);
964 if (pseudo_op_code < GATT_OP_CODE_MAX) {
965 if (op_code == GATT_SIGN_CMD_WRITE) {
966 #if (SMP_INCLUDED == TRUE)
967 gatt_verify_signature(p_tcb, p_buf);
968 #endif ///SMP_INCLUDED == TRUE
970 /* message from client */
971 if ((op_code % 2) == 0) {
972 #if (GATTS_INCLUDED == TRUE)
973 gatt_server_handle_client_req (p_tcb, op_code, msg_len, p);
974 #endif ///GATTS_INCLUDED == TRUE
976 #if (GATTC_INCLUDED == TRUE)
977 gatt_client_handle_server_rsp (p_tcb, op_code, msg_len, p);
978 #endif ///GATTC_INCLUDED == TRUE
982 GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x\n", op_code);
985 GATT_TRACE_ERROR ("invalid data length, ignore\n");
991 /*******************************************************************************
993 ** Function gatt_add_a_bonded_dev_for_srv_chg
995 ** Description Add a bonded dev to the service changed client list
999 *******************************************************************************/
1000 void gatt_add_a_bonded_dev_for_srv_chg (BD_ADDR bda)
1002 tGATTS_SRV_CHG_REQ req;
1003 tGATTS_SRV_CHG srv_chg_clt;
1005 memcpy(srv_chg_clt.bda, bda, BD_ADDR_LEN);
1006 srv_chg_clt.srv_changed = FALSE;
1007 if (gatt_add_srv_chg_clt(&srv_chg_clt) != NULL) {
1008 memcpy(req.srv_chg.bda, bda, BD_ADDR_LEN);
1009 req.srv_chg.srv_changed = FALSE;
1010 if (gatt_cb.cb_info.p_srv_chg_callback) {
1011 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req, NULL);
1016 /*******************************************************************************
1018 ** Function gatt_send_srv_chg_ind
1020 ** Description This function is called to send a service chnaged indication to
1021 ** the specified bd address
1025 *******************************************************************************/
1026 #if (GATTS_INCLUDED == TRUE)
1027 void gatt_send_srv_chg_ind (BD_ADDR peer_bda)
1029 UINT8 handle_range[GATT_SIZE_OF_SRV_CHG_HNDL_RANGE];
1030 UINT8 *p = handle_range;
1033 GATT_TRACE_DEBUG("gatt_send_srv_chg_ind");
1035 if (gatt_cb.handle_of_h_r) {
1036 if ((conn_id = gatt_profile_find_conn_id_by_bd_addr(peer_bda)) != GATT_INVALID_CONN_ID) {
1037 UINT16_TO_STREAM (p, 1);
1038 UINT16_TO_STREAM (p, 0xFFFF);
1039 GATTS_HandleValueIndication (conn_id,
1040 gatt_cb.handle_of_h_r,
1041 GATT_SIZE_OF_SRV_CHG_HNDL_RANGE,
1044 GATT_TRACE_ERROR("Unable to find conn_id for %08x%04x ",
1045 (peer_bda[0] << 24) + (peer_bda[1] << 16) + (peer_bda[2] << 8) + peer_bda[3],
1046 (peer_bda[4] << 8) + peer_bda[5] );
1052 /*******************************************************************************
1054 ** Function gatt_chk_srv_chg
1056 ** Description Check sending service chnaged Indication is required or not
1057 ** if required then send the Indication
1061 *******************************************************************************/
1062 void gatt_chk_srv_chg(tGATTS_SRV_CHG *p_srv_chg_clt)
1064 GATT_TRACE_DEBUG("gatt_chk_srv_chg srv_changed=%d", p_srv_chg_clt->srv_changed );
1066 if (p_srv_chg_clt->srv_changed) {
1067 gatt_send_srv_chg_ind(p_srv_chg_clt->bda);
1070 #endif ///GATTS_INCLUDED == TRUE
1073 /*******************************************************************************
1075 ** Function gatt_init_srv_chg
1077 ** Description This function is used to initialize the service changed
1082 *******************************************************************************/
1083 void gatt_init_srv_chg (void)
1085 tGATTS_SRV_CHG_REQ req;
1086 tGATTS_SRV_CHG_RSP rsp;
1088 UINT8 num_clients, i;
1089 tGATTS_SRV_CHG srv_chg_clt;
1091 GATT_TRACE_DEBUG("gatt_init_srv_chg");
1092 if (gatt_cb.cb_info.p_srv_chg_callback) {
1093 status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_NUM_CLENTS, NULL, &rsp);
1095 if (status && rsp.num_clients) {
1096 GATT_TRACE_DEBUG("gatt_init_srv_chg num_srv_chg_clt_clients=%d", rsp.num_clients);
1097 num_clients = rsp.num_clients;
1098 i = 1; /* use one based index */
1099 while ((i <= num_clients) && status) {
1100 req.client_read_index = i;
1101 if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)) == TRUE) {
1102 memcpy(&srv_chg_clt, &rsp.srv_chg , sizeof(tGATTS_SRV_CHG));
1103 if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL) {
1104 GATT_TRACE_ERROR("Unable to add a service change client");
1112 GATT_TRACE_DEBUG("gatt_init_srv_chg callback not registered yet");
1116 /*******************************************************************************
1118 ** Function gatt_proc_srv_chg
1120 ** Description This function is process the service changed request
1124 *******************************************************************************/
1125 #if (GATTS_INCLUDED == TRUE)
1126 void gatt_proc_srv_chg (void)
1128 UINT8 start_idx, found_idx;
1130 BOOLEAN srv_chg_ind_pending = FALSE;
1132 tBT_TRANSPORT transport;
1134 GATT_TRACE_DEBUG ("gatt_proc_srv_chg");
1136 if (gatt_cb.cb_info.p_srv_chg_callback && gatt_cb.handle_of_h_r) {
1139 while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
1140 p_tcb = &gatt_cb.tcb[found_idx];;
1141 srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb);
1143 if (!srv_chg_ind_pending) {
1144 gatt_send_srv_chg_ind(bda);
1146 GATT_TRACE_DEBUG ("discard srv chg - already has one in the queue");
1148 start_idx = ++found_idx;
1152 #endif ///GATTS_INCLUDED == TRUE
1154 /*******************************************************************************
1156 ** Function gatt_set_ch_state
1158 ** Description This function set the ch_state in tcb
1162 *******************************************************************************/
1163 void gatt_set_ch_state(tGATT_TCB *p_tcb, tGATT_CH_STATE ch_state)
1166 GATT_TRACE_DEBUG ("gatt_set_ch_state: old=%d new=%d", p_tcb->ch_state, ch_state);
1167 p_tcb->ch_state = ch_state;
1171 /*******************************************************************************
1173 ** Function gatt_get_ch_state
1175 ** Description This function get the ch_state in tcb
1179 *******************************************************************************/
1180 tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB *p_tcb)
1182 tGATT_CH_STATE ch_state = GATT_CH_CLOSE;
1184 GATT_TRACE_DEBUG ("gatt_get_ch_state: ch_state=%d", p_tcb->ch_state);
1185 ch_state = p_tcb->ch_state;
1190 uint16_t gatt_get_local_mtu(void)
1192 return gatt_default.local_mtu;
1195 void gatt_set_local_mtu(uint16_t mtu)
1197 gatt_default.local_mtu = mtu;
1200 #endif /* BLE_INCLUDED */