/******************************************************************************* ** ** 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_channel_congestion ** ** Description This function is called to process the congestion callback ** from lcb ** ** Returns void ** *******************************************************************************/ static void gatt_channel_congestion(tGATT_TCB *p_tcb, BOOLEAN congested) { UINT8 i = 0; tGATT_REG *p_reg=NULL; UINT16 conn_id; /* if uncongested, check to see if there is any more pending data */ if (p_tcb != NULL && congested == FALSE) { gatt_cl_send_next_cmd_inq(p_tcb); } /* 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_reg->app_cb.p_congestion_cb) { conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_congestion_cb)(conn_id, congested); } } } }
/******************************************************************************* ** ** Function gatt_process_notification ** ** Description This function is called to handle the handle value indication ** or handle value notification. ** ** ** Returns void ** *******************************************************************************/ void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { tGATT_VALUE value = {0}; tGATT_REG *p_reg; UINT16 conn_id; tGATT_STATUS encrypt_status; UINT8 *p = p_data, i, event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION; GATT_TRACE_DEBUG("gatt_process_notification "); if (len < GATT_NOTIFICATION_MIN_LEN) { GATT_TRACE_ERROR("illegal notification PDU length, discard"); return; } STREAM_TO_UINT16 (value.handle, p); value.len = len - 2; memcpy (value.value, p, value.len); if (!GATT_HANDLE_IS_VALID(value.handle)) { /* illegal handle, send ack now */ if (op_code == GATT_HANDLE_VALUE_IND) { attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL); } return; } if (event == GATTC_OPTYPE_INDICATION) { if (p_tcb->ind_count) { /* this is an error case that receiving an indication but we still has an indication not being acked yet. For now, just log the error reset the counter. Later we need to disconnect the link unconditionally. */ GATT_TRACE_ERROR("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count); } p_tcb->ind_count = 0; } /* should notify all registered client with the handle value notificaion/indication Note: need to do the indication count and start timer first then do callback */ for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) { if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION)) { p_tcb->ind_count++; } } if (event == GATTC_OPTYPE_INDICATION) { /* start a timer for app confirmation */ if (p_tcb->ind_count > 0) { gatt_start_ind_ack_timer(p_tcb); } else { /* no app to indicate, or invalid handle */ attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL); } } encrypt_status = gatt_get_link_encrypt_status(p_tcb); for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) { if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) { conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value); } } }