/******************************************************************************* ** ** 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 rw_t4t_update_nlen ** ** Description Send UpdateBinary Command to update NLEN to peer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len) { BT_HDR *p_c_apdu; UINT8 *p; RW_TRACE_DEBUG1 ("rw_t4t_update_nlen () NLEN:%d", ndef_len); p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (!p_c_apdu) { RW_TRACE_ERROR0 ("rw_t4t_update_nlen (): Cannot allocate buffer"); return FALSE; } p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY); UINT16_TO_BE_STREAM (p, 0x0000); /* offset for NLEN */ UINT8_TO_BE_STREAM (p, T4T_FILE_LENGTH_SIZE); UINT16_TO_BE_STREAM (p, ndef_len); p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_LENGTH_SIZE; if (!rw_t4t_send_to_lower (p_c_apdu)) { return FALSE; } return TRUE; }
/******************************************************************************* ** ** Function CE_T4TTestSetCC ** ** Description Set fields in Capability Container File for testing ** ** Returns NFC_STATUS_OK if success ** *******************************************************************************/ tNFC_STATUS CE_T4TTestSetCC (UINT16 cc_len, UINT8 version, UINT16 max_le, UINT16 max_lc) { #if (CE_TEST_INCLUDED == TRUE) tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; UINT8 *p; CE_TRACE_DEBUG4 ("CE_T4TTestSetCC (): CCLen:0x%04X, Ver:0x%02X, MaxLe:0x%04X, MaxLc:0x%04X", cc_len, version, max_le, max_lc); /* CC file */ p = p_t4t->cc_file; if (cc_len != 0xFFFF) { UINT16_TO_BE_STREAM (p, cc_len); } else p += 2; if (version != 0xFF) { mapping_aid_test_enabled = TRUE; if (version == T4T_VERSION_1_0) ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x00; else if (version == T4T_VERSION_2_0) ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x01; else /* Undefined version */ ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0xFF; UINT8_TO_BE_STREAM (p, version); } else { mapping_aid_test_enabled = FALSE; p += 1; } if (max_le != 0xFFFF) { UINT16_TO_BE_STREAM (p, max_le); } else p += 2; if (max_lc != 0xFFFF) { UINT16_TO_BE_STREAM (p, max_lc); } else p += 2; return NFC_STATUS_OK; #else return NFC_STATUS_FAILED; #endif }
/******************************************************************************* ** ** Function avrc_bld_app_setting_text_rsp ** ** Description This function builds the Get Application Settings Attribute Text ** or Get Application Settings Value Text response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len, len_left; UINT8 xx; tAVRC_STS sts = AVRC_STS_NO_ERROR; UINT8 num_added = 0; if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR0("avrc_bld_app_setting_text_rsp NULL parameter"); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE - p_pkt->offset - p_pkt->len; BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xx<p_rsp->num_attr; xx++) { if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) { AVRC_TRACE_ERROR3("avrc_bld_app_setting_text_rsp out of room (str_len:%d, left:%d)", xx, p_rsp->p_attrs[xx].str_len, len_left); p_rsp->num_attr = num_added; sts = AVRC_STS_INTERNAL_ERR; break; } if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str ) { AVRC_TRACE_ERROR1("avrc_bld_app_setting_text_rsp NULL attr text[%d]", xx); continue; } UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id); UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len); (*p_count)++; num_added++; } len = p_data - p_count; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return sts; }
/****************************************************************************** ** ** Function avrc_send_continue_frag ** ** Description This function sends a continue response fragment ** ** Returns Nothing. ** ******************************************************************************/ static void avrc_send_continue_frag(UINT8 handle, UINT8 label) { tAVRC_FRAG_CB *p_fcb; BT_HDR *p_pkt_old, *p_pkt; UINT8 *p_old, *p_data; UINT8 cr = AVCT_RSP; tAVRC_RSP rej_rsp; p_fcb = &avrc_cb.fcb[handle]; p_pkt = p_fcb->p_fmsg; AVRC_TRACE_DEBUG("%s handle = %u label = %u len = %d", __func__, handle, label, p_pkt->len); if (p_pkt->len > AVRC_MAX_CTRL_DATA_LEN) { int offset_len = MAX(AVCT_MSG_OFFSET, p_pkt->offset); p_pkt_old = p_fcb->p_fmsg; p_pkt = (BT_HDR *)osi_malloc((UINT16)(AVRC_PACKET_LEN + offset_len + BT_HDR_SIZE)); if (p_pkt) { p_pkt->len = AVRC_MAX_CTRL_DATA_LEN; p_pkt->offset = AVCT_MSG_OFFSET; p_pkt->layer_specific = p_pkt_old->layer_specific; p_pkt->event = p_pkt_old->event; p_old = (UINT8 *)(p_pkt_old + 1) + p_pkt_old->offset; p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset; memcpy (p_data, p_old, AVRC_MAX_CTRL_DATA_LEN); /* use AVRC continue packet type */ p_data += AVRC_VENDOR_HDR_SIZE; p_data++; /* pdu */ *p_data++ = AVRC_PKT_CONTINUE; /* 4=pdu, pkt_type & len */ UINT16_TO_BE_STREAM(p_data, (AVRC_MAX_CTRL_DATA_LEN - AVRC_VENDOR_HDR_SIZE - 4)); /* prepare the left over for as an end fragment */ avrc_prep_end_frag (handle); } else { /* use the current GKI buffer to send Internal error status */ p_pkt = p_fcb->p_fmsg; p_fcb->p_fmsg = NULL; p_fcb->frag_enabled = FALSE; AVRC_TRACE_ERROR ("AVRC_MsgReq no buffers for fragmentation - send internal error" ); p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset; *p_data++ = AVRC_PDU_REQUEST_CONTINUATION_RSP; *p_data++ = 0; UINT16_TO_BE_STREAM(p_data, 0); p_pkt->len = 4; rej_rsp.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP; rej_rsp.status = AVRC_STS_INTERNAL_ERR; AVRC_BldResponse( handle, (tAVRC_RESPONSE *)&rej_rsp, &p_pkt); cr = AVCT_RSP; } } else { /* end fragment. clean the control block */ p_fcb->frag_enabled = FALSE; p_fcb->p_fmsg = NULL; } AVCT_MsgReq( handle, label, cr, p_pkt); }
/******************************************************************************* ** ** Function avrc_bld_get_elem_attrs_rsp ** ** Description This function builds the Get Element Attributes ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len; UINT8 xx; AVRC_TRACE_API0("avrc_bld_get_elem_attrs_rsp"); if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR0("avrc_bld_get_elem_attrs_rsp NULL parameter"); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xx<p_rsp->num_attr; xx++) { if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) { AVRC_TRACE_ERROR2("avrc_bld_get_elem_attrs_rsp invalid attr id[%d]: %d", xx, p_rsp->p_attrs[xx].attr_id); continue; } if ( !p_rsp->p_attrs[xx].name.p_str ) { p_rsp->p_attrs[xx].name.str_len = 0; } UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len); (*p_count)++; } len = p_data - p_count; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** 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_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 avrc_bld_init_rsp_buffer ** ** Description This function initializes the response buffer based on PDU ** ** Returns NULL, if no GKI buffer or failure to build the message. ** Otherwise, the GKI buffer that contains the initialized message. ** *******************************************************************************/ static BT_HDR *avrc_bld_init_rsp_buffer(tAVRC_RESPONSE *p_rsp) { UINT16 offset = AVRC_MSG_PASS_THRU_OFFSET, chnl = AVCT_DATA_CTRL, len=AVRC_META_CMD_POOL_SIZE; BT_HDR *p_pkt=NULL; UINT8 opcode = avrc_opcode_from_pdu(p_rsp->pdu); AVRC_TRACE_API3("avrc_bld_init_rsp_buffer: pdu=%x, opcode=%x/%x", p_rsp->pdu, opcode, p_rsp->rsp.opcode); if (opcode != p_rsp->rsp.opcode && p_rsp->rsp.status != AVRC_STS_NO_ERROR && avrc_is_valid_opcode(p_rsp->rsp.opcode)) { opcode = p_rsp->rsp.opcode; AVRC_TRACE_API1("opcode=%x", opcode); } switch (opcode) { case AVRC_OP_PASS_THRU: offset = AVRC_MSG_PASS_THRU_OFFSET; break; case AVRC_OP_VENDOR: offset = AVRC_MSG_VENDOR_OFFSET; if (p_rsp->pdu == AVRC_PDU_GET_ELEMENT_ATTR) len = AVRC_BROWSE_POOL_SIZE; break; } /* allocate and initialize the buffer */ p_pkt = (BT_HDR *)GKI_getbuf(len); if (p_pkt) { UINT8 *p_data, *p_start; p_pkt->layer_specific = chnl; p_pkt->event = opcode; p_pkt->offset = offset; p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_start = p_data; /* pass thru - group navigation - has a two byte op_id, so dont do it here */ if (opcode != AVRC_OP_PASS_THRU) *p_data++ = p_rsp->pdu; switch (opcode) { case AVRC_OP_VENDOR: /* reserved 0, packet_type 0 */ UINT8_TO_BE_STREAM(p_data, 0); /* continue to the next "case to add length */ /* add fixed lenth - 0 */ UINT16_TO_BE_STREAM(p_data, 0); break; } p_pkt->len = (p_data - p_start); } p_rsp->rsp.opcode = opcode; return p_pkt; }
/******************************************************************************* ** ** 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 avrc_prep_end_frag ** ** Description This function prepares an end response fragment ** ** Returns Nothing. ** ******************************************************************************/ static void avrc_prep_end_frag(UINT8 handle) { tAVRC_FRAG_CB *p_fcb; BT_HDR *p_pkt_new; UINT8 *p_data, *p_orig_data; UINT8 rsp_type; AVRC_TRACE_DEBUG ("avrc_prep_end_frag" ); p_fcb = &avrc_cb.fcb[handle]; /* The response type of the end fragment should be the same as the the PDU of "End Fragment ** Response" Errata: https://www.bluetooth.org/errata/errata_view.cfm?errata_id=4383 */ p_orig_data = ((UINT8 *)(p_fcb->p_fmsg + 1) + p_fcb->p_fmsg->offset); rsp_type = ((*p_orig_data) & AVRC_CTYPE_MASK); p_pkt_new = p_fcb->p_fmsg; p_pkt_new->len -= (AVRC_MAX_CTRL_DATA_LEN - AVRC_VENDOR_HDR_SIZE - AVRC_MIN_META_HDR_SIZE); p_pkt_new->offset += (AVRC_MAX_CTRL_DATA_LEN - AVRC_VENDOR_HDR_SIZE - AVRC_MIN_META_HDR_SIZE); p_data = (UINT8 *)(p_pkt_new + 1) + p_pkt_new->offset; *p_data++ = rsp_type; *p_data++ = (AVRC_SUB_PANEL << AVRC_SUBTYPE_SHIFT); *p_data++ = AVRC_OP_VENDOR; AVRC_CO_ID_TO_BE_STREAM(p_data, AVRC_CO_METADATA); *p_data++ = p_fcb->frag_pdu; *p_data++ = AVRC_PKT_END; /* 4=pdu, pkt_type & len */ UINT16_TO_BE_STREAM(p_data, (p_pkt_new->len - AVRC_VENDOR_HDR_SIZE - AVRC_MIN_META_HDR_SIZE)); }
/******************************************************************************* ** ** 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_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 ce_t4t_send_status ** ** Description Send status on R-APDU to peer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN ce_t4t_send_status (UINT16 status) { BT_HDR *p_r_apdu; UINT8 *p; CE_TRACE_DEBUG1 ("ce_t4t_send_status (): Status:0x%04X", status); p_r_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID); if (!p_r_apdu) { CE_TRACE_ERROR0 ("ce_t4t_send_status (): Cannot allocate buffer"); return FALSE; } p_r_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; UINT16_TO_BE_STREAM (p, status); p_r_apdu->len = T4T_RSP_STATUS_WORDS_SIZE; if (!ce_t4t_send_to_lower (p_r_apdu)) { return FALSE; } return TRUE; }
/******************************************************************************* ** ** Function mca_ccb_snd_req ** ** Description This function builds a request and sends it to the peer. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_snd_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data; BT_HDR *p_pkt; UINT8 *p, *p_start; BOOLEAN is_abort = FALSE; tMCA_DCB *p_dcb; MCA_TRACE_DEBUG ("mca_ccb_snd_req cong=%d req=%d", p_ccb->cong, p_msg->op_code); /* check for abort request */ if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (p_msg->op_code == MCA_OP_MDL_ABORT_REQ)) { p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx); /* the Abort API does not have the associated mdl_id. * Get the mdl_id in dcb to compose the request */ if (p_dcb) { p_msg->mdl_id = p_dcb->mdl_id; mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL); } mca_free_buf ((void **)&p_ccb->p_tx_req); p_ccb->status = MCA_CCB_STAT_NORM; is_abort = TRUE; } /* no pending outgoing messages or it's an abort request for a pending data channel */ if ((!p_ccb->p_tx_req) || is_abort) { p_ccb->p_tx_req = p_msg; if (!p_ccb->cong) { p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU); if (p_pkt) { p_pkt->offset = L2CAP_MIN_OFFSET; p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET; *p++ = p_msg->op_code; UINT16_TO_BE_STREAM (p, p_msg->mdl_id); if (p_msg->op_code == MCA_OP_MDL_CREATE_REQ) { *p++ = p_msg->mdep_id; *p++ = p_msg->param; } p_msg->hdr.layer_specific = TRUE; /* mark this message as sent */ p_pkt->len = p - p_start; L2CA_DataWrite (p_ccb->lcid, p_pkt); p_ccb->timer_entry.param = (TIMER_PARAM_TYPE) p_ccb; btu_start_timer(&p_ccb->timer_entry, BTU_TTYPE_MCA_CCB_RSP, p_ccb->p_rcb->reg.rsp_tout); } } /* else the L2CAP channel is congested. keep the message to be sent later */ } else { MCA_TRACE_WARNING ("dropping api req"); GKI_freebuf (p_data); } }
/****************************************************************************** ** ** Function AVRC_AddRecord ** ** Description This function is called to build an AVRCP SDP record. ** Prior to calling this function the application must ** call SDP_CreateRecord() to create an SDP record. ** ** Input Parameters: ** service_uuid: Indicates TG(UUID_SERVCLASS_AV_REM_CTRL_TARGET) ** or CT(UUID_SERVCLASS_AV_REMOTE_CONTROL) ** ** p_service_name: Pointer to a null-terminated character ** string containing the service name. ** If service name is not used set this to NULL. ** ** p_provider_name: Pointer to a null-terminated character ** string containing the provider name. ** If provider name is not used set this to NULL. ** ** categories: Supported categories. ** ** sdp_handle: SDP handle returned by SDP_CreateRecord(). ** ** Output Parameters: ** None. ** ** Returns AVRC_SUCCESS if successful. ** AVRC_NO_RESOURCES if not enough resources to build the SDP record. ** ******************************************************************************/ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provider_name, UINT16 categories, UINT32 sdp_handle) { UINT16 browse_list[1]; BOOLEAN result = TRUE; UINT8 temp[8]; UINT8 *p; UINT16 count = 1; UINT16 class_list[2]; AVRC_TRACE_API1("AVRC_AddRecord uuid: %x", service_uuid); if( service_uuid != UUID_SERVCLASS_AV_REM_CTRL_TARGET && service_uuid != UUID_SERVCLASS_AV_REMOTE_CONTROL ) return AVRC_BAD_PARAM; /* add service class id list */ class_list[0] = service_uuid; result &= SDP_AddServiceClassIdList(sdp_handle, count, class_list); /* add protocol descriptor list */ result &= SDP_AddProtocolList(sdp_handle, AVRC_NUM_PROTO_ELEMS, (tSDP_PROTOCOL_ELEM *)avrc_proto_list); /* add profile descriptor list */ #if AVRC_METADATA_INCLUDED == TRUE result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_3); #else result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_0); #endif /* add supported categories */ p = temp; UINT16_TO_BE_STREAM(p, categories); result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, (UINT32)2, (UINT8*)temp); /* add provider name */ if (p_provider_name != NULL) { result &= SDP_AddAttribute(sdp_handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE, (UINT32)(strlen(p_provider_name)+1), (UINT8 *) p_provider_name); } /* add service name */ if (p_service_name != NULL) { result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, (UINT32)(strlen(p_service_name)+1), (UINT8 *) p_service_name); } /* add browse group list */ browse_list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list); return (result ? AVRC_SUCCESS : AVRC_FAIL); }
/******************************************************************************* ** ** Function avrc_bld_init_cmd_buffer ** ** Description This function initializes the command buffer based on PDU ** ** Returns NULL, if no GKI buffer or failure to build the message. ** Otherwise, the GKI buffer that contains the initialized message. ** *******************************************************************************/ static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd) { UINT16 offset = 0, chnl = AVCT_DATA_CTRL, len=AVRC_META_CMD_POOL_SIZE; BT_HDR *p_pkt=NULL; UINT8 opcode; opcode = avrc_opcode_from_pdu(p_cmd->pdu); AVRC_TRACE_API("avrc_bld_init_cmd_buffer: pdu=%x, opcode=%x", p_cmd->pdu, opcode); switch (opcode) { case AVRC_OP_PASS_THRU: offset = AVRC_MSG_PASS_THRU_OFFSET; break; case AVRC_OP_VENDOR: offset = AVRC_MSG_VENDOR_OFFSET; break; } /* allocate and initialize the buffer */ p_pkt = (BT_HDR *)GKI_getbuf(len); if (p_pkt) { UINT8 *p_data, *p_start; p_pkt->layer_specific = chnl; p_pkt->event = opcode; p_pkt->offset = offset; p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_start = p_data; /* pass thru - group navigation - has a two byte op_id, so dont do it here */ if (opcode != AVRC_OP_PASS_THRU) *p_data++ = p_cmd->pdu; switch (opcode) { case AVRC_OP_VENDOR: /* reserved 0, packet_type 0 */ UINT8_TO_BE_STREAM(p_data, 0); /* continue to the next "case to add length */ /* add fixed lenth - 0 */ UINT16_TO_BE_STREAM(p_data, 0); break; } p_pkt->len = (p_data - p_start); } p_cmd->cmd.opcode = opcode; return p_pkt; }
/******************************************************************************* ** ** Function rw_t4t_update_file ** ** Description Send UpdateBinary Command to peer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN rw_t4t_update_file (void) { tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; BT_HDR *p_c_apdu; UINT8 *p; UINT16 length; RW_TRACE_DEBUG2 ("rw_t4t_update_file () rw_offset:%d, rw_length:%d", p_t4t->rw_offset, p_t4t->rw_length); p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (!p_c_apdu) { RW_TRACE_ERROR0 ("rw_t4t_write_file (): Cannot allocate buffer"); return FALSE; } /* try to send all of remaining data */ length = p_t4t->rw_length; /* adjust updating length if payload is bigger than max size per single command */ if (length > p_t4t->max_update_size) { length = (UINT8) (p_t4t->max_update_size); } p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY); UINT16_TO_BE_STREAM (p, p_t4t->rw_offset); UINT8_TO_BE_STREAM (p, length); memcpy (p, p_t4t->p_update_data, length); p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length; if (!rw_t4t_send_to_lower (p_c_apdu)) { return FALSE; } /* adjust offset, length and pointer for remaining data */ p_t4t->rw_offset += length; p_t4t->rw_length -= length; p_t4t->p_update_data += length; return TRUE; }
/******************************************************************************* ** ** Function NDEF_MsgAddWktCr ** ** Description This function adds Collision Resolution Record. ** ** Returns NDEF_OK if all OK ** *******************************************************************************/ tNDEF_STATUS NDEF_MsgAddWktCr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, UINT16 random_number ) { tNDEF_STATUS status; UINT8 data[2], *p; p = data; UINT16_TO_BE_STREAM (p, random_number); status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, NDEF_TNF_WKT, cr_rec_type, CR_REC_TYPE_LEN, NULL, 0, data, 2); return (status); }
/******************************************************************************* ** ** Function avrc_bld_set_abs_volume_cmd ** ** Description This function builds the Set Absolute Volume command. ** ** Returns AVRC_STS_NO_ERROR, if the command is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_set_abs_volume_cmd (tAVRC_SET_VOLUME_CMD *p_cmd, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API("avrc_bld_set_abs_volume_cmd"); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ /* add fixed lenth 1 - volume (1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume)); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function rw_t4t_read_file ** ** Description Send ReadBinary Command to peer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue) { tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; BT_HDR *p_c_apdu; UINT8 *p; RW_TRACE_DEBUG3 ("rw_t4t_read_file () offset:%d, length:%d, is_continue:%d, ", offset, length, is_continue); p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (!p_c_apdu) { RW_TRACE_ERROR0 ("rw_t4t_read_file (): Cannot allocate buffer"); return FALSE; } /* if this is the first reading */ if (is_continue == FALSE) { /* initialise starting offset and total length */ /* these will be updated when receiving response */ p_t4t->rw_offset = offset; p_t4t->rw_length = length; } /* adjust reading length if payload is bigger than max size per single command */ if (length > p_t4t->max_read_size) { length = (UINT8) (p_t4t->max_read_size); } p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); UINT8_TO_BE_STREAM (p, T4T_CMD_INS_READ_BINARY); UINT16_TO_BE_STREAM (p, offset); UINT8_TO_BE_STREAM (p, length); /* Le */ p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */ if (!rw_t4t_send_to_lower (p_c_apdu)) { return FALSE; } return TRUE; }
/******************************************************************************* ** ** Function avrc_bld_vol_change_notfn ** ** Description This function builds the register notification for volume change. ** ** Returns AVRC_STS_NO_ERROR, if the command is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_vol_change_notfn(BT_HDR * p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API("avrc_bld_vol_change"); /* get the existing length, if any, and also the num attributes */ // Set the notify value p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ /* add fixed length 5 -*/ UINT16_TO_BE_STREAM(p_data, 5); UINT8_TO_BE_STREAM(p_data,AVRC_EVT_VOLUME_CHANGE); UINT32_TO_BE_STREAM(p_data, 0); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function avrc_bld_group_navigation_rsp ** ** Description This function builds the Group Navigation ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt) { UINT8 *p_data; if (!AVRC_IS_VALID_GROUP(navi_id)) { AVRC_TRACE_ERROR1("avrc_bld_group_navigation_rsp bad navigation op id: %d", navi_id); return AVRC_STS_BAD_PARAM; } AVRC_TRACE_API0("avrc_bld_group_navigation_rsp"); p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset; UINT16_TO_BE_STREAM(p_data, navi_id); p_pkt->len = 2; return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function avrc_bld_rejected_rsp ** ** Description This function builds the General Response response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_rejected_rsp( tAVRC_RSP *p_rsp, BT_HDR *p_pkt ) { UINT8 *p_data, *p_start; AVRC_TRACE_API2("avrc_bld_rejected_rsp: status=%d, pdu:x%x", p_rsp->status, p_rsp->pdu); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; AVRC_TRACE_DEBUG1("pdu:x%x", *p_start); UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, p_rsp->status); p_pkt->len = p_data - p_start; return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function avrc_bld_get_play_status_rsp ** ** Description This function builds the Get Play Status ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API0("avrc_bld_get_play_status_rsp"); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* add fixed lenth - song len(4) + song position(4) + status(1) */ UINT16_TO_BE_STREAM(p_data, 9); UINT32_TO_BE_STREAM(p_data, p_rsp->song_len); UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos); UINT8_TO_BE_STREAM(p_data, p_rsp->play_status); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function avrc_bld_next_cmd ** ** Description This function builds the Request Continue or Abort command. ** ** Returns AVRC_STS_NO_ERROR, if the command is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_next_cmd (tAVRC_NEXT_CMD *p_cmd, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API("avrc_bld_next_cmd"); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ /* add fixed lenth 1 - pdu_id (1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function avrc_bld_get_cur_app_setting_value_rsp ** ** Description This function builds the Get Current Application Setting Value ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len; UINT8 xx; if (!p_rsp->p_vals) { AVRC_TRACE_ERROR0("avrc_bld_get_cur_app_setting_value_rsp NULL parameter"); return AVRC_STS_BAD_PARAM; } AVRC_TRACE_API0("avrc_bld_get_cur_app_setting_value_rsp"); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { /* first time initialize the attribute count */ *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xx<p_rsp->num_val; xx++) { if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val)) { (*p_count)++; UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id); UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_val); } } len = ((*p_count) << 1) + 1; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** 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 rw_t4t_select_file ** ** Description Send Select Command (by File ID) to peer ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN rw_t4t_select_file (UINT16 file_id) { BT_HDR *p_c_apdu; UINT8 *p; RW_TRACE_DEBUG1 ("rw_t4t_select_file (): File ID:0x%04X", file_id); p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (!p_c_apdu) { RW_TRACE_ERROR0 ("rw_t4t_select_file (): Cannot allocate buffer"); return FALSE; } p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT); UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_FILE_ID); /* if current version mapping is V2.0 */ if (rw_cb.tcb.t4t.version == T4T_VERSION_2_0) { UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_0CH); } else /* version 1.0 */ { UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H); } UINT8_TO_BE_STREAM (p, T4T_FILE_ID_SIZE); UINT16_TO_BE_STREAM (p, file_id); p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE; if (!rw_t4t_send_to_lower (p_c_apdu)) { return FALSE; } return TRUE; }
/******************************************************************************* ** ** Function mca_ccb_snd_rsp ** ** Description This function builds a response and sends it to ** the peer. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_snd_rsp(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { tMCA_CCB_MSG *p_msg = (tMCA_CCB_MSG *)p_data; BT_HDR *p_pkt; UINT8 *p, *p_start; BOOLEAN chk_mdl = FALSE; tMCA_DCB *p_dcb; MCA_TRACE_DEBUG ("mca_ccb_snd_rsp cong=%d req=%d", p_ccb->cong, p_msg->op_code); /* assume that API functions verified the parameters */ p_pkt = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU); if (p_pkt) { p_pkt->offset = L2CAP_MIN_OFFSET; p = p_start = (UINT8*)(p_pkt + 1) + L2CAP_MIN_OFFSET; *p++ = p_msg->op_code; *p++ = p_msg->rsp_code; UINT16_TO_BE_STREAM (p, p_msg->mdl_id); if (p_msg->op_code == MCA_OP_MDL_CREATE_RSP) { *p++ = p_msg->param; chk_mdl = TRUE; } else if (p_msg->op_code == MCA_OP_MDL_RECONNECT_RSP) chk_mdl = TRUE; if (chk_mdl && p_msg->rsp_code == MCA_RSP_SUCCESS) { p_dcb = mca_dcb_by_hdl(p_msg->dcb_idx); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask, p_ccb->p_rcb->reg.data_psm, BTM_SEC_PROTO_MCA, p_msg->dcb_idx); p_ccb->status = MCA_CCB_STAT_PENDING; /* set p_tx_req to block API_REQ/API_RSP before DL is up */ mca_free_buf ((void **)&p_ccb->p_tx_req); p_ccb->p_tx_req = p_ccb->p_rx_msg; p_ccb->p_rx_msg = NULL; p_ccb->p_tx_req->dcb_idx = p_msg->dcb_idx; } mca_free_buf ((void **)&p_ccb->p_rx_msg); p_pkt->len = p - p_start; L2CA_DataWrite (p_ccb->lcid, p_pkt); } }