/******************************************************************************* ** ** Function gatt_send_conn_cback ** ** Description Callback used to notify layer above about a connection. ** ** ** Returns void ** *******************************************************************************/ static void gatt_send_conn_cback(tGATT_TCB *p_tcb) { UINT8 i; tGATT_REG *p_reg; tGATT_BG_CONN_DEV *p_bg_dev=NULL; UINT16 conn_id; p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda); /* notifying all applications for the connection up event */ for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++) { if (p_reg->in_use) { if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if)) gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE); if (p_reg->app_cb.p_conn_cb) { conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, TRUE, 0, p_tcb->transport); } } } if (gatt_num_apps_hold_link(p_tcb) && p_tcb->att_lcid == L2CAP_ATT_CID ) { /* disable idle timeout if one or more clients are holding the link disable the idle timer */ GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport); } }
/******************************************************************************* ** ** Function gatt_update_app_use_link_flag ** ** Description Update the application use link flag and optional to check the acl link ** if the link is up then set the idle time out accordingly ** ** Returns void. ** *******************************************************************************/ void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link) { GATT_TRACE_DEBUG("gatt_update_app_use_link_flag is_add=%d chk_link=%d", is_add, check_acl_link); gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add); if (check_acl_link && p_tcb && p_tcb->att_lcid == L2CAP_ATT_CID && /* only update link idle timer for fixed channel */ (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) != GATT_INVALID_ACL_HANDLE)) { if (is_add) { GATT_TRACE_DEBUG("GATT disables link idle timer"); /* acl link is connected disable the idle timeout */ GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport); } else { if (!gatt_num_apps_hold_link(p_tcb)) { /* acl link is connected but no application needs to use the link so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */ GATT_TRACE_DEBUG("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP); GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, p_tcb->transport); } } } }
/******************************************************************************* ** ** Function gatt_act_connect ** ** Description GATT connection initiation. ** ** Returns void. ** *******************************************************************************/ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr) { BOOLEAN ret = FALSE; tGATT_TCB *p_tcb; UINT8 st; GATT_TRACE_DEBUG0("gatt_act_connect"); if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL) { ret = TRUE; st = gatt_get_ch_state(p_tcb); /* before link down, another app try to open a GATT connection */ if(st == GATT_CH_OPEN && gatt_num_apps_hold_link(p_tcb) == 0 && /* only connection on fix channel when the l2cap channel is already open */ p_tcb->att_lcid == L2CAP_ATT_CID ) { if (!gatt_connect(bd_addr, p_tcb)) ret = FALSE; } else if(st == GATT_CH_CLOSING) { /* need to complete the closing first */ ret = FALSE; } } else { if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr)) != NULL) { if (!gatt_connect(bd_addr, p_tcb)) { GATT_TRACE_ERROR0("gatt_connect failed"); memset(p_tcb, 0, sizeof(tGATT_TCB)); } else ret = TRUE; } else { ret = 0; GATT_TRACE_ERROR1("Max TCB for gatt_if [%d] reached.", p_reg->gatt_if); } } if (ret) { gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE); } return ret; }
/******************************************************************************* ** ** Function gatt_act_connect ** ** Description GATT connection initiation. ** ** Returns void. ** *******************************************************************************/ BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport) { BOOLEAN ret = FALSE; tGATT_TCB *p_tcb; UINT8 st; if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, transport)) != NULL) { ret = TRUE; st = gatt_get_ch_state(p_tcb); /* before link down, another app try to open a GATT connection */ if(st == GATT_CH_OPEN && gatt_num_apps_hold_link(p_tcb) == 0 && transport == BT_TRANSPORT_LE ) { if (!gatt_connect(bd_addr, p_tcb, transport)) ret = FALSE; } else if(st == GATT_CH_CLOSING) { /* need to complete the closing first */ ret = FALSE; } } else { if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, transport)) != NULL) { if (!gatt_connect(bd_addr, p_tcb, transport)) { GATT_TRACE_ERROR("gatt_connect failed"); memset(p_tcb, 0, sizeof(tGATT_TCB)); } else ret = TRUE; } else { ret = 0; GATT_TRACE_ERROR("Max TCB for gatt_if [%d] reached.", p_reg->gatt_if); } } if (ret) { gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE); } return ret; }