rw_t2t.c revision e9df6ba5a8fcccf306a80b1670b423be8fe7746a
1/****************************************************************************** 2 * 3 * Copyright (C) 2010-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19/****************************************************************************** 20 * 21 * This file contains the implementation for Type 2 tag in Reader/Writer 22 * mode. 23 * 24 ******************************************************************************/ 25#include <string.h> 26#include "nfc_target.h" 27#include "bt_types.h" 28 29#if (NFC_INCLUDED == TRUE) 30#include "nfc_api.h" 31#include "nci_hmsgs.h" 32#include "rw_api.h" 33#include "rw_int.h" 34#include "nfc_int.h" 35#include "gki.h" 36 37/* Static local functions */ 38static void rw_t2t_proc_data (UINT8 conn_id, tNFC_CONN_EVT event, BT_HDR *p_pkt); 39static tNFC_STATUS rw_t2t_send_cmd (UINT8 opcode, UINT8 *p_dat); 40static void rw_t2t_process_error (void); 41static void rw_t2t_process_frame_error (void); 42static void rw_t2t_handle_presence_check_rsp (tNFC_STATUS status); 43static void rw_t2t_resume_op (void); 44 45#if (BT_TRACE_VERBOSE == TRUE) 46static char *rw_t2t_get_state_name (UINT8 state); 47static char *rw_t2t_get_substate_name (UINT8 substate); 48#endif 49 50/******************************************************************************* 51** 52** Function rw_t2t_proc_data 53** 54** Description This function handles data evt received from NFC Controller. 55** 56** Returns none 57** 58*******************************************************************************/ 59static void rw_t2t_proc_data (UINT8 conn_id, tNFC_CONN_EVT event, BT_HDR *p_pkt) 60{ 61 tRW_EVENT rw_event = RW_RAW_FRAME_EVT; 62 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 63 BOOLEAN b_notify = TRUE; 64 BOOLEAN b_release = TRUE; 65 UINT8 *p; 66 tRW_READ_DATA evt_data = {0}; 67 tT2T_CMD_RSP_INFO *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info; 68 tRW_DETECT_NDEF_DATA ndef_data; 69 70 if ( (p_t2t->state == RW_T2T_STATE_IDLE) 71 ||(p_cmd_rsp_info == NULL) ) 72 { 73 RW_TRACE_DEBUG2 ("rw_t2t_proc_data - Raw frame event! state: IDLE, conn_id: %u event: %u", 74 conn_id, event); 75 76 evt_data.status = NFC_STATUS_OK; 77 evt_data.p_data = p_pkt; 78 (*rw_cb.p_cback) (RW_T2T_RAW_FRAME_EVT, (tRW_DATA *)&evt_data); 79 return; 80 } 81#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 82 /* Update rx stats */ 83 rw_main_update_rx_stats (p_pkt->len); 84#endif 85 /* Stop timer as response is received */ 86 nfc_stop_quick_timer (&p_t2t->t2_timer); 87 88 RW_TRACE_EVENT2 ("RW RECV [%s]:0x%x RSP", t2t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode); 89 90 if ( (p_pkt->len != p_cmd_rsp_info->rsp_len) 91 &&(p_pkt->len != p_cmd_rsp_info->nack_rsp_len) 92 &&(p_t2t->substate != RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR) ) 93 { 94#if (BT_TRACE_VERBOSE == TRUE) 95 RW_TRACE_ERROR1 ("T2T Frame error. state=%s ", rw_t2t_get_state_name (p_t2t->state)); 96#else 97 RW_TRACE_ERROR1 ("T2T Frame error. state=0x%02X command=0x%02X ", p_t2t->state); 98#endif 99 /* Retrasmit the last sent command if retry-count < max retry */ 100 rw_t2t_process_frame_error (); 101 GKI_freebuf (p_pkt); 102 return; 103 } 104 rw_cb.cur_retry = 0; 105 106 /* Assume the data is just the response byte sequence */ 107 p = (UINT8 *) (p_pkt + 1) + p_pkt->offset; 108 109 110 RW_TRACE_EVENT5 ("rw_t2t_proc_data State: %u conn_id: %u event: %u len: %u data[0]: 0x%02x", 111 p_t2t->state, conn_id, event, p_pkt->len, *p); 112 113 evt_data.p_data = NULL; 114 115 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT) 116 { 117 /* The select process happens in two steps */ 118 if ((*p & 0x0f) == T2T_RSP_ACK) 119 { 120 if (rw_t2t_sector_change (p_t2t->select_sector) == NFC_STATUS_OK) 121 b_notify = FALSE; 122 else 123 evt_data.status = NFC_STATUS_FAILED; 124 } 125 else 126 { 127 evt_data.status = NFC_STATUS_FAILED; 128 } 129 } 130 else if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR) 131 { 132 evt_data.status = NFC_STATUS_FAILED; 133 } 134 else if (p_pkt->len == p_cmd_rsp_info->rsp_len) 135 { 136 /* If the response length indicates positive response or cannot be known from length then assume success */ 137 evt_data.status = NFC_STATUS_OK; 138 139 /* The response data depends on what the current operation was */ 140 switch (p_t2t->state) 141 { 142 case RW_T2T_STATE_CHECK_PRESENCE: 143 b_notify = FALSE; 144 rw_t2t_handle_presence_check_rsp (NFC_STATUS_OK); 145 break; 146 147 case RW_T2T_STATE_READ: 148 evt_data.p_data = p_pkt; 149 b_release = FALSE; 150 if (p_t2t->block_read == 0) 151 { 152 p_t2t->b_read_hdr = TRUE; 153 memcpy (p_t2t->tag_hdr, p, T2T_READ_DATA_LEN); 154 155 /* On Ultralight - C tag, if CC is corrupt, correct it */ 156 if ( (p_t2t->tag_hdr[0] == TAG_MIFARE_MID) 157 &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] >= T2T_INVALID_CC_TMS_VAL0) 158 &&(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] <= T2T_INVALID_CC_TMS_VAL1) ) 159 { 160 p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] = T2T_CC2_TMS_MULC; 161 } 162 } 163 break; 164 165 case RW_T2T_STATE_WRITE: 166 /* Check positive or negative acknowledgment */ 167 if ((*p & 0x0f) != T2T_RSP_ACK) 168 evt_data.status = NFC_STATUS_FAILED; 169 break; 170 171 default: 172 /* NDEF/other Tlv Operation/Format Tag/Config Tag as Read only 173 * Check if Positive response to previous write command */ 174 if ( (p_cmd_rsp_info->opcode == T2T_CMD_WRITE) 175 &&((*p & 0x0f) != T2T_RSP_ACK) ) 176 evt_data.status = NFC_STATUS_FAILED; 177 else 178 { 179 b_notify = FALSE; 180 rw_t2t_handle_rsp (p); 181 } 182 break; 183 } 184 } 185 else 186 { 187 evt_data.p_data = p_pkt; 188 if (p_t2t->state == RW_T2T_STATE_READ) 189 b_release = FALSE; 190 191 /* Negative response to the command sent */ 192 evt_data.status = NFC_STATUS_FAILED; 193 } 194 195 if (b_notify) 196 { 197 rw_event = rw_t2t_info_to_event (p_cmd_rsp_info); 198 /* Move back to idle state */ 199 rw_t2t_handle_op_complete (); 200 if (rw_event == RW_T2T_NDEF_DETECT_EVT) 201 { 202 ndef_data.status = evt_data.status; 203 ndef_data.protocol = NFC_PROTOCOL_T2T; 204 ndef_data.flags = RW_NDEF_FL_UNKNOWN; 205 ndef_data.max_size = 0; 206 ndef_data.cur_size = 0; 207 (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &ndef_data); 208 } 209 else 210 (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data); 211 } 212 213 if (b_release) 214 GKI_freebuf (p_pkt); 215} 216 217/******************************************************************************* 218** 219** Function rw_t2t_conn_cback 220** 221** Description This callback function receives events/data from NFCC. 222** 223** Returns none 224** 225*******************************************************************************/ 226void rw_t2t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) 227{ 228 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 229 tRW_READ_DATA evt_data; 230 231 RW_TRACE_DEBUG2 ("rw_t2t_conn_cback: conn_id=%i, evt=%i", conn_id, event); 232 /* Only handle static conn_id */ 233 if (conn_id != NFC_RF_CONN_ID) 234 { 235 return; 236 } 237 238 switch (event) 239 { 240 case NFC_CONN_CREATE_CEVT: 241 case NFC_CONN_CLOSE_CEVT: 242 break; 243 244 case NFC_DEACTIVATE_CEVT: 245#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 246 /* Display stats */ 247 rw_main_log_stats (); 248#endif 249 /* Stop t2t timer (if started) */ 250 nfc_stop_quick_timer (&p_t2t->t2_timer); 251 252 /* Free cmd buf for retransmissions */ 253 if (p_t2t->p_cur_cmd_buf) 254 { 255 GKI_freebuf (p_t2t->p_cur_cmd_buf); 256 p_t2t->p_cur_cmd_buf = NULL; 257 } 258 /* Free cmd buf used to hold command before sector change */ 259 if (p_t2t->p_sec_cmd_buf) 260 { 261 GKI_freebuf (p_t2t->p_sec_cmd_buf); 262 p_t2t->p_sec_cmd_buf = NULL; 263 } 264 265 p_t2t->state = RW_T2T_STATE_NOT_ACTIVATED; 266 NFC_SetStaticRfCback (NULL); 267 break; 268 269 case NFC_DATA_CEVT: 270 if ( (p_data != NULL) 271 &&(p_data->data.status == NFC_STATUS_OK) ) 272 { 273 rw_t2t_proc_data (conn_id, event, (BT_HDR *) (p_data->data.p_data)); 274 break; 275 } 276 /* Data event with error status...fall through to NFC_ERROR_CEVT case */ 277 278 case NFC_ERROR_CEVT: 279 if ( (p_t2t->state == RW_T2T_STATE_NOT_ACTIVATED) 280 ||(p_t2t->state == RW_T2T_STATE_IDLE) ) 281 { 282#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 283 rw_main_update_trans_error_stats (); 284#endif /* RW_STATS_INCLUDED */ 285 if (event == NFC_ERROR_CEVT) 286 evt_data.status = (tNFC_STATUS) (*(UINT8*) p_data); 287 else if (p_data) 288 evt_data.status = p_data->status; 289 else 290 evt_data.status = NFC_STATUS_FAILED; 291 292 evt_data.p_data = NULL; 293 (*rw_cb.p_cback) (RW_T2T_INTF_ERROR_EVT, (tRW_DATA *) &evt_data); 294 break; 295 } 296 nfc_stop_quick_timer (&p_t2t->t2_timer); 297#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 298 rw_main_update_trans_error_stats (); 299#endif 300 if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE) 301 { 302 rw_t2t_handle_presence_check_rsp (NFC_STATUS_FAILED); 303 } 304 else 305 { 306 rw_t2t_process_error (); 307 } 308 break; 309 310 default: 311 break; 312 313 } 314} 315 316/******************************************************************************* 317** 318** Function rw_t2t_send_cmd 319** 320** Description This function composes a Type 2 Tag command and send it via 321** NCI to NFCC. 322** 323** Returns NFC_STATUS_OK if the command is successfuly sent to NCI 324** otherwise, error status 325** 326*******************************************************************************/ 327tNFC_STATUS rw_t2t_send_cmd (UINT8 opcode, UINT8 *p_dat) 328{ 329 tNFC_STATUS status = NFC_STATUS_FAILED; 330 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 331 const tT2T_CMD_RSP_INFO *p_cmd_rsp_info = t2t_cmd_to_rsp_info (opcode); 332 BT_HDR *p_data; 333 UINT8 *p; 334 335 if (p_cmd_rsp_info) 336 { 337 /* a valid opcode for RW */ 338 p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); 339 if (p_data) 340 { 341 p_t2t->p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) p_cmd_rsp_info; 342 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 343 p = (UINT8 *) (p_data + 1) + p_data->offset; 344 345 UINT8_TO_STREAM (p, opcode); 346 347 if (p_dat) 348 { 349 ARRAY_TO_STREAM (p, p_dat, (p_cmd_rsp_info->cmd_len - 1)); 350 } 351 352 p_data->len = p_cmd_rsp_info->cmd_len; 353 354 /* Indicate first attempt to send command, back up cmd buffer in case needed for retransmission */ 355 rw_cb.cur_retry = 0; 356 memcpy (p_t2t->p_cur_cmd_buf, p_data, sizeof (BT_HDR) + p_data->offset + p_data->len); 357 358#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 359 /* Update stats */ 360 rw_main_update_tx_stats (p_data->len, FALSE); 361#endif 362 RW_TRACE_EVENT2 ("RW SENT [%s]:0x%x CMD", t2t_info_to_str (p_cmd_rsp_info), p_cmd_rsp_info->opcode); 363 364 if ((status = NFC_SendData (NFC_RF_CONN_ID, p_data)) == NFC_STATUS_OK) 365 { 366 nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE, 367 (RW_T2T_TOUT_RESP*QUICK_TIMER_TICKS_PER_SEC) / 1000); 368 } 369 else 370 { 371#if (BT_TRACE_VERBOSE == TRUE) 372 RW_TRACE_ERROR2 ("T2T NFC Send data failed. state=%s substate=%s ", rw_t2t_get_state_name (p_t2t->state), rw_t2t_get_substate_name (p_t2t->substate)); 373#else 374 RW_TRACE_ERROR2 ("T2T NFC Send data failed. state=0x%02X substate=0x%02X ", p_t2t->state, p_t2t->substate); 375#endif 376 } 377 } 378 else 379 { 380 status = NFC_STATUS_NO_BUFFERS; 381 } 382 } 383 return status; 384} 385 386/******************************************************************************* 387** 388** Function rw_t2t_process_timeout 389** 390** Description handles timeout event 391** 392** Returns none 393** 394*******************************************************************************/ 395void rw_t2t_process_timeout (TIMER_LIST_ENT *p_tle) 396{ 397 tRW_READ_DATA evt_data; 398 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 399 400 if (p_t2t->state == RW_T2T_STATE_CHECK_PRESENCE) 401 { 402 /* Move back to idle state */ 403 rw_t2t_handle_presence_check_rsp (NFC_STATUS_FAILED); 404 return; 405 } 406 407 if (p_t2t->substate == RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR) 408 { 409 p_t2t->sector = p_t2t->select_sector; 410 /* Here timeout is an acknowledgment for successfull sector change */ 411 if (p_t2t->state == RW_T2T_STATE_SELECT_SECTOR) 412 { 413 /* Notify that select sector op is successfull */ 414 rw_t2t_handle_op_complete (); 415 evt_data.status = NFC_STATUS_OK; 416 evt_data.p_data = NULL; 417 (*rw_cb.p_cback) (RW_T2T_SELECT_CPLT_EVT, (tRW_DATA *) &evt_data); 418 } 419 else 420 { 421 /* Resume operation from where we stopped before sector change */ 422 rw_t2t_resume_op (); 423 } 424 } 425 else if (p_t2t->state != RW_T2T_STATE_IDLE) 426 { 427#if (BT_TRACE_VERBOSE == TRUE) 428 RW_TRACE_ERROR1 ("T2T timeout. state=%s ", rw_t2t_get_state_name (p_t2t->state)); 429#else 430 RW_TRACE_ERROR1 ("T2T timeout. state=0x%02X ", p_t2t->state); 431#endif 432 /* Handle timeout error as no response to the command sent */ 433 rw_t2t_process_error (); 434 } 435} 436 437/******************************************************************************* 438** 439** Function rw_t2t_process_frame_error 440** 441** Description handles frame crc error 442** 443** Returns none 444** 445*******************************************************************************/ 446static void rw_t2t_process_frame_error (void) 447{ 448#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 449 /* Update stats */ 450 rw_main_update_crc_error_stats (); 451#endif 452 /* Process the error */ 453 rw_t2t_process_error (); 454} 455 456/******************************************************************************* 457** 458** Function rw_t2t_process_error 459** 460** Description Process error including Timeout, Frame error. This function 461** will retry atleast till RW_MAX_RETRIES before give up and 462** sending negative notification to upper layer 463** 464** Returns none 465** 466*******************************************************************************/ 467static void rw_t2t_process_error (void) 468{ 469 tRW_READ_DATA evt_data; 470 tRW_EVENT rw_event; 471 BT_HDR *p_cmd_buf; 472 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 473 tT2T_CMD_RSP_INFO *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info; 474 tRW_DETECT_NDEF_DATA ndef_data; 475 476 RW_TRACE_DEBUG1 ("rw_t2t_process_error () State: %u", p_t2t->state); 477 478 /* Retry sending command if retry-count < max */ 479 if (rw_cb.cur_retry < RW_MAX_RETRIES) 480 { 481 /* retry sending the command */ 482 rw_cb.cur_retry++; 483 484 RW_TRACE_DEBUG2 ("T2T retransmission attempt %i of %i", rw_cb.cur_retry, RW_MAX_RETRIES); 485 486 /* allocate a new buffer for message */ 487 if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL) 488 { 489 memcpy (p_cmd_buf, p_t2t->p_cur_cmd_buf, sizeof (BT_HDR) + p_t2t->p_cur_cmd_buf->offset + p_t2t->p_cur_cmd_buf->len); 490#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 491 /* Update stats */ 492 rw_main_update_tx_stats (p_cmd_buf->len, TRUE); 493#endif 494 if (NFC_SendData (NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK) 495 { 496 /* Start timer for waiting for response */ 497 nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE, 498 (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); 499 500 return; 501 } 502 } 503 } 504 else 505 { 506 RW_TRACE_DEBUG1 ("T2T maximum retransmission attempts reached (%i)", RW_MAX_RETRIES); 507 } 508 rw_event = rw_t2t_info_to_event (p_cmd_rsp_info); 509#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 510 /* update failure count */ 511 rw_main_update_fail_stats (); 512#endif 513 /* If not activated remain in non activated state, otherwise move to idle state */ 514 if (p_t2t->state != RW_T2T_STATE_NOT_ACTIVATED) 515 rw_t2t_handle_op_complete (); 516 517 p_t2t->substate = RW_T2T_SUBSTATE_NONE; 518 evt_data.status = NFC_STATUS_TIMEOUT; 519 if (rw_event == RW_T2T_NDEF_DETECT_EVT) 520 { 521 ndef_data.status = evt_data.status; 522 ndef_data.protocol = NFC_PROTOCOL_T2T; 523 ndef_data.flags = RW_NDEF_FL_UNKNOWN; 524 ndef_data.max_size = 0; 525 ndef_data.cur_size = 0; 526 (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &ndef_data); 527 } 528 else 529 { 530 evt_data.p_data = NULL; 531 (*rw_cb.p_cback) (rw_event, (tRW_DATA *) &evt_data); 532 } 533} 534 535/***************************************************************************** 536** 537** Function rw_t2t_handle_presence_check_rsp 538** 539** Description Handle response to presence check 540** 541** Returns Nothing 542** 543*****************************************************************************/ 544void rw_t2t_handle_presence_check_rsp (tNFC_STATUS status) 545{ 546 tRW_READ_DATA evt_data; 547 548 /* Notify, Tag is present or not */ 549 evt_data.status = status; 550 rw_t2t_handle_op_complete (); 551 552 (*rw_cb.p_cback) (RW_T2T_PRESENCE_CHECK_EVT, (tRW_DATA *) &evt_data); 553} 554 555/******************************************************************************* 556** 557** Function rw_t2t_resume_op 558** 559** Description This function will continue operation after moving to new 560** sector 561** 562** Returns tNFC_STATUS 563** 564*******************************************************************************/ 565static void rw_t2t_resume_op (void) 566{ 567 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 568 tRW_READ_DATA evt_data; 569 BT_HDR *p_cmd_buf; 570 tRW_EVENT event; 571 const tT2T_CMD_RSP_INFO *p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) rw_cb.tcb.t2t.p_cmd_rsp_info; 572 UINT8 *p; 573 574 /* Move back to the substate where we were before changing sector */ 575 p_t2t->substate = p_t2t->prev_substate; 576 577 p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset; 578 p_cmd_rsp_info = t2t_cmd_to_rsp_info ((UINT8) *p); 579 p_t2t->p_cmd_rsp_info = (tT2T_CMD_RSP_INFO *) p_cmd_rsp_info; 580 581 /* allocate a new buffer for message */ 582 if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) != NULL) 583 { 584 memcpy (p_cmd_buf, p_t2t->p_sec_cmd_buf, sizeof (BT_HDR) + p_t2t->p_sec_cmd_buf->offset + p_t2t->p_sec_cmd_buf->len); 585 memcpy (p_t2t->p_cur_cmd_buf, p_t2t->p_sec_cmd_buf, sizeof (BT_HDR) + p_t2t->p_sec_cmd_buf->offset + p_t2t->p_sec_cmd_buf->len); 586 587#if (defined (RW_STATS_INCLUDED) && (RW_STATS_INCLUDED == TRUE)) 588 /* Update stats */ 589 rw_main_update_tx_stats (p_cmd_buf->len, TRUE); 590#endif 591 if (NFC_SendData (NFC_RF_CONN_ID, p_cmd_buf) == NFC_STATUS_OK) 592 { 593 /* Start timer for waiting for response */ 594 nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE, 595 (RW_T2T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); 596 } 597 else 598 { 599 /* failure - could not send buffer */ 600 evt_data.p_data = NULL; 601 evt_data.status = NFC_STATUS_FAILED; 602 event = rw_t2t_info_to_event (p_cmd_rsp_info); 603 rw_t2t_handle_op_complete (); 604 (*rw_cb.p_cback) (event, (tRW_DATA *) &evt_data); 605 } 606 } 607} 608 609/******************************************************************************* 610** 611** Function rw_t2t_sector_change 612** 613** Description This function issues Type 2 Tag SECTOR-SELECT command 614** packet 1. 615** 616** Returns tNFC_STATUS 617** 618*******************************************************************************/ 619tNFC_STATUS rw_t2t_sector_change (UINT8 sector) 620{ 621 tNFC_STATUS status; 622 BT_HDR *p_data; 623 UINT8 *p; 624 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 625 626 if ((p_data = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) 627 { 628 RW_TRACE_ERROR0 ("rw_t2t_sector_change - No buffer"); 629 return (NFC_STATUS_NO_BUFFERS); 630 } 631 632 p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 633 p = (UINT8 *) (p_data + 1) + p_data->offset; 634 635 UINT8_TO_BE_STREAM (p, sector); 636 UINT8_TO_BE_STREAM (p, 0x00); 637 UINT8_TO_BE_STREAM (p, 0x00); 638 UINT8_TO_BE_STREAM (p, 0x00); 639 640 p_data->len = 4; 641 642 if ((status = NFC_SendData (NFC_RF_CONN_ID , p_data)) == NFC_STATUS_OK) 643 { 644 /* Passive rsp command and suppose not to get response to this command */ 645 p_t2t->p_cmd_rsp_info = NULL; 646 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR; 647 648 RW_TRACE_EVENT0 ("rw_t2t_sector_change Sent Second Command"); 649 nfc_start_quick_timer (&p_t2t->t2_timer, NFC_TTYPE_RW_T2T_RESPONSE, 650 (RW_T2T_SEC_SEL_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); 651 } 652 else 653 { 654 RW_TRACE_ERROR1 ("rw_t2t_sector_change Send failed at rw_t2t_send_cmd, error: %u", status); 655 } 656 657 return status; 658} 659 660/******************************************************************************* 661** 662** Function rw_t2t_read 663** 664** Description This function issues Type 2 Tag READ command for the 665** specified block. If the specified block is in different 666** sector then it first sends command to move to new sector 667** and after the tag moves to new sector it issues the read 668** command for the block. 669** 670** Returns tNFC_STATUS 671** 672*******************************************************************************/ 673tNFC_STATUS rw_t2t_read (UINT16 block) 674{ 675 tNFC_STATUS status; 676 UINT8 *p; 677 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 678 UINT8 sector_byte2[1]; 679 UINT8 read_cmd[1]; 680 681 682 read_cmd[0] = block % T2T_BLOCKS_PER_SECTOR; 683 if (p_t2t->sector != block/T2T_BLOCKS_PER_SECTOR) 684 { 685 sector_byte2[0] = 0xFF; 686 /* First Move to new sector before sending Read command */ 687 if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL,sector_byte2)) == NFC_STATUS_OK) 688 { 689 /* Prepare command that needs to be sent after sector change op is completed */ 690 p_t2t->select_sector = (UINT8) (block/T2T_BLOCKS_PER_SECTOR); 691 p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 692 693 p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset; 694 UINT8_TO_BE_STREAM (p, T2T_CMD_READ); 695 UINT8_TO_BE_STREAM (p, read_cmd[0]); 696 p_t2t->p_sec_cmd_buf->len = 2; 697 p_t2t->block_read = block; 698 699 /* Backup the current substate to move back to this substate after changing sector */ 700 p_t2t->prev_substate = p_t2t->substate; 701 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT; 702 return NFC_STATUS_OK; 703 } 704 return NFC_STATUS_FAILED; 705 } 706 707 /* Send Read command as sector change is not needed */ 708 if ((status = rw_t2t_send_cmd (T2T_CMD_READ, (UINT8 *) read_cmd)) == NFC_STATUS_OK) 709 { 710 p_t2t->block_read = block; 711 RW_TRACE_EVENT1 ("rw_t2t_read Sent Command for Block: %u", block); 712 } 713 714 return status; 715} 716 717/******************************************************************************* 718** 719** Function rw_t2t_write 720** 721** Description This function issues Type 2 Tag WRITE command for the 722** specified block. If the specified block is in different 723** sector then it first sends command to move to new sector 724** and after the tag moves to new sector it issues the write 725** command for the block. 726** 727** Returns tNFC_STATUS 728** 729*******************************************************************************/ 730tNFC_STATUS rw_t2t_write (UINT16 block, UINT8 *p_write_data) 731{ 732 tNFC_STATUS status; 733 UINT8 *p; 734 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 735 UINT8 write_cmd[T2T_WRITE_DATA_LEN + 1]; 736 UINT8 sector_byte2[1]; 737 738 p_t2t->block_written = block; 739 write_cmd[0] = (UINT8) (block%T2T_BLOCKS_PER_SECTOR); 740 memcpy (&write_cmd[1], p_write_data, T2T_WRITE_DATA_LEN); 741 742 if (p_t2t->sector != block/T2T_BLOCKS_PER_SECTOR) 743 { 744 sector_byte2[0] = 0xFF; 745 /* First Move to new sector before sending Write command */ 746 if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL, sector_byte2)) == NFC_STATUS_OK) 747 { 748 /* Prepare command that needs to be sent after sector change op is completed */ 749 p_t2t->select_sector = (UINT8) (block/T2T_BLOCKS_PER_SECTOR); 750 p_t2t->p_sec_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 751 p = (UINT8 *) (p_t2t->p_sec_cmd_buf + 1) + p_t2t->p_sec_cmd_buf->offset; 752 UINT8_TO_BE_STREAM (p, T2T_CMD_WRITE); 753 memcpy (p, write_cmd, T2T_WRITE_DATA_LEN + 1); 754 p_t2t->p_sec_cmd_buf->len = 2 + T2T_WRITE_DATA_LEN; 755 p_t2t->block_written = block; 756 757 /* Backup the current substate to move back to this substate after changing sector */ 758 p_t2t->prev_substate = p_t2t->substate; 759 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT; 760 return NFC_STATUS_OK; 761 } 762 return NFC_STATUS_FAILED; 763 } 764 765 /* Send Write command as sector change is not needed */ 766 if ((status = rw_t2t_send_cmd (T2T_CMD_WRITE, write_cmd)) == NFC_STATUS_OK) 767 { 768 RW_TRACE_EVENT1 ("rw_t2t_write Sent Command for Block: %u", block); 769 } 770 771 return status; 772} 773 774/******************************************************************************* 775** 776** Function rw_t2t_select 777** 778** Description This function selects type 2 tag. 779** 780** Returns Tag selection status 781** 782*******************************************************************************/ 783tNFC_STATUS rw_t2t_select (void) 784{ 785 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 786 787 p_t2t->state = RW_T2T_STATE_IDLE; 788 p_t2t->ndef_status = T2T_NDEF_NOT_DETECTED; 789 790 791 /* Alloc cmd buf for retransmissions */ 792 if (p_t2t->p_cur_cmd_buf == NULL) 793 { 794 if ((p_t2t->p_cur_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) 795 { 796 RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer for retransmission"); 797 return (NFC_STATUS_FAILED); 798 } 799 } 800 /* Alloc cmd buf for holding a command untill sector changes */ 801 if (p_t2t->p_sec_cmd_buf == NULL) 802 { 803 if ((p_t2t->p_sec_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID)) == NULL) 804 { 805 RW_TRACE_ERROR0 ("rw_t2t_select: unable to allocate buffer used during sector change"); 806 return (NFC_STATUS_FAILED); 807 } 808 } 809 810 NFC_SetStaticRfCback (rw_t2t_conn_cback); 811 rw_t2t_handle_op_complete (); 812 813 return NFC_STATUS_OK; 814} 815 816/***************************************************************************** 817** 818** Function rw_t2t_handle_op_complete 819** 820** Description Reset to IDLE state 821** 822** Returns Nothing 823** 824*****************************************************************************/ 825void rw_t2t_handle_op_complete (void) 826{ 827 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 828 829 p_t2t->state = RW_T2T_STATE_IDLE; 830 p_t2t->substate = RW_T2T_SUBSTATE_NONE; 831 return; 832} 833 834/***************************************************************************** 835** 836** Function RW_T2tPresenceCheck 837** 838** Description 839** Check if the tag is still in the field. 840** 841** The RW_T2T_PRESENCE_CHECK_EVT w/ status is used to indicate presence 842** or non-presence. 843** 844** Returns 845** NFC_STATUS_OK, if raw data frame sent 846** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation 847** NFC_STATUS_FAILED: other error 848** 849*****************************************************************************/ 850tNFC_STATUS RW_T2tPresenceCheck (void) 851{ 852 tNFC_STATUS retval = NFC_STATUS_OK; 853 tRW_DATA evt_data; 854 tRW_CB *p_rw_cb = &rw_cb; 855 UINT8 sector_blk = 0; /* block 0 of current sector */ 856 857 RW_TRACE_API0 ("RW_T2tPresenceCheck"); 858 859 /* If RW_SelectTagType was not called (no conn_callback) return failure */ 860 if (!p_rw_cb->p_cback) 861 { 862 retval = NFC_STATUS_FAILED; 863 } 864 /* If we are not activated, then RW_T2T_PRESENCE_CHECK_EVT status=FAIL */ 865 else if (p_rw_cb->tcb.t2t.state == RW_T2T_STATE_NOT_ACTIVATED) 866 { 867 evt_data.status = NFC_STATUS_FAILED; 868 (*p_rw_cb->p_cback) (RW_T2T_PRESENCE_CHECK_EVT, &evt_data); 869 } 870 /* If command is pending, assume tag is still present */ 871 else if (p_rw_cb->tcb.t2t.state != RW_T2T_STATE_IDLE) 872 { 873 evt_data.status = NFC_STATUS_OK; 874 (*p_rw_cb->p_cback) (RW_T2T_PRESENCE_CHECK_EVT, &evt_data); 875 } 876 else 877 { 878 /* IDLE state: send a READ command to block 0 of the current sector */ 879 if((retval = rw_t2t_send_cmd (T2T_CMD_READ, §or_blk))== NFC_STATUS_OK) 880 { 881 p_rw_cb->tcb.t2t.state = RW_T2T_STATE_CHECK_PRESENCE; 882 } 883 } 884 885 return (retval); 886} 887 888/******************************************************************************* 889** 890** Function RW_T2tRead 891** 892** Description This function issues the Type 2 Tag READ command. When the 893** operation is complete the callback function will be called 894** with a RW_T2T_READ_EVT. 895** 896** Returns tNFC_STATUS 897** 898*******************************************************************************/ 899tNFC_STATUS RW_T2tRead (UINT16 block) 900{ 901 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 902 tNFC_STATUS status; 903 904 if (p_t2t->state != RW_T2T_STATE_IDLE) 905 { 906 RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state); 907 return (NFC_STATUS_FAILED); 908 } 909 910 if ((status = rw_t2t_read (block)) == NFC_STATUS_OK) 911 { 912 p_t2t->state = RW_T2T_STATE_READ; 913 RW_TRACE_EVENT0 ("RW_T2tRead Sent Read command"); 914 } 915 916 return status; 917 918} 919 920/******************************************************************************* 921** 922** Function RW_T2tWrite 923** 924** Description This function issues the Type 2 Tag WRITE command. When the 925** operation is complete the callback function will be called 926** with a RW_T2T_WRITE_EVT. 927** 928** p_new_bytes points to the array of 4 bytes to be written 929** 930** Returns tNFC_STATUS 931** 932*******************************************************************************/ 933tNFC_STATUS RW_T2tWrite (UINT16 block, UINT8 *p_write_data) 934{ 935 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 936 tNFC_STATUS status; 937 938 if (p_t2t->state != RW_T2T_STATE_IDLE) 939 { 940 RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state); 941 return (NFC_STATUS_FAILED); 942 } 943 944 if ((status = rw_t2t_write (block, p_write_data)) == NFC_STATUS_OK) 945 { 946 p_t2t->state = RW_T2T_STATE_WRITE; 947 if (block < T2T_FIRST_DATA_BLOCK) 948 p_t2t->b_read_hdr = FALSE; 949 else if (block < (T2T_FIRST_DATA_BLOCK + T2T_READ_BLOCKS)) 950 p_t2t->b_read_data = FALSE; 951 RW_TRACE_EVENT0 ("RW_T2tWrite Sent Write command"); 952 } 953 954 return status; 955} 956 957/******************************************************************************* 958** 959** Function RW_T2tSectorSelect 960** 961** Description This function issues the Type 2 Tag SECTOR-SELECT command 962** packet 1. If a NACK is received as the response, the callback 963** function will be called with a RW_T2T_SECTOR_SELECT_EVT. If 964** an ACK is received as the response, the command packet 2 with 965** the given sector number is sent to the peer device. When the 966** response for packet 2 is received, the callback function will 967** be called with a RW_T2T_SECTOR_SELECT_EVT. 968** 969** A sector is 256 contiguous blocks (1024 bytes). 970** 971** Returns tNFC_STATUS 972** 973*******************************************************************************/ 974tNFC_STATUS RW_T2tSectorSelect (UINT8 sector) 975{ 976 tNFC_STATUS status; 977 tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t; 978 UINT8 sector_byte2[1]; 979 980 if (p_t2t->state != RW_T2T_STATE_IDLE) 981 { 982 RW_TRACE_ERROR1 ("Error: Type 2 tag not activated or Busy - State: %u", p_t2t->state); 983 return (NFC_STATUS_FAILED); 984 } 985 986 if (sector >= T2T_MAX_SECTOR) 987 { 988 RW_TRACE_ERROR2 ("RW_T2tSectorSelect - Invalid sector: %u, T2 Max supported sector value: %u", sector, T2T_MAX_SECTOR - 1); 989 return (NFC_STATUS_FAILED); 990 } 991 992 sector_byte2[0] = 0xFF; 993 994 if ((status = rw_t2t_send_cmd (T2T_CMD_SEC_SEL, sector_byte2)) == NFC_STATUS_OK) 995 { 996 p_t2t->state = RW_T2T_STATE_SELECT_SECTOR; 997 p_t2t->select_sector = sector; 998 p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT; 999 1000 RW_TRACE_EVENT0 ("RW_T2tSectorSelect Sent Sector select first command"); 1001 } 1002 1003 return status; 1004} 1005 1006#if (BT_TRACE_VERBOSE == TRUE) 1007/******************************************************************************* 1008** 1009** Function rw_t2t_get_state_name 1010** 1011** Description This function returns the state name. 1012** 1013** NOTE conditionally compiled to save memory. 1014** 1015** Returns pointer to the name 1016** 1017*******************************************************************************/ 1018static char *rw_t2t_get_state_name (UINT8 state) 1019{ 1020 switch (state) 1021 { 1022 case RW_T2T_STATE_NOT_ACTIVATED: 1023 return ("NOT_ACTIVATED"); 1024 case RW_T2T_STATE_IDLE: 1025 return ("IDLE"); 1026 case RW_T2T_STATE_READ: 1027 return ("APP_READ"); 1028 case RW_T2T_STATE_WRITE: 1029 return ("APP_WRITE"); 1030 case RW_T2T_STATE_SELECT_SECTOR: 1031 return ("SECTOR_SELECT"); 1032 case RW_T2T_STATE_DETECT_TLV: 1033 return ("TLV_DETECT"); 1034 case RW_T2T_STATE_READ_NDEF: 1035 return ("READ_NDEF"); 1036 case RW_T2T_STATE_WRITE_NDEF: 1037 return ("WRITE_NDEF"); 1038 case RW_T2T_STATE_SET_TAG_RO: 1039 return ("SET_TAG_RO"); 1040 case RW_T2T_STATE_CHECK_PRESENCE: 1041 return ("CHECK_PRESENCE"); 1042 default: 1043 return ("???? UNKNOWN STATE"); 1044 } 1045} 1046 1047/******************************************************************************* 1048** 1049** Function rw_t2t_get_substate_name 1050** 1051** Description This function returns the substate name. 1052** 1053** NOTE conditionally compiled to save memory. 1054** 1055** Returns pointer to the name 1056** 1057*******************************************************************************/ 1058static char *rw_t2t_get_substate_name (UINT8 substate) 1059{ 1060 switch (substate) 1061 { 1062 case RW_T2T_SUBSTATE_NONE: 1063 return ("RW_T2T_SUBSTATE_NONE"); 1064 case RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT: 1065 return ("RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR_SUPPORT"); 1066 case RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR: 1067 return ("RW_T2T_SUBSTATE_WAIT_SELECT_SECTOR"); 1068 case RW_T2T_SUBSTATE_WAIT_READ_CC: 1069 return ("RW_T2T_SUBSTATE_WAIT_READ_CC"); 1070 case RW_T2T_SUBSTATE_WAIT_TLV_DETECT: 1071 return ("RW_T2T_SUBSTATE_WAIT_TLV_DETECT"); 1072 case RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN: 1073 return ("RW_T2T_SUBSTATE_WAIT_FIND_LEN_FIELD_LEN"); 1074 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0: 1075 return ("RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN0"); 1076 case RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1: 1077 return ("RW_T2T_SUBSTATE_WAIT_READ_TLV_LEN1"); 1078 case RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE: 1079 return ("RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE"); 1080 case RW_T2T_SUBSTATE_WAIT_READ_LOCKS: 1081 return ("RW_T2T_SUBSTATE_WAIT_READ_LOCKS"); 1082 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK: 1083 return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK"); 1084 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK: 1085 return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK"); 1086 case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK: 1087 return ("RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK"); 1088 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK: 1089 return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_NEXT_BLOCK"); 1090 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK: 1091 return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_NEXT_BLOCK"); 1092 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK: 1093 return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LAST_BLOCK"); 1094 case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK: 1095 return ("RW_T2T_SUBSTATE_WAIT_READ_NDEF_LEN_BLOCK"); 1096 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK: 1097 return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK"); 1098 case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK: 1099 return ("RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_NEXT_BLOCK"); 1100 case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT: 1101 return ("RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT"); 1102 default: 1103 return ("???? UNKNOWN SUBSTATE"); 1104 } 1105} 1106 1107#endif /* (BT_TRACE_VERBOSE == TRUE) */ 1108 1109#endif /* NFC_INCLUDED == TRUE*/ 1110