/******************************************************************************* ** ** Function rw_t2t_select ** ** Description This function selects type 2 tag. ** ** Returns Tag selection status ** *******************************************************************************/ tNFC_STATUS rw_t2t_select (void) { tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; p_t2t->state = RW_T2T_STATE_IDLE; p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED; /* Alloc cmd buf for retransmissions */ if (p_t2t->p_cur_cmd_buf == NULL) { if ((p_t2t->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) { RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer for retransmission"); return (NFC_STATUS_FAILED); } } /* Alloc cmd buf for holding a command untill sector changes */ if (p_t2t->p_sec_cmd_buf == NULL) { if ((p_t2t->p_sec_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) { RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer used during sector change"); return (NFC_STATUS_FAILED); } } NFC_SetStaticRfCback (rw_t2t_conn_cback); rw_t2t_handle_op_complete (); p_t2t->check_tag_halt = FALSE; return NFC_STATUS_OK; }
/******************************************************************************* ** ** Function rw_t1t_select ** ** Description This function will set the callback function to ** receive data from lower layers and also send rid command ** ** Returns none ** *******************************************************************************/ tNFC_STATUS rw_t1t_select (UINT8 hr[T1T_HR_LEN], UINT8 uid[T1T_CMD_UID_LEN]) { tNFC_STATUS status = NFC_STATUS_FAILED; tRW_T1T_CB *p_t1t = &rw_cb.tcb.t1t; p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED; /* Alloc cmd buf for retransmissions */ if (p_t1t->p_cur_cmd_buf == NULL) { if ((p_t1t->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) { RW_TRACE_ERROR0 ("rw_t1t_select: unable to allocate buffer for retransmission"); return status; } } memcpy (p_t1t->hr, hr, T1T_HR_LEN); memcpy (p_t1t->mem, uid, T1T_CMD_UID_LEN); NFC_SetStaticRfCback (rw_t1t_conn_cback); p_t1t->state = RW_T1T_STATE_IDLE; return NFC_STATUS_OK; }
/******************************************************************************* ** ** Function ce_select_t4t ** ** Description Select Type 4 Tag ** ** Returns NFC_STATUS_OK if success ** *******************************************************************************/ tNFC_STATUS ce_select_t4t (void) { tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; CE_TRACE_DEBUG0 ("ce_select_t4t ()"); nfc_stop_quick_timer (&p_t4t->timer); /* clear other than read-only flag */ p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY; NFC_SetStaticRfCback (ce_t4t_data_cback); return NFC_STATUS_OK; }
/******************************************************************************* ** ** Function nfa_rw_sys_disable ** ** Description Clean up rw sub-system ** ** ** Returns void ** *******************************************************************************/ void nfa_rw_sys_disable (void) { /* Return to idle */ NFC_SetStaticRfCback (NULL); /* Stop presence check timer (if started) */ nfa_rw_stop_presence_check_timer (); /* Free scratch buffer if any */ nfa_rw_free_ndef_rx_buf (); /* Free pending command if any */ if (nfa_rw_cb.p_pending_msg) { GKI_freebuf (nfa_rw_cb.p_pending_msg); nfa_rw_cb.p_pending_msg = NULL; } nfa_sys_deregister (NFA_ID_RW); }
/******************************************************************************* ** ** Function rw_t4t_select ** ** Description Initialise T4T ** ** Returns NFC_STATUS_OK if success ** *******************************************************************************/ tNFC_STATUS rw_t4t_select (void) { tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; RW_TRACE_DEBUG0 ("rw_t4t_select ()"); NFC_SetStaticRfCback (rw_t4t_data_cback); p_t4t->state = RW_T4T_STATE_IDLE; p_t4t->version = T4T_MY_VERSION; /* set it min of max R-APDU data size before reading CC file */ p_t4t->cc_file.max_le = T4T_MIN_MLE; /* These will be udated during NDEF detection */ p_t4t->max_read_size = T4T_MAX_LENGTH_LE; p_t4t->max_update_size = T4T_MAX_LENGTH_LC; return NFC_STATUS_OK; }
/******************************************************************************* ** ** Function CE_SetActivatedTagType ** ** Description This function selects the tag type for CE mode. ** ** Returns tNFC_STATUS ** *******************************************************************************/ tNFC_STATUS CE_SetActivatedTagType (tNFC_ACTIVATE_DEVT *p_activate_params, UINT16 t3t_system_code, tCE_CBACK *p_cback) { tNFC_STATUS status = NFC_STATUS_FAILED; tNFC_PROTOCOL protocol = p_activate_params->protocol; CE_TRACE_API1 ("CE_SetActivatedTagType protocol:%d", protocol); switch (protocol) { case NFC_PROTOCOL_T1T: case NFC_PROTOCOL_T2T: return NFC_STATUS_FAILED; case NFC_PROTOCOL_T3T: /* Type3Tag - NFC-F */ /* store callback function before NFC_SetStaticRfCback () */ ce_cb.p_cback = p_cback; status = ce_select_t3t (t3t_system_code, p_activate_params->rf_tech_param.param.lf.nfcid2); break; case NFC_PROTOCOL_ISO_DEP: /* ISODEP/4A,4B- NFC-A or NFC-B */ /* store callback function before NFC_SetStaticRfCback () */ ce_cb.p_cback = p_cback; status = ce_select_t4t (); break; default: CE_TRACE_ERROR0 ("CE_SetActivatedTagType Invalid protocol"); return NFC_STATUS_FAILED; } if (status != NFC_STATUS_OK) { NFC_SetStaticRfCback (NULL); ce_cb.p_cback = NULL; } return status; }
/******************************************************************************* ** ** Function ce_t4t_data_cback ** ** Description This callback function receives the data from NFCC. ** ** Returns none ** *******************************************************************************/ static void ce_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) { BT_HDR *p_c_apdu; UINT8 *p_cmd; UINT8 cla, instruct, select_type = 0, length; UINT16 offset, max_file_size; tCE_DATA ce_data; if (event == NFC_DEACTIVATE_CEVT) { NFC_SetStaticRfCback (NULL); return; } if (event != NFC_DATA_CEVT) { return; } p_c_apdu = (BT_HDR *) p_data->data.p_data; #if (BT_TRACE_PROTOCOL == TRUE) DispCET4Tags (p_c_apdu, TRUE); #endif CE_TRACE_DEBUG1 ("ce_t4t_data_cback (): conn_id = 0x%02X", conn_id); p_cmd = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; /* Class Byte */ BE_STREAM_TO_UINT8 (cla, p_cmd); /* Don't check class if registered AID has been selected */ if ( (cla != T4T_CMD_CLASS) &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) == 0) &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) == 0) ) { GKI_freebuf (p_c_apdu); ce_t4t_send_status (T4T_RSP_CLASS_NOT_SUPPORTED); return; } /* Instruction Byte */ BE_STREAM_TO_UINT8 (instruct, p_cmd); if ((cla == T4T_CMD_CLASS) && (instruct == T4T_CMD_INS_SELECT)) { /* P1 Byte */ BE_STREAM_TO_UINT8 (select_type, p_cmd); if (select_type == T4T_CMD_P1_SELECT_BY_NAME) { ce_t4t_process_select_app_cmd (p_cmd, p_c_apdu); return; } } /* if registered AID is selected */ if (ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) { CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to registered AID"); /* forward raw frame to upper layer */ if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID) { ce_data.raw_frame.status = p_data->data.status; ce_data.raw_frame.p_data = p_c_apdu; ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx; p_c_apdu = NULL; (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); } else { GKI_freebuf (p_c_apdu); ce_t4t_send_status (T4T_RSP_NOT_FOUND); } } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) { CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to wildcard AID handler"); /* forward raw frame to upper layer */ ce_data.raw_frame.status = p_data->data.status; ce_data.raw_frame.p_data = p_c_apdu; ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE; p_c_apdu = NULL; (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED) { if (instruct == T4T_CMD_INS_SELECT) { /* P1 Byte is already parsed */ if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID) { ce_t4t_process_select_file_cmd (p_cmd); } else { CE_TRACE_ERROR1 ("CET4T: Bad P1 byte (0x%02X)", select_type); ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); } } else if (instruct == T4T_CMD_INS_READ_BINARY) { if ( (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) ||(ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) ) { if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) { max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE; } else { max_file_size = ce_cb.mem.t4t.max_file_size; } BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */ BE_STREAM_TO_UINT8 (length, p_cmd); /* Le */ /* check if valid parameters */ if (length <= CE_T4T_MAX_LE) { /* CE allows to read more than current file size but not max file size */ if (length + offset > max_file_size) { if (offset < max_file_size) { length = (UINT8) (max_file_size - offset); CE_TRACE_DEBUG2 ("CET4T: length is reduced to %d by max_file_size (%d)", length, max_file_size); } else { CE_TRACE_ERROR2 ("CET4T: offset (%d) must be less than max_file_size (%d)", offset, max_file_size); length = 0; } } } else { CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLe (%d)", length, CE_T4T_MAX_LE); length = 0; } if (length > 0) ce_t4t_read_binary (offset, length); else ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); } else { CE_TRACE_ERROR0 ("CET4T: File has not been selected"); ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); } } else if (instruct == T4T_CMD_INS_UPDATE_BINARY) { if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY) { CE_TRACE_ERROR0 ("CET4T: No access right"); ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); } else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) { BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */ BE_STREAM_TO_UINT8 (length, p_cmd); /* Lc */ /* check if valid parameters */ if (length <= CE_T4T_MAX_LC) { if (length + offset > ce_cb.mem.t4t.max_file_size) { CE_TRACE_ERROR3 ("CET4T: length (%d) + offset (%d) must be less than max_file_size (%d)", length, offset, ce_cb.mem.t4t.max_file_size); length = 0; } } else { CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLc (%d)", length, CE_T4T_MAX_LC); length = 0; } if (length > 0) ce_t4t_update_binary (offset, length, p_cmd); else ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); } else { CE_TRACE_ERROR0 ("CET4T: NDEF File has not been selected"); ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); } } else { CE_TRACE_ERROR1 ("CET4T: Unsupported Instruction byte (0x%02X)", instruct); ce_t4t_send_status (T4T_RSP_INSTR_NOT_SUPPORTED); } } else { CE_TRACE_ERROR0 ("CET4T: Application has not been selected"); ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); } if (p_c_apdu) GKI_freebuf (p_c_apdu); }
/******************************************************************************* ** ** Function rw_t2t_conn_cback ** ** Description This callback function receives events/data from NFCC. ** ** Returns none ** *******************************************************************************/ void rw_t2t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) { tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; tRW_READ_DATA evt_data; RW_TRACE_DEBUG2 ("rw_t2t_conn_cback: conn_id=%i, evt=%i", conn_id, event); /* Only handle static conn_id */ if (conn_id != NFC_RF_CONN_ID) { return; } switch (event) { case NFC_CONN_CREATE_CEVT: case NFC_CONN_CLOSE_CEVT: break; case NFC_DEACTIVATE_CEVT: #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) /* Display stats */ rw_main_log_stats (); #endif /* Stop t2t timer (if started) */ nfc_stop_quick_timer (&p_t2t->t2_timer); /* Free cmd buf for retransmissions */ if (p_t2t->p_cur_cmd_buf) { GKI_freebuf (p_t2t->p_cur_cmd_buf); p_t2t->p_cur_cmd_buf = NULL; } /* Free cmd buf used to hold command before sector change */ if (p_t2t->p_sec_cmd_buf) { GKI_freebuf (p_t2t->p_sec_cmd_buf); p_t2t->p_sec_cmd_buf = NULL; } p_t2t->state = RW_T2T_STATE_NOT_ACTIVATED; NFC_SetStaticRfCback (NULL); break; case NFC_DATA_CEVT: if ( (p_data != NULL) &&( (p_data->data.status == NFC_STATUS_OK) ||(p_data->data.status == NFC_STATUS_CONTINUE) ) ) { rw_t2t_proc_data (conn_id, &(p_data->data)); break; } /* Data event with error status...fall through to NFC_ERROR_CEVT case */ case NFC_ERROR_CEVT: if ( (p_t2t->state == RW_T2T_STATE_NOT_ACTIVATED) ||(p_t2t->state == RW_T2T_STATE_IDLE) ||(p_t2t->state == RW_T2T_STATE_HALT) ) { #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) rw_main_update_trans_error_stats (); #endif /* RW_STATS_INCLUDED */ if (event == NFC_ERROR_CEVT) evt_data.status = (tNFC_STATUS) (*(UINT8*) p_data); else if (p_data) evt_data.status = p_data->status; else evt_data.status = NFC_STATUS_FAILED; evt_data.p_data = NULL; (*rw_cb.p_cback) (RW_T2T_INTF_ERROR_EVT, (tRW_DATA *) &evt_data); break; } nfc_stop_quick_timer (&p_t2t->t2_timer); #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) rw_main_update_trans_error_stats (); #endif if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE) { if (p_t2t->check_tag_halt) { p_t2t->state = RW_T2T_STATE_HALT; rw_t2t_handle_presence_check_rsp (NFC_STATUS_REJECTED); } else { /* Move back to idle state */ rw_t2t_handle_presence_check_rsp (NFC_STATUS_FAILED); } } else { rw_t2t_process_error (); } #if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE) /* Free the response buffer in case of invalid response*/ if (p_data != NULL) { GKI_freebuf((BT_HDR *) (p_data->data.p_data)); } #endif break; default: break; } }
/******************************************************************************* ** ** Function rw_t1t_conn_cback ** ** Description This callback function receives the events/data from NFCC. ** ** Returns none ** *******************************************************************************/ void rw_t1t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) { tRW_T1T_CB *p_t1t = &rw_cb.tcb.t1t; tRW_READ_DATA evt_data; RW_TRACE_DEBUG2 ("rw_t1t_conn_cback: conn_id=%i, evt=0x%x", conn_id, event); /* Only handle static conn_id */ if (conn_id != NFC_RF_CONN_ID) { RW_TRACE_WARNING1 ("rw_t1t_conn_cback - Not static connection id: =%i", conn_id); return; } switch (event) { case NFC_CONN_CREATE_CEVT: case NFC_CONN_CLOSE_CEVT: break; case NFC_DEACTIVATE_CEVT: #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) /* Display stats */ rw_main_log_stats (); #endif /* RW_STATS_INCLUDED */ /* Stop t1t timer (if started) */ nfc_stop_quick_timer (&p_t1t->timer); /* Free cmd buf for retransmissions */ if (p_t1t->p_cur_cmd_buf) { GKI_freebuf (p_t1t->p_cur_cmd_buf); p_t1t->p_cur_cmd_buf = NULL; } p_t1t->state = RW_T1T_STATE_NOT_ACTIVATED; NFC_SetStaticRfCback (NULL); break; case NFC_DATA_CEVT: if ( (p_data != NULL) &&(p_data->data.status == NFC_STATUS_OK) ) { rw_t1t_data_cback (conn_id, event, p_data); break; } /* Data event with error status...fall through to NFC_ERROR_CEVT case */ case NFC_ERROR_CEVT: if ( (p_t1t->state == RW_T1T_STATE_NOT_ACTIVATED) ||(p_t1t->state == RW_T1T_STATE_IDLE) ) { #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) rw_main_update_trans_error_stats (); #endif /* RW_STATS_INCLUDED */ if (event == NFC_ERROR_CEVT) evt_data.status = (tNFC_STATUS) (*(UINT8*) p_data); else if (p_data) evt_data.status = p_data->status; else evt_data.status = NFC_STATUS_FAILED; evt_data.p_data = NULL; (*rw_cb.p_cback) (RW_T1T_INTF_ERROR_EVT, (tRW_DATA *) &evt_data); break; } nfc_stop_quick_timer (&p_t1t->timer); #if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) rw_main_update_trans_error_stats (); #endif /* RW_STATS_INCLUDED */ if (p_t1t->state == RW_T1T_STATE_CHECK_PRESENCE) { rw_t1t_handle_presence_check_rsp (NFC_STATUS_FAILED); } else { rw_t1t_process_error (); } break; default: break; } }
/******************************************************************************* ** ** Function rw_t4t_data_cback ** ** Description This callback function receives the data from NFCC. ** ** Returns none ** *******************************************************************************/ static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) { tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; BT_HDR *p_r_apdu = (BT_HDR *) p_data->data.p_data; tRW_DATA rw_data; #if (BT_TRACE_VERBOSE == TRUE) UINT8 begin_state = p_t4t->state; #endif RW_TRACE_DEBUG1 ("rw_t4t_data_cback () event = 0x%X", event); nfc_stop_quick_timer (&p_t4t->timer); switch (event) { case NFC_DEACTIVATE_CEVT: NFC_SetStaticRfCback (NULL); p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED; return; case NFC_ERROR_CEVT: if (p_t4t->state == RW_T4T_STATE_PRESENCE_CHECK) { p_t4t->state = RW_T4T_STATE_IDLE; rw_data.status = NFC_STATUS_FAILED; (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data); } else { p_t4t->state = RW_T4T_STATE_IDLE; rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data); (*(rw_cb.p_cback)) (RW_T4T_INTF_ERROR_EVT, &rw_data); } return; case NFC_DATA_CEVT: break; default: return; } #if (BT_TRACE_PROTOCOL == TRUE) DispRWT4Tags (p_r_apdu, TRUE); #endif #if (BT_TRACE_VERBOSE == TRUE) RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>", rw_t4t_get_state_name (p_t4t->state), p_t4t->state); #else RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state); #endif switch (p_t4t->state) { case RW_T4T_STATE_IDLE: /* Unexpected R-APDU, it should be raw frame response */ /* forward to upper layer without parsing */ if (rw_cb.p_cback) { rw_data.raw_frame.status = NFC_STATUS_OK; rw_data.raw_frame.p_data = p_r_apdu; (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data); p_r_apdu = NULL; } else { GKI_freebuf (p_r_apdu); } break; case RW_T4T_STATE_DETECT_NDEF: rw_t4t_sm_detect_ndef (p_r_apdu); GKI_freebuf (p_r_apdu); break; case RW_T4T_STATE_READ_NDEF: rw_t4t_sm_read_ndef (p_r_apdu); /* p_r_apdu may send upper lyaer */ break; case RW_T4T_STATE_UPDATE_NDEF: rw_t4t_sm_update_ndef (p_r_apdu); GKI_freebuf (p_r_apdu); break; case RW_T4T_STATE_PRESENCE_CHECK: /* if any response, send presence check with ok */ rw_data.status = NFC_STATUS_OK; p_t4t->state = RW_T4T_STATE_IDLE; (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data); GKI_freebuf (p_r_apdu); break; default: RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state); GKI_freebuf (p_r_apdu); break; } #if (BT_TRACE_VERBOSE == TRUE) if (begin_state != p_t4t->state) { RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>", rw_t4t_get_state_name (begin_state), rw_t4t_get_state_name (p_t4t->state)); } #endif }