/******************************************************************************* ** ** 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 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 NDEF_MsgAddWktErr ** ** Description This function adds Error Record. ** ** Returns NDEF_OK if all OK ** *******************************************************************************/ tNDEF_STATUS NDEF_MsgAddWktErr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, UINT8 error_reason, UINT32 error_data ) { tNDEF_STATUS status; UINT8 payload[5], *p; UINT32 payload_len; p = payload; UINT8_TO_BE_STREAM (p, error_reason); if (error_reason == 0x02) { UINT32_TO_BE_STREAM (p, error_data); payload_len = 5; } else { UINT8_TO_BE_STREAM (p, error_data); payload_len = 2; } status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, NDEF_TNF_WKT, err_rec_type, ERR_REC_TYPE_LEN, NULL, 0, payload, payload_len); return (status); }
/******************************************************************************* ** ** 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 rw_t1t_send_dyn_cmd ** ** Description This function composes a Type 1 Tag command for dynamic memory ** and send through NCI to NFCC. ** ** Returns NFC_STATUS_OK if the command is successfuly sent to NCI ** otherwise, error status ** *******************************************************************************/ tNFC_STATUS rw_t1t_send_dyn_cmd (UINT8 opcode, UINT8 add, UINT8 *p_dat) { tNFC_STATUS status = NFC_STATUS_FAILED; tRW_T1T_CB *p_t1t = &rw_cb.tcb.t1t; const tT1T_CMD_RSP_INFO *p_cmd_rsp_info = t1t_cmd_to_rsp_info (opcode); BT_HDR *p_data; UINT8 *p; if (p_cmd_rsp_info) { /* a valid opcode for RW */ p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (p_data) { p_t1t->p_cmd_rsp_info = (tT1T_CMD_RSP_INFO *) p_cmd_rsp_info; p_t1t->addr = add; p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_data + 1) + p_data->offset; UINT8_TO_BE_STREAM (p, opcode); UINT8_TO_BE_STREAM (p, add); if (p_dat) { ARRAY_TO_STREAM (p, p_dat, 8); } else { memset (p, 0, 8); p += 8; } ARRAY_TO_STREAM (p, p_t1t->mem, T1T_CMD_UID_LEN); p_data->len = p_cmd_rsp_info->cmd_len; /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */ rw_cb.cur_retry = 0; memcpy (p_t1t->p_cur_cmd_buf, p_data, sizeof (BT_HDR) + p_data->offset + p_data->len); #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) /* Update stats */ rw_main_update_tx_stats (p_data->len, FALSE); #endif /* RW_STATS_INCLUDED */ RW_TRACE_EVENT2 ("RW SENT [%s]:0x%x CMD", t1t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode); if ((status = NFC_SendData (NFC_RF_CONN_ID, p_data)) == NFC_STATUS_OK) { nfc_start_quick_timer (&p_t1t->timer, NFC_TTYPE_RW_T1T_RESPONSE, (RW_T1T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); } } else { status = NFC_STATUS_NO_BUFFERS; } } return status; }
/******************************************************************************* ** ** Function llcp_sdp_add_sdres ** ** Description Add Service Discovery Response into SNL PDU ** ** ** Returns void ** *******************************************************************************/ static void llcp_sdp_add_sdres (UINT8 tid, UINT8 sap) { UINT8 *p; p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset + llcp_cb.sdp_cb.p_snl->len; UINT8_TO_BE_STREAM (p, LLCP_SDRES_TYPE); UINT8_TO_BE_STREAM (p, LLCP_SDRES_LEN); UINT8_TO_BE_STREAM (p, tid); UINT8_TO_BE_STREAM (p, sap); llcp_cb.sdp_cb.p_snl->len += 2 + LLCP_SDRES_LEN; /* type and length */ }
/******************************************************************************* ** ** 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 llcp_sdp_add_sdreq ** ** Description Add Service Discovery Request into SNL PDU ** ** ** Returns void ** *******************************************************************************/ static void llcp_sdp_add_sdreq (UINT8 tid, char *p_name) { UINT8 *p; UINT16 name_len = (UINT16) strlen (p_name); p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset + llcp_cb.sdp_cb.p_snl->len; UINT8_TO_BE_STREAM (p, LLCP_SDREQ_TYPE); UINT8_TO_BE_STREAM (p, (1 + name_len)); UINT8_TO_BE_STREAM (p, tid); ARRAY_TO_BE_STREAM (p, p_name, name_len); llcp_cb.sdp_cb.p_snl->len += LLCP_SDREQ_MIN_LEN + name_len; }
/******************************************************************************* ** ** 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 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 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_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 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_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_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_t2t_read ** ** Description This function issues Type 2 Tag READ command for the ** specified block. If the specified block is in different ** sector then it first sends command to move to new sector ** and after the tag moves to new sector it issues the read ** command for the block. ** ** Returns tNFC_STATUS ** *******************************************************************************/ tNFC_STATUS rw_t2t_read (UINT16 block) { tNFC_STATUS status; UINT8 *p; tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; UINT8 sector_byte2[1]; UINT8 read_cmd[1]; read_cmd[0] = block % T2T_BLOCKS_PER_SECTOR; if (p_t2t->sector != block/T2T_BLOCKS_PER_SECTOR) { sector_byte2[0] = 0xFF; /* First Move to new sector before sending Read command */ if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL,sector_byte2)) == NFC_STATUS_OK) { /* Prepare command that needs to be sent after sector change op is completed */ p_t2t->select_sector = (UINT8) (block/T2T_BLOCKS_PER_SECTOR); p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset; UINT8_TO_BE_STREAM (p, T2T_CMD_READ); UINT8_TO_BE_STREAM (p, read_cmd[0]); p_t2t->p_sec_cmd_buf->len = 2; p_t2t->block_read = block; /* Backup the current substate to move back to this substate after changing sector */ p_t2t->prev_substate = p_t2t->substate; p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT; return NFC_STATUS_OK; } return NFC_STATUS_FAILED; } /* Send Read command as sector change is not needed */ if ((status = rw_t2t_send_cmd (T2T_CMD_READ, (UINT8 *) read_cmd)) == NFC_STATUS_OK) { p_t2t->block_read = block; RW_TRACE_EVENT1 ("rw_t2t_read Sent Command for Block: %u", block); } return status; }
/******************************************************************************* ** ** Function ce_t4t_set_version_in_cc ** ** Description update version in CC file ** If reader selects NDEF Tag Application with V1.0 AID then ** set V1.0 into CC file. ** If reader selects NDEF Tag Application with V2.0 AID then ** set V2.0 into CC file. ** ** Returns None ** *******************************************************************************/ static void ce_t4t_set_version_in_cc (UINT8 version) { tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; UINT8 *p; CE_TRACE_DEBUG1 ("ce_t4t_set_version_in_cc (): version = 0x%02X", version); p = p_t4t->cc_file + T4T_VERSION_OFFSET_IN_CC; UINT8_TO_BE_STREAM (p, version); }
/******************************************************************************* ** ** Function rw_t2t_sector_change ** ** Description This function issues Type 2 Tag SECTOR-SELECT command ** packet 1. ** ** Returns tNFC_STATUS ** *******************************************************************************/ tNFC_STATUS rw_t2t_sector_change (UINT8 sector) { tNFC_STATUS status; BT_HDR *p_data; UINT8 *p; tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; if ((p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) { RW_TRACE_ERROR0 ("rw_t2t_sector_change - No buffer"); return (NFC_STATUS_NO_BUFFERS); } p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_data + 1) + p_data->offset; UINT8_TO_BE_STREAM (p, sector); UINT8_TO_BE_STREAM (p, 0x00); UINT8_TO_BE_STREAM (p, 0x00); UINT8_TO_BE_STREAM (p, 0x00); p_data->len = 4; if ((status = NFC_SendData (NFC_RF_CONN_ID , p_data)) == NFC_STATUS_OK) { /* Passive rsp command and suppose not to get response to this command */ p_t2t->p_cmd_rsp_info = NULL; p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR; RW_TRACE_EVENT0 ("rw_t2t_sector_change Sent Second Command"); nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE, (RW_T2T_SEC_SEL_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); } else { RW_TRACE_ERROR1 ("rw_t2t_sector_change Send failed at rw_t2t_send_cmd, error: %u", status); } return status; }
/******************************************************************************* ** ** 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_select_application ** ** Description Select Application ** ** NDEF Tag Application Select - C-APDU ** ** CLA INS P1 P2 Lc Data(AID) Le ** V1.0: 00 A4 04 00 07 D2760000850100 - ** V2.0: 00 A4 04 00 07 D2760000850101 00 ** ** Returns TRUE if success ** *******************************************************************************/ static BOOLEAN rw_t4t_select_application (UINT8 version) { BT_HDR *p_c_apdu; UINT8 *p; RW_TRACE_DEBUG1 ("rw_t4t_select_application () version:0x%X", version); p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); if (!p_c_apdu) { RW_TRACE_ERROR0 ("rw_t4t_select_application (): 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_NAME); UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H); if (version == T4T_VERSION_1_0) /* this is for V1.0 */ { UINT8_TO_BE_STREAM (p, T4T_V10_NDEF_TAG_AID_LEN); memcpy (p, t4t_v10_ndef_tag_aid, T4T_V10_NDEF_TAG_AID_LEN); p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V10_NDEF_TAG_AID_LEN; } else if (version == T4T_VERSION_2_0) /* this is for V2.0 */ { UINT8_TO_BE_STREAM (p, T4T_V20_NDEF_TAG_AID_LEN); memcpy (p, t4t_v20_ndef_tag_aid, T4T_V20_NDEF_TAG_AID_LEN); p += T4T_V20_NDEF_TAG_AID_LEN; UINT8_TO_BE_STREAM (p, 0x00); /* Le set to 0x00 */ p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V20_NDEF_TAG_AID_LEN + 1; } else { return FALSE; } if (!rw_t4t_send_to_lower (p_c_apdu)) { return FALSE; } return TRUE; }
/******************************************************************************* ** ** 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 nfa_p2p_set_config ** ** Description Set General bytes and WT parameters for LLCP ** ** ** Returns void ** *******************************************************************************/ void nfa_p2p_set_config (tNFA_DM_DISC_TECH_PROTO_MASK disc_mask) { UINT8 wt, gen_bytes_len = LLCP_MAX_GEN_BYTES; UINT8 params[LLCP_MAX_GEN_BYTES + 5], *p, length; P2P_TRACE_DEBUG0 ("nfa_p2p_set_config ()"); LLCP_GetDiscoveryConfig (&wt, params + 2, &gen_bytes_len); if (nfa_dm_is_p2p_paused ()) { gen_bytes_len = 0; } if (disc_mask & ( NFA_DM_DISC_MASK_PA_NFC_DEP |NFA_DM_DISC_MASK_PF_NFC_DEP |NFA_DM_DISC_MASK_PAA_NFC_DEP |NFA_DM_DISC_MASK_PFA_NFC_DEP) ) { p = params; UINT8_TO_BE_STREAM (p, NFC_PMID_ATR_REQ_GEN_BYTES); UINT8_TO_BE_STREAM (p, gen_bytes_len); p += gen_bytes_len; length = gen_bytes_len + 2; nfa_dm_check_set_config (length, params, FALSE); } if (disc_mask & ( NFA_DM_DISC_MASK_LA_NFC_DEP |NFA_DM_DISC_MASK_LF_NFC_DEP |NFA_DM_DISC_MASK_LAA_NFC_DEP |NFA_DM_DISC_MASK_LFA_NFC_DEP) ) { p = params; UINT8_TO_BE_STREAM (p, NFC_PMID_ATR_RES_GEN_BYTES); UINT8_TO_BE_STREAM (p, gen_bytes_len); p += gen_bytes_len; length = gen_bytes_len + 2; UINT8_TO_BE_STREAM (p, NFC_PMID_WT); UINT8_TO_BE_STREAM (p, NCI_PARAM_LEN_WT); UINT8_TO_BE_STREAM (p, wt); length += 3; nfa_dm_check_set_config (length, params, FALSE); } }
/******************************************************************************* ** ** 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_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_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_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 rw_t2t_write ** ** Description This function issues Type 2 Tag WRITE command for the ** specified block. If the specified block is in different ** sector then it first sends command to move to new sector ** and after the tag moves to new sector it issues the write ** command for the block. ** ** Returns tNFC_STATUS ** *******************************************************************************/ tNFC_STATUS rw_t2t_write (UINT16 block, UINT8 *p_write_data) { tNFC_STATUS status; UINT8 *p; tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; UINT8 write_cmd[T2T_WRITE_DATA_LEN + 1]; UINT8 sector_byte2[1]; p_t2t->block_written = block; write_cmd[0] = (UINT8) (block%T2T_BLOCKS_PER_SECTOR); memcpy (&write_cmd[1], p_write_data, T2T_WRITE_DATA_LEN); if (p_t2t->sector != block/T2T_BLOCKS_PER_SECTOR) { sector_byte2[0] = 0xFF; /* First Move to new sector before sending Write command */ if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL, sector_byte2)) == NFC_STATUS_OK) { /* Prepare command that needs to be sent after sector change op is completed */ p_t2t->select_sector = (UINT8) (block/T2T_BLOCKS_PER_SECTOR); p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset; UINT8_TO_BE_STREAM (p, T2T_CMD_WRITE); memcpy (p, write_cmd, T2T_WRITE_DATA_LEN + 1); p_t2t->p_sec_cmd_buf->len = 2 + T2T_WRITE_DATA_LEN; p_t2t->block_written = block; /* Backup the current substate to move back to this substate after changing sector */ p_t2t->prev_substate = p_t2t->substate; p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT; return NFC_STATUS_OK; } return NFC_STATUS_FAILED; } /* Send Write command as sector change is not needed */ if ((status = rw_t2t_send_cmd (T2T_CMD_WRITE, write_cmd)) == NFC_STATUS_OK) { RW_TRACE_EVENT1 ("rw_t2t_write Sent Command for Block: %u", block); } return status; }
/******************************************************************************* ** ** Function llcp_util_send_dm ** ** Description Send DM PDU ** ** Returns void ** *******************************************************************************/ void llcp_util_send_dm (UINT8 dsap, UINT8 ssap, UINT8 reason) { BT_HDR *p_msg; UINT8 *p; p_msg = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (p_msg) { p_msg->len = LLCP_PDU_DM_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_DM_TYPE, ssap)); UINT8_TO_BE_STREAM (p, reason); GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, p_msg); llcp_link_check_send_data (); } }
/******************************************************************************* ** ** Function avrc_bld_list_app_settings_attr_rsp ** ** Description This function builds the List Application Settings Attribute ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_num; UINT16 len = 0; UINT8 xx; AVRC_TRACE_API0("avrc_bld_list_app_settings_attr_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_num = p_data; if (len == 0) { /* first time initialize the attribute count */ *p_num = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xx<p_rsp->num_attr; xx++) { if(AVRC_IsValidPlayerAttr(p_rsp->attrs[xx])) { (*p_num)++; UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]); } } len = *p_num + 1; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function bta_hl_compose_supported_feature_list ** ** Description This function is called to compose a data sequence from ** the supported feature element list struct pointer ** ** Returns the length of the data sequence ** *******************************************************************************/ int bta_hl_compose_supported_feature_list( UINT8 *p, UINT16 num_elem, const tBTA_HL_SUP_FEATURE_ELEM *p_elem_list) { UINT16 xx, str_len, seq_len; UINT8 *p_head = p; for (xx = 0; xx < num_elem; xx++, p_elem_list++) { UINT8_TO_BE_STREAM (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); seq_len=7; str_len=0; if (p_elem_list->p_mdep_desp) { str_len = strlen(p_elem_list->p_mdep_desp)+1; seq_len += str_len+2; /* todo add a # symbol for 2 */ } *p++ = (UINT8) seq_len; UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE); UINT8_TO_BE_STREAM (p, p_elem_list->mdep_id); UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); UINT16_TO_BE_STREAM (p, p_elem_list->data_type); UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE); UINT8_TO_BE_STREAM (p, p_elem_list->mdep_role); if (str_len) { UINT8_TO_BE_STREAM (p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); UINT8_TO_BE_STREAM (p, str_len); ARRAY_TO_BE_STREAM(p, p_elem_list->p_mdep_desp, str_len); } } return(p - p_head); }