/******************************************************************************* ** ** Function llcp_util_build_info_pdu ** ** Description Add DSAP, PTYPE, SSAP and sequence numbers and update local ack ** sequence ** ** Returns void ** *******************************************************************************/ void llcp_util_build_info_pdu (tLLCP_DLCB *p_dlcb, BT_HDR *p_msg) { UINT8 *p; UINT8 rcv_seq; p_msg->offset -= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE; p_msg->len += LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE; p = (UINT8 *) (p_msg + 1) + p_msg->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_I_TYPE, p_dlcb->local_sap)); /* if local_busy or rx congested then do not update receive sequence number to flow off */ if ( (p_dlcb->local_busy) ||(p_dlcb->is_rx_congested) ||(llcp_cb.overall_rx_congested) ) { rcv_seq = p_dlcb->sent_ack_seq; } else { p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq; rcv_seq = p_dlcb->sent_ack_seq; } UINT8_TO_BE_STREAM (p, LLCP_GET_SEQUENCE (p_dlcb->next_tx_seq, rcv_seq)); }
/******************************************************************************* ** ** Function llcp_sdp_check_send_snl ** ** Description Enqueue Service Name Lookup PDU into sig_xmit_q for transmitting ** ** ** Returns void ** *******************************************************************************/ void llcp_sdp_check_send_snl (void) { UINT8 *p; if (llcp_cb.sdp_cb.p_snl) { LLCP_TRACE_DEBUG0 ("SDP: llcp_sdp_check_send_snl ()"); llcp_cb.sdp_cb.p_snl->len += LLCP_PDU_HEADER_SIZE; llcp_cb.sdp_cb.p_snl->offset -= LLCP_PDU_HEADER_SIZE; p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (LLCP_SAP_SDP, LLCP_PDU_SNL_TYPE, LLCP_SAP_SDP )); GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, llcp_cb.sdp_cb.p_snl); llcp_cb.sdp_cb.p_snl = NULL; } #if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE) else { /* Notify DTA after sending out SNL with SDRES not to send SNLs in AGF PDU */ if ((llcp_cb.p_dta_cback) && (llcp_cb.dta_snl_resp)) { llcp_cb.dta_snl_resp = FALSE; (*llcp_cb.p_dta_cback) (); } } #endif }
/******************************************************************************* ** ** Function llcp_util_send_frmr ** ** Description Send FRMR PDU ** ** Returns tLLCP_STATUS ** *******************************************************************************/ tLLCP_STATUS llcp_util_send_frmr (tLLCP_DLCB *p_dlcb, UINT8 flags, UINT8 ptype, UINT8 sequence) { BT_HDR *p_msg; UINT8 *p; p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (p_msg) { p_msg->len = LLCP_PDU_FRMR_SIZE; p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_msg + 1) + p_msg->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_FRMR_TYPE, p_dlcb->local_sap)); UINT8_TO_BE_STREAM (p, (flags << 4) | ptype); UINT8_TO_BE_STREAM (p, sequence); UINT8_TO_BE_STREAM (p, (p_dlcb->next_tx_seq << 4) | p_dlcb->next_rx_seq); UINT8_TO_BE_STREAM (p, (p_dlcb->rcvd_ack_seq << 4) | p_dlcb->sent_ack_seq); GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); llcp_link_check_send_data (); return LLCP_STATUS_SUCCESS; } else { LLCP_TRACE_ERROR0 ("llcp_util_send_frmr (): Out of resource"); return LLCP_STATUS_FAIL; } }
/******************************************************************************* ** ** Function llcp_util_send_connect ** ** Description Send CONNECT PDU ** ** Returns tLLCP_STATUS ** ******************************************************************************/ tLLCP_STATUS llcp_util_send_connect (tLLCP_DLCB *p_dlcb, tLLCP_CONNECTION_PARAMS *p_params) { BT_HDR *p_msg; UINT8 *p; UINT16 miu_len = 0, rw_len = 0, sn_len = 0; if (p_params->miu != LLCP_DEFAULT_MIU) { miu_len = 4; /* TYPE, LEN, 2 bytes MIU */ } if (p_params->rw != LLCP_DEFAULT_RW) { rw_len = 3; /* TYPE, LEN, 1 byte RW */ p_params->rw &= 0x0F; /* only 4 bits */ } if ((strlen (p_params->sn)) && (p_dlcb->remote_sap == LLCP_SAP_SDP)) { sn_len = (UINT16) (2 + strlen (p_params->sn)); /* TYPE, LEN, SN */ } p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (p_msg) { p_msg->len = LLCP_PDU_HEADER_SIZE + miu_len + rw_len + sn_len; p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_msg + 1) + p_msg->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_CONNECT_TYPE, p_dlcb->local_sap)); if (miu_len) { UINT8_TO_BE_STREAM (p, LLCP_MIUX_TYPE); UINT8_TO_BE_STREAM (p, LLCP_MIUX_LEN); UINT16_TO_BE_STREAM (p, p_params->miu - LLCP_DEFAULT_MIU); } if (rw_len) { UINT8_TO_BE_STREAM (p, LLCP_RW_TYPE); UINT8_TO_BE_STREAM (p, LLCP_RW_LEN); UINT8_TO_BE_STREAM (p, p_params->rw); } if (sn_len) { UINT8_TO_BE_STREAM (p, LLCP_SN_TYPE); UINT8_TO_BE_STREAM (p, sn_len - 2); memcpy (p, p_params->sn, sn_len - 2); } GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); llcp_link_check_send_data (); return LLCP_STATUS_SUCCESS; } return LLCP_STATUS_FAIL; }
/******************************************************************************* ** ** Function llcp_util_send_ui ** ** Description Send UI PDU ** ** Returns tLLCP_STATUS ** *******************************************************************************/ tLLCP_STATUS llcp_util_send_ui (UINT8 ssap, UINT8 dsap, tLLCP_APP_CB *p_app_cb, BT_HDR *p_msg) { UINT8 *p; tLLCP_STATUS status = LLCP_STATUS_SUCCESS; p_msg->offset -= LLCP_PDU_HEADER_SIZE; p_msg->len += LLCP_PDU_HEADER_SIZE; p = (UINT8 *) (p_msg + 1) + p_msg->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (dsap, LLCP_PDU_UI_TYPE, ssap)); GKI_enqueue (&p_app_cb->ui_xmit_q, p_msg); llcp_cb.total_tx_ui_pdu++; llcp_link_check_send_data (); if ( (p_app_cb->is_ui_tx_congested) ||(p_app_cb->ui_xmit_q.count >= llcp_cb.ll_tx_congest_start) ||(llcp_cb.overall_tx_congested) ||(llcp_cb.total_tx_ui_pdu >= llcp_cb.max_num_ll_tx_buff) ) { /* set congested here so overall congestion check routine will not report event again, */ /* or notify uncongestion later */ p_app_cb->is_ui_tx_congested = TRUE; LLCP_TRACE_WARNING2 ("Logical link (SAP=0x%X) congested: ui_xmit_q.count=%d", ssap, p_app_cb->ui_xmit_q.count); status = LLCP_STATUS_CONGESTED; } return status; }
/******************************************************************************* ** ** Function llcp_util_send_cc ** ** Description Send CC PDU ** ** Returns tLLCP_STATUS ** ******************************************************************************/ tLLCP_STATUS llcp_util_send_cc (tLLCP_DLCB *p_dlcb, tLLCP_CONNECTION_PARAMS *p_params) { BT_HDR *p_msg; UINT8 *p; UINT16 miu_len = 0, rw_len = 0; if (p_params->miu != LLCP_DEFAULT_MIU) { miu_len = 4; } if (p_params->rw != LLCP_DEFAULT_RW) { rw_len = 3; p_params->rw &= 0x0F; } p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (p_msg) { p_msg->len = LLCP_PDU_HEADER_SIZE + miu_len + rw_len; p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_msg + 1) + p_msg->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, LLCP_PDU_CC_TYPE, p_dlcb->local_sap)); if (miu_len) { UINT8_TO_BE_STREAM (p, LLCP_MIUX_TYPE); UINT8_TO_BE_STREAM (p, LLCP_MIUX_LEN); UINT16_TO_BE_STREAM (p, p_params->miu - LLCP_DEFAULT_MIU); } if (rw_len) { UINT8_TO_BE_STREAM (p, LLCP_RW_TYPE); UINT8_TO_BE_STREAM (p, LLCP_RW_LEN); UINT8_TO_BE_STREAM (p, p_params->rw); } GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); llcp_link_check_send_data (); return LLCP_STATUS_SUCCESS; } return LLCP_STATUS_FAIL; }
/******************************************************************************* ** ** Function llcp_sdp_check_send_snl ** ** Description Enqueue Service Name Lookup PDU into sig_xmit_q for transmitting ** ** ** Returns void ** *******************************************************************************/ void llcp_sdp_check_send_snl (void) { UINT8 *p; if (llcp_cb.sdp_cb.p_snl) { LLCP_TRACE_DEBUG0 ("SDP: llcp_sdp_check_send_snl ()"); llcp_cb.sdp_cb.p_snl->len += LLCP_PDU_HEADER_SIZE; llcp_cb.sdp_cb.p_snl->offset -= LLCP_PDU_HEADER_SIZE; p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (LLCP_SAP_SDP, LLCP_PDU_SNL_TYPE, LLCP_SAP_SDP )); GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, llcp_cb.sdp_cb.p_snl); llcp_cb.sdp_cb.p_snl = NULL; } }
/******************************************************************************* ** ** Function llcp_util_send_disc ** ** Description Send DISC PDU ** ** Returns void ** *******************************************************************************/ void llcp_util_send_disc (UINT8 dsap, UINT8 ssap) { BT_HDR *p_msg; UINT8 *p; p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (p_msg) { p_msg->len = LLCP_PDU_DISC_SIZE; p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_msg + 1) + p_msg->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (dsap, LLCP_PDU_DISC_TYPE, ssap)); GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); llcp_link_check_send_data (); } }
/******************************************************************************* ** ** Function llcp_util_send_rr_rnr ** ** Description Send RR or RNR PDU ** ** Returns void ** *******************************************************************************/ void llcp_util_send_rr_rnr (tLLCP_DLCB *p_dlcb) { BT_HDR *p_msg; UINT8 *p; UINT8 pdu_type; UINT8 pdu_size; UINT8 rcv_seq; /* if no indication of change in local busy or rx congestion */ if ((p_dlcb->flags & LLCP_DATA_LINK_FLAG_PENDING_RR_RNR) == 0) { /* if all ack is sent */ if (p_dlcb->sent_ack_seq == p_dlcb->next_rx_seq) { /* we don't need to send RR/RNR */ return; } else { /* if rx flow off because of local busy or congestion */ if ( (p_dlcb->local_busy) ||(p_dlcb->is_rx_congested) ||(llcp_cb.overall_rx_congested) ) { /* don't send RR/RNR */ return; } } } if ( (p_dlcb->local_busy) ||(p_dlcb->is_rx_congested) ||(llcp_cb.overall_rx_congested) ) { LLCP_TRACE_DEBUG3 ("llcp_util_send_rr_rnr (): local_busy=%d,is_rx_congested=%d,overall_rx_congested=%d", p_dlcb->local_busy, p_dlcb->is_rx_congested, llcp_cb.overall_rx_congested); /* if local_busy or rx congested then do not update receive sequence number to flow off */ pdu_type = LLCP_PDU_RNR_TYPE; pdu_size = LLCP_PDU_RNR_SIZE; rcv_seq = p_dlcb->sent_ack_seq; } else { pdu_type = LLCP_PDU_RR_TYPE; pdu_size = LLCP_PDU_RR_SIZE; p_dlcb->sent_ack_seq = p_dlcb->next_rx_seq; rcv_seq = p_dlcb->sent_ack_seq; } p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (p_msg) { p_dlcb->flags &= ~LLCP_DATA_LINK_FLAG_PENDING_RR_RNR; p_msg->len = pdu_size; p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_msg + 1) + p_msg->offset; UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (p_dlcb->remote_sap, pdu_type, p_dlcb->local_sap)); UINT8_TO_BE_STREAM (p, rcv_seq); #if (BT_TRACE_VERBOSE == TRUE) LLCP_TRACE_DEBUG5 ("LLCP TX - N(S,R):(NA,%d) V(S,SA,R,RA):(%d,%d,%d,%d)", p_dlcb->next_rx_seq, p_dlcb->next_tx_seq, p_dlcb->rcvd_ack_seq, p_dlcb->next_rx_seq, p_dlcb->sent_ack_seq); #endif GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); llcp_link_check_send_data (); } else { LLCP_TRACE_ERROR0 ("llcp_util_send_rr_rnr (): Out of resource"); } }