rw_t4t.c revision e9629bad30a9f478b336ab46b8e6e02f7f87af46
1/****************************************************************************** 2 * 3 * Copyright (C) 2010-2014 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 * 22 * This file contains the implementation for Type 4 tag in Reader/Writer 23 * mode. 24 * 25 ******************************************************************************/ 26#include <string.h> 27#include "nfc_target.h" 28#include "bt_types.h" 29#include "trace_api.h" 30 31#if (NFC_INCLUDED == TRUE) 32 33#include "nfc_api.h" 34#include "nfc_int.h" 35#include "rw_api.h" 36#include "rw_int.h" 37#include "tags_int.h" 38#include "gki.h" 39 40/* main state */ 41#define RW_T4T_STATE_NOT_ACTIVATED 0x00 /* T4T is not activated */ 42#define RW_T4T_STATE_IDLE 0x01 /* waiting for upper layer API */ 43#define RW_T4T_STATE_DETECT_NDEF 0x02 /* performing NDEF detection precedure */ 44#define RW_T4T_STATE_READ_NDEF 0x03 /* performing read NDEF procedure */ 45#define RW_T4T_STATE_UPDATE_NDEF 0x04 /* performing update NDEF procedure */ 46#define RW_T4T_STATE_PRESENCE_CHECK 0x05 /* checking presence of tag */ 47#define RW_T4T_STATE_SET_READ_ONLY 0x06 /* convert tag to read only */ 48 49/* sub state */ 50#define RW_T4T_SUBSTATE_WAIT_SELECT_APP 0x00 /* waiting for response of selecting AID */ 51#define RW_T4T_SUBSTATE_WAIT_SELECT_CC 0x01 /* waiting for response of selecting CC */ 52#define RW_T4T_SUBSTATE_WAIT_CC_FILE 0x02 /* waiting for response of reading CC */ 53#define RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE 0x03 /* waiting for response of selecting NDEF */ 54#define RW_T4T_SUBSTATE_WAIT_READ_NLEN 0x04 /* waiting for response of reading NLEN */ 55#define RW_T4T_SUBSTATE_WAIT_READ_RESP 0x05 /* waiting for response of reading file */ 56#define RW_T4T_SUBSTATE_WAIT_UPDATE_RESP 0x06 /* waiting for response of updating file */ 57#define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN 0x07 /* waiting for response of updating NLEN */ 58#define RW_T4T_SUBSTATE_WAIT_UPDATE_CC 0x08 /* waiting for response of updating CC */ 59 60#if (BT_TRACE_VERBOSE == TRUE) 61static char *rw_t4t_get_state_name (UINT8 state); 62static char *rw_t4t_get_sub_state_name (UINT8 sub_state); 63#endif 64 65static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu); 66static BOOLEAN rw_t4t_select_file (UINT16 file_id); 67static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue); 68static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len); 69static BOOLEAN rw_t4t_update_file (void); 70static BOOLEAN rw_t4t_update_cc_to_readonly (void); 71static BOOLEAN rw_t4t_select_application (UINT8 version); 72static BOOLEAN rw_t4t_validate_cc_file (void); 73static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2); 74static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu); 75static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu); 76static void rw_t4t_sm_update_ndef (BT_HDR *p_r_apdu); 77static void rw_t4t_sm_set_readonly (BT_HDR *p_r_apdu); 78static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data); 79 80/******************************************************************************* 81** 82** Function rw_t4t_send_to_lower 83** 84** Description Send C-APDU to lower layer 85** 86** Returns TRUE if success 87** 88*******************************************************************************/ 89static BOOLEAN rw_t4t_send_to_lower (BT_HDR *p_c_apdu) 90{ 91#if (BT_TRACE_PROTOCOL == TRUE) 92 DispRWT4Tags (p_c_apdu, FALSE); 93#endif 94 95 if (NFC_SendData (NFC_RF_CONN_ID, p_c_apdu) != NFC_STATUS_OK) 96 { 97 RW_TRACE_ERROR0 ("rw_t4t_send_to_lower (): NFC_SendData () failed"); 98 return FALSE; 99 } 100 101 nfc_start_quick_timer (&rw_cb.tcb.t4t.timer, NFC_TTYPE_RW_T4T_RESPONSE, 102 (RW_T4T_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000); 103 104 return TRUE; 105} 106 107/******************************************************************************* 108** 109** Function rw_t4t_select_file 110** 111** Description Send Select Command (by File ID) to peer 112** 113** Returns TRUE if success 114** 115*******************************************************************************/ 116static BOOLEAN rw_t4t_select_file (UINT16 file_id) 117{ 118 BT_HDR *p_c_apdu; 119 UINT8 *p; 120 121 RW_TRACE_DEBUG1 ("rw_t4t_select_file (): File ID:0x%04X", file_id); 122 123 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); 124 125 if (!p_c_apdu) 126 { 127 RW_TRACE_ERROR0 ("rw_t4t_select_file (): Cannot allocate buffer"); 128 return FALSE; 129 } 130 131 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 132 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 133 134 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); 135 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT); 136 UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_FILE_ID); 137 138 /* if current version mapping is V2.0 */ 139 if (rw_cb.tcb.t4t.version == T4T_VERSION_2_0) 140 { 141 UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_0CH); 142 } 143 else /* version 1.0 */ 144 { 145 UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H); 146 } 147 148 UINT8_TO_BE_STREAM (p, T4T_FILE_ID_SIZE); 149 UINT16_TO_BE_STREAM (p, file_id); 150 151 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE; 152 153 if (!rw_t4t_send_to_lower (p_c_apdu)) 154 { 155 return FALSE; 156 } 157 158 return TRUE; 159} 160 161/******************************************************************************* 162** 163** Function rw_t4t_read_file 164** 165** Description Send ReadBinary Command to peer 166** 167** Returns TRUE if success 168** 169*******************************************************************************/ 170static BOOLEAN rw_t4t_read_file (UINT16 offset, UINT16 length, BOOLEAN is_continue) 171{ 172 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 173 BT_HDR *p_c_apdu; 174 UINT8 *p; 175 176 RW_TRACE_DEBUG3 ("rw_t4t_read_file () offset:%d, length:%d, is_continue:%d, ", 177 offset, length, is_continue); 178 179 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); 180 181 if (!p_c_apdu) 182 { 183 RW_TRACE_ERROR0 ("rw_t4t_read_file (): Cannot allocate buffer"); 184 return FALSE; 185 } 186 187 /* if this is the first reading */ 188 if (is_continue == FALSE) 189 { 190 /* initialise starting offset and total length */ 191 /* these will be updated when receiving response */ 192 p_t4t->rw_offset = offset; 193 p_t4t->rw_length = length; 194 } 195 196 /* adjust reading length if payload is bigger than max size per single command */ 197 if (length > p_t4t->max_read_size) 198 { 199 length = (UINT8) (p_t4t->max_read_size); 200 } 201 202 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 203 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 204 205 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); 206 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_READ_BINARY); 207 UINT16_TO_BE_STREAM (p, offset); 208 UINT8_TO_BE_STREAM (p, length); /* Le */ 209 210 p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */ 211 212 if (!rw_t4t_send_to_lower (p_c_apdu)) 213 { 214 return FALSE; 215 } 216 217 return TRUE; 218} 219 220/******************************************************************************* 221** 222** Function rw_t4t_update_nlen 223** 224** Description Send UpdateBinary Command to update NLEN to peer 225** 226** Returns TRUE if success 227** 228*******************************************************************************/ 229static BOOLEAN rw_t4t_update_nlen (UINT16 ndef_len) 230{ 231 BT_HDR *p_c_apdu; 232 UINT8 *p; 233 234 RW_TRACE_DEBUG1 ("rw_t4t_update_nlen () NLEN:%d", ndef_len); 235 236 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); 237 238 if (!p_c_apdu) 239 { 240 RW_TRACE_ERROR0 ("rw_t4t_update_nlen (): Cannot allocate buffer"); 241 return FALSE; 242 } 243 244 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 245 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 246 247 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); 248 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY); 249 UINT16_TO_BE_STREAM (p, 0x0000); /* offset for NLEN */ 250 UINT8_TO_BE_STREAM (p, T4T_FILE_LENGTH_SIZE); 251 UINT16_TO_BE_STREAM (p, ndef_len); 252 253 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_LENGTH_SIZE; 254 255 if (!rw_t4t_send_to_lower (p_c_apdu)) 256 { 257 return FALSE; 258 } 259 260 return TRUE; 261} 262 263/******************************************************************************* 264** 265** Function rw_t4t_update_file 266** 267** Description Send UpdateBinary Command to peer 268** 269** Returns TRUE if success 270** 271*******************************************************************************/ 272static BOOLEAN rw_t4t_update_file (void) 273{ 274 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 275 BT_HDR *p_c_apdu; 276 UINT8 *p; 277 UINT16 length; 278 279 RW_TRACE_DEBUG2 ("rw_t4t_update_file () rw_offset:%d, rw_length:%d", 280 p_t4t->rw_offset, p_t4t->rw_length); 281 282 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); 283 284 if (!p_c_apdu) 285 { 286 RW_TRACE_ERROR0 ("rw_t4t_write_file (): Cannot allocate buffer"); 287 return FALSE; 288 } 289 290 /* try to send all of remaining data */ 291 length = p_t4t->rw_length; 292 293 /* adjust updating length if payload is bigger than max size per single command */ 294 if (length > p_t4t->max_update_size) 295 { 296 length = (UINT8) (p_t4t->max_update_size); 297 } 298 299 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 300 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 301 302 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); 303 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY); 304 UINT16_TO_BE_STREAM (p, p_t4t->rw_offset); 305 UINT8_TO_BE_STREAM (p, length); 306 307 memcpy (p, p_t4t->p_update_data, length); 308 309 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length; 310 311 if (!rw_t4t_send_to_lower (p_c_apdu)) 312 { 313 return FALSE; 314 } 315 316 /* adjust offset, length and pointer for remaining data */ 317 p_t4t->rw_offset += length; 318 p_t4t->rw_length -= length; 319 p_t4t->p_update_data += length; 320 321 return TRUE; 322} 323 324/******************************************************************************* 325** 326** Function rw_t4t_update_cc_to_readonly 327** 328** Description Send UpdateBinary Command for changing Write access 329** 330** Returns TRUE if success 331** 332*******************************************************************************/ 333static BOOLEAN rw_t4t_update_cc_to_readonly (void) 334{ 335 BT_HDR *p_c_apdu; 336 UINT8 *p; 337 338 RW_TRACE_DEBUG0 ("rw_t4t_update_cc_to_readonly (): Remove Write access from CC"); 339 340 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); 341 342 if (!p_c_apdu) 343 { 344 RW_TRACE_ERROR0 ("rw_t4t_update_cc_to_readonly (): Cannot allocate buffer"); 345 return FALSE; 346 } 347 348 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 349 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 350 351 /* Add Command Header */ 352 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); 353 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_UPDATE_BINARY); 354 UINT16_TO_BE_STREAM (p, (T4T_FC_TLV_OFFSET_IN_CC + T4T_FC_WRITE_ACCESS_OFFSET_IN_TLV)); /* Offset for Read Write access byte of CC */ 355 UINT8_TO_BE_STREAM (p, 1); /* Length of write access field in cc interms of bytes */ 356 357 /* Remove Write access */ 358 UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS); 359 360 361 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + 1; 362 363 if (!rw_t4t_send_to_lower (p_c_apdu)) 364 { 365 return FALSE; 366 } 367 368 return TRUE; 369} 370 371/******************************************************************************* 372** 373** Function rw_t4t_select_application 374** 375** Description Select Application 376** 377** NDEF Tag Application Select - C-APDU 378** 379** CLA INS P1 P2 Lc Data(AID) Le 380** V1.0: 00 A4 04 00 07 D2760000850100 - 381** V2.0: 00 A4 04 00 07 D2760000850101 00 382** 383** Returns TRUE if success 384** 385*******************************************************************************/ 386static BOOLEAN rw_t4t_select_application (UINT8 version) 387{ 388 BT_HDR *p_c_apdu; 389 UINT8 *p; 390 391 RW_TRACE_DEBUG1 ("rw_t4t_select_application () version:0x%X", version); 392 393 p_c_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_RW_POOL_ID); 394 395 if (!p_c_apdu) 396 { 397 RW_TRACE_ERROR0 ("rw_t4t_select_application (): Cannot allocate buffer"); 398 return FALSE; 399 } 400 401 p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 402 p = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 403 404 UINT8_TO_BE_STREAM (p, T4T_CMD_CLASS); 405 UINT8_TO_BE_STREAM (p, T4T_CMD_INS_SELECT); 406 UINT8_TO_BE_STREAM (p, T4T_CMD_P1_SELECT_BY_NAME); 407 UINT8_TO_BE_STREAM (p, T4T_CMD_P2_FIRST_OR_ONLY_00H); 408 409 if (version == T4T_VERSION_1_0) /* this is for V1.0 */ 410 { 411 UINT8_TO_BE_STREAM (p, T4T_V10_NDEF_TAG_AID_LEN); 412 413 memcpy (p, t4t_v10_ndef_tag_aid, T4T_V10_NDEF_TAG_AID_LEN); 414 415 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V10_NDEF_TAG_AID_LEN; 416 } 417 else if (version == T4T_VERSION_2_0) /* this is for V2.0 */ 418 { 419 UINT8_TO_BE_STREAM (p, T4T_V20_NDEF_TAG_AID_LEN); 420 421 memcpy (p, t4t_v20_ndef_tag_aid, T4T_V20_NDEF_TAG_AID_LEN); 422 p += T4T_V20_NDEF_TAG_AID_LEN; 423 424 UINT8_TO_BE_STREAM (p, 0x00); /* Le set to 0x00 */ 425 426 p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V20_NDEF_TAG_AID_LEN + 1; 427 } 428 else 429 { 430 return FALSE; 431 } 432 433 if (!rw_t4t_send_to_lower (p_c_apdu)) 434 { 435 return FALSE; 436 } 437 438 return TRUE; 439} 440 441/******************************************************************************* 442** 443** Function rw_t4t_validate_cc_file 444** 445** Description Validate CC file and mandatory NDEF TLV 446** 447** Returns TRUE if success 448** 449*******************************************************************************/ 450static BOOLEAN rw_t4t_validate_cc_file (void) 451{ 452 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 453 454 RW_TRACE_DEBUG0 ("rw_t4t_validate_cc_file ()"); 455 456 if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN) 457 { 458 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): CCLEN (%d) is too short", 459 p_t4t->cc_file.cclen); 460 return FALSE; 461 } 462 463 if (T4T_GET_MAJOR_VERSION (p_t4t->cc_file.version) != T4T_GET_MAJOR_VERSION (p_t4t->version)) 464 { 465 RW_TRACE_ERROR2 ("rw_t4t_validate_cc_file (): Peer version (0x%02X) is matched to ours (0x%02X)", 466 p_t4t->cc_file.version, p_t4t->version); 467 return FALSE; 468 } 469 470 if (p_t4t->cc_file.max_le < 0x000F) 471 { 472 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLe (%d) is too small", 473 p_t4t->cc_file.max_le); 474 return FALSE; 475 } 476 477 if (p_t4t->cc_file.max_lc < 0x0001) 478 { 479 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): MaxLc (%d) is too small", 480 p_t4t->cc_file.max_lc); 481 return FALSE; 482 } 483 484 if ( (p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID) 485 ||(p_t4t->cc_file.ndef_fc.file_id == 0xE102) 486 ||(p_t4t->cc_file.ndef_fc.file_id == 0xE103) 487 ||((p_t4t->cc_file.ndef_fc.file_id == 0x0000) && (p_t4t->cc_file.version == 0x20)) 488 ||(p_t4t->cc_file.ndef_fc.file_id == 0x3F00) 489 ||(p_t4t->cc_file.ndef_fc.file_id == 0x3FFF) 490 ||(p_t4t->cc_file.ndef_fc.file_id == 0xFFFF) ) 491 { 492 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): File ID (0x%04X) is invalid", 493 p_t4t->cc_file.ndef_fc.file_id); 494 return FALSE; 495 } 496 497 if ( (p_t4t->cc_file.ndef_fc.max_file_size < 0x0005) 498 ||(p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF) ) 499 { 500 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): max_file_size (%d) is reserved", 501 p_t4t->cc_file.ndef_fc.max_file_size); 502 return FALSE; 503 } 504 505 if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS) 506 { 507 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Read Access (0x%02X) is invalid", 508 p_t4t->cc_file.ndef_fc.read_access); 509 return FALSE; 510 } 511 512 if ( (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) 513 &&(p_t4t->cc_file.ndef_fc.write_access != T4T_FC_NO_WRITE_ACCESS) ) 514 { 515 RW_TRACE_ERROR1 ("rw_t4t_validate_cc_file (): Write Access (0x%02X) is invalid", 516 p_t4t->cc_file.ndef_fc.write_access); 517 return FALSE; 518 } 519 520 return TRUE; 521} 522 523/******************************************************************************* 524** 525** Function rw_t4t_handle_error 526** 527** Description notify error to application and clean up 528** 529** Returns none 530** 531*******************************************************************************/ 532static void rw_t4t_handle_error (tNFC_STATUS status, UINT8 sw1, UINT8 sw2) 533{ 534 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 535 tRW_DATA rw_data; 536 tRW_EVENT event; 537 538 RW_TRACE_DEBUG4 ("rw_t4t_handle_error (): status:0x%02X, sw1:0x%02X, sw2:0x%02X, state:0x%X", 539 status, sw1, sw2, p_t4t->state); 540 541 nfc_stop_quick_timer (&p_t4t->timer); 542 543 if (rw_cb.p_cback) 544 { 545 rw_data.status = status; 546 547 rw_data.t4t_sw.sw1 = sw1; 548 rw_data.t4t_sw.sw2 = sw2; 549 550 switch (p_t4t->state) 551 { 552 case RW_T4T_STATE_DETECT_NDEF: 553 rw_data.ndef.flags = RW_NDEF_FL_UNKNOWN; 554 event = RW_T4T_NDEF_DETECT_EVT; 555 break; 556 557 case RW_T4T_STATE_READ_NDEF: 558 event = RW_T4T_NDEF_READ_FAIL_EVT; 559 break; 560 561 case RW_T4T_STATE_UPDATE_NDEF: 562 event = RW_T4T_NDEF_UPDATE_FAIL_EVT; 563 break; 564 565 case RW_T4T_STATE_PRESENCE_CHECK: 566 event = RW_T4T_PRESENCE_CHECK_EVT; 567 rw_data.status = NFC_STATUS_FAILED; 568 break; 569 570 case RW_T4T_STATE_SET_READ_ONLY: 571 event = RW_T4T_SET_TO_RO_EVT; 572 break; 573 574 default: 575 event = RW_T4T_MAX_EVT; 576 break; 577 } 578 579 p_t4t->state = RW_T4T_STATE_IDLE; 580 581 if (event != RW_T4T_MAX_EVT) 582 { 583 (*(rw_cb.p_cback)) (event, &rw_data); 584 } 585 } 586 else 587 { 588 p_t4t->state = RW_T4T_STATE_IDLE; 589 } 590} 591 592/******************************************************************************* 593** 594** Function rw_t4t_sm_detect_ndef 595** 596** Description State machine for NDEF detection procedure 597** 598** Returns none 599** 600*******************************************************************************/ 601static void rw_t4t_sm_detect_ndef (BT_HDR *p_r_apdu) 602{ 603 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 604 UINT8 *p, type, length; 605 UINT16 status_words, nlen; 606 tRW_DATA rw_data; 607 608#if (BT_TRACE_VERBOSE == TRUE) 609 RW_TRACE_DEBUG2 ("rw_t4t_sm_detect_ndef (): sub_state:%s (%d)", 610 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state); 611#else 612 RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): sub_state=%d", p_t4t->sub_state); 613#endif 614 615 /* get status words */ 616 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 617 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE); 618 BE_STREAM_TO_UINT16 (status_words, p); 619 620 if (status_words != T4T_RSP_CMD_CMPLTED) 621 { 622 /* try V1.0 after failing of V2.0 */ 623 if ( (p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP) 624 &&(p_t4t->version == T4T_VERSION_2_0) ) 625 { 626 p_t4t->version = T4T_VERSION_1_0; 627 628 RW_TRACE_DEBUG1 ("rw_t4t_sm_detect_ndef (): retry with version=0x%02X", 629 p_t4t->version); 630 631 if (!rw_t4t_select_application (T4T_VERSION_1_0)) 632 { 633 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 634 } 635 return; 636 } 637 638 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED); 639 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1)); 640 return; 641 } 642 643 switch (p_t4t->sub_state) 644 { 645 case RW_T4T_SUBSTATE_WAIT_SELECT_APP: 646 647 /* NDEF Tag application has been selected then select CC file */ 648 if (!rw_t4t_select_file (T4T_CC_FILE_ID)) 649 { 650 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 651 } 652 else 653 { 654 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC; 655 } 656 break; 657 658 case RW_T4T_SUBSTATE_WAIT_SELECT_CC: 659 660 /* CC file has been selected then read mandatory part of CC file */ 661 if (!rw_t4t_read_file (0x00, T4T_CC_FILE_MIN_LEN, FALSE)) 662 { 663 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 664 } 665 else 666 { 667 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE; 668 } 669 break; 670 671 case RW_T4T_SUBSTATE_WAIT_CC_FILE: 672 673 /* CC file has been read then validate and select mandatory NDEF file */ 674 if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE) 675 { 676 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 677 678 BE_STREAM_TO_UINT16 (p_t4t->cc_file.cclen, p); 679 BE_STREAM_TO_UINT8 (p_t4t->cc_file.version, p); 680 BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_le, p); 681 BE_STREAM_TO_UINT16 (p_t4t->cc_file.max_lc, p); 682 683 BE_STREAM_TO_UINT8 (type, p); 684 BE_STREAM_TO_UINT8 (length, p); 685 686 if ( (type == T4T_NDEF_FILE_CONTROL_TYPE) 687 &&(length == T4T_FILE_CONTROL_LENGTH) ) 688 { 689 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.file_id, p); 690 BE_STREAM_TO_UINT16 (p_t4t->cc_file.ndef_fc.max_file_size, p); 691 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.read_access, p); 692 BE_STREAM_TO_UINT8 (p_t4t->cc_file.ndef_fc.write_access, p); 693 694#if (BT_TRACE_VERBOSE == TRUE) 695 RW_TRACE_DEBUG0 ("Capability Container (CC) file"); 696 RW_TRACE_DEBUG1 (" CCLEN: 0x%04X", p_t4t->cc_file.cclen); 697 RW_TRACE_DEBUG1 (" Version:0x%02X", p_t4t->cc_file.version); 698 RW_TRACE_DEBUG1 (" MaxLe: 0x%04X", p_t4t->cc_file.max_le); 699 RW_TRACE_DEBUG1 (" MaxLc: 0x%04X", p_t4t->cc_file.max_lc); 700 RW_TRACE_DEBUG0 (" NDEF File Control TLV"); 701 RW_TRACE_DEBUG1 (" FileID: 0x%04X", p_t4t->cc_file.ndef_fc.file_id); 702 RW_TRACE_DEBUG1 (" MaxFileSize: 0x%04X", p_t4t->cc_file.ndef_fc.max_file_size); 703 RW_TRACE_DEBUG1 (" ReadAccess: 0x%02X", p_t4t->cc_file.ndef_fc.read_access); 704 RW_TRACE_DEBUG1 (" WriteAccess: 0x%02X", p_t4t->cc_file.ndef_fc.write_access); 705#endif 706 707 if (rw_t4t_validate_cc_file ()) 708 { 709 if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id)) 710 { 711 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 712 } 713 else 714 { 715 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE; 716 } 717 break; 718 } 719 } 720 } 721 722 /* invalid response or CC file */ 723 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED); 724 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0); 725 break; 726 727 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE: 728 729 /* NDEF file has been selected then read the first 2 bytes (NLEN) */ 730 if (!rw_t4t_read_file (0, T4T_FILE_LENGTH_SIZE, FALSE)) 731 { 732 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 733 } 734 else 735 { 736 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN; 737 } 738 break; 739 740 case RW_T4T_SUBSTATE_WAIT_READ_NLEN: 741 742 /* NLEN has been read then report upper layer */ 743 if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE) 744 { 745 /* get length of NDEF */ 746 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 747 BE_STREAM_TO_UINT16 (nlen, p); 748 749 if (nlen <= p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE) 750 { 751 p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED; 752 753 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) 754 { 755 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY; 756 } 757 758 /* Get max bytes to read per command */ 759 if (p_t4t->cc_file.max_le >= RW_T4T_MAX_DATA_PER_READ) 760 { 761 p_t4t->max_read_size = RW_T4T_MAX_DATA_PER_READ; 762 } 763 else 764 { 765 p_t4t->max_read_size = p_t4t->cc_file.max_le; 766 } 767 768 /* Le: valid range is 0x01 to 0xFF */ 769 if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE) 770 { 771 p_t4t->max_read_size = T4T_MAX_LENGTH_LE; 772 } 773 774 /* Get max bytes to update per command */ 775 if (p_t4t->cc_file.max_lc >= RW_T4T_MAX_DATA_PER_WRITE) 776 { 777 p_t4t->max_update_size = RW_T4T_MAX_DATA_PER_WRITE; 778 } 779 else 780 { 781 p_t4t->max_update_size = p_t4t->cc_file.max_lc; 782 } 783 784 /* Lc: valid range is 0x01 to 0xFF */ 785 if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC) 786 { 787 p_t4t->max_update_size = T4T_MAX_LENGTH_LC; 788 } 789 790 p_t4t->ndef_length = nlen; 791 p_t4t->state = RW_T4T_STATE_IDLE; 792 793 if (rw_cb.p_cback) 794 { 795 rw_data.ndef.status = NFC_STATUS_OK; 796 rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP; 797 rw_data.ndef.max_size = (UINT32) (p_t4t->cc_file.ndef_fc.max_file_size - (UINT16) T4T_FILE_LENGTH_SIZE); 798 rw_data.ndef.cur_size = nlen; 799 rw_data.ndef.flags = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED; 800 if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) 801 { 802 rw_data.ndef.flags |= RW_NDEF_FL_READ_ONLY; 803 } 804 805 (*(rw_cb.p_cback)) (RW_T4T_NDEF_DETECT_EVT, &rw_data); 806 807 RW_TRACE_DEBUG0 ("rw_t4t_sm_detect_ndef (): Sent RW_T4T_NDEF_DETECT_EVT"); 808 } 809 } 810 else 811 { 812 /* NLEN should be less than max file size */ 813 RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): NLEN (%d) + 2 must be <= max file size (%d)", 814 nlen, p_t4t->cc_file.ndef_fc.max_file_size); 815 816 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED); 817 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0); 818 } 819 } 820 else 821 { 822 /* response payload size should be T4T_FILE_LENGTH_SIZE */ 823 RW_TRACE_ERROR2 ("rw_t4t_sm_detect_ndef (): Length (%d) of R-APDU must be %d", 824 p_r_apdu->len, T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE); 825 826 p_t4t->ndef_status &= ~ (RW_T4T_NDEF_STATUS_NDEF_DETECTED); 827 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0); 828 } 829 break; 830 831 default: 832 RW_TRACE_ERROR1 ("rw_t4t_sm_detect_ndef (): unknown sub_state=%d", p_t4t->sub_state); 833 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 834 break; 835 } 836} 837 838/******************************************************************************* 839** 840** Function rw_t4t_sm_read_ndef 841** 842** Description State machine for NDEF read procedure 843** 844** Returns none 845** 846*******************************************************************************/ 847static void rw_t4t_sm_read_ndef (BT_HDR *p_r_apdu) 848{ 849 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 850 UINT8 *p; 851 UINT16 status_words; 852 tRW_DATA rw_data; 853 854#if (BT_TRACE_VERBOSE == TRUE) 855 RW_TRACE_DEBUG2 ("rw_t4t_sm_read_ndef (): sub_state:%s (%d)", 856 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state); 857#else 858 RW_TRACE_DEBUG1 ("rw_t4t_sm_read_ndef (): sub_state=%d", p_t4t->sub_state); 859#endif 860 861 /* get status words */ 862 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 863 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE); 864 BE_STREAM_TO_UINT16 (status_words, p); 865 866 if (status_words != T4T_RSP_CMD_CMPLTED) 867 { 868 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1)); 869 GKI_freebuf (p_r_apdu); 870 return; 871 } 872 873 switch (p_t4t->sub_state) 874 { 875 case RW_T4T_SUBSTATE_WAIT_READ_RESP: 876 877 /* Read partial or complete data */ 878 p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE; 879 880 if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length)) 881 { 882 p_t4t->rw_length -= p_r_apdu->len; 883 p_t4t->rw_offset += p_r_apdu->len; 884 885 if (rw_cb.p_cback) 886 { 887 rw_data.data.status = NFC_STATUS_OK; 888 rw_data.data.p_data = p_r_apdu; 889 890 /* if need to read more data */ 891 if (p_t4t->rw_length > 0) 892 { 893 (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_EVT, &rw_data); 894 895 if (!rw_t4t_read_file (p_t4t->rw_offset, p_t4t->rw_length, TRUE)) 896 { 897 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 898 } 899 } 900 else 901 { 902 p_t4t->state = RW_T4T_STATE_IDLE; 903 904 (*(rw_cb.p_cback)) (RW_T4T_NDEF_READ_CPLT_EVT, &rw_data); 905 906 RW_TRACE_DEBUG0 ("rw_t4t_sm_read_ndef (): Sent RW_T4T_NDEF_READ_CPLT_EVT"); 907 908 } 909 910 p_r_apdu = NULL; 911 } 912 else 913 { 914 p_t4t->rw_length = 0; 915 p_t4t->state = RW_T4T_STATE_IDLE; 916 } 917 } 918 else 919 { 920 RW_TRACE_ERROR2 ("rw_t4t_sm_read_ndef (): invalid payload length (%d), rw_length (%d)", 921 p_r_apdu->len, p_t4t->rw_length); 922 rw_t4t_handle_error (NFC_STATUS_BAD_RESP, 0, 0); 923 } 924 break; 925 926 default: 927 RW_TRACE_ERROR1 ("rw_t4t_sm_read_ndef (): unknown sub_state = %d", p_t4t->sub_state); 928 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 929 break; 930 } 931 932 if (p_r_apdu) 933 GKI_freebuf (p_r_apdu); 934} 935 936/******************************************************************************* 937** 938** Function rw_t4t_sm_update_ndef 939** 940** Description State machine for NDEF update procedure 941** 942** Returns none 943** 944*******************************************************************************/ 945static void rw_t4t_sm_update_ndef (BT_HDR *p_r_apdu) 946{ 947 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 948 UINT8 *p; 949 UINT16 status_words; 950 tRW_DATA rw_data; 951 952#if (BT_TRACE_VERBOSE == TRUE) 953 RW_TRACE_DEBUG2 ("rw_t4t_sm_update_ndef (): sub_state:%s (%d)", 954 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state); 955#else 956 RW_TRACE_DEBUG1 ("rw_t4t_sm_update_ndef (): sub_state=%d", p_t4t->sub_state); 957#endif 958 959 /* Get status words */ 960 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 961 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE); 962 BE_STREAM_TO_UINT16 (status_words, p); 963 964 if (status_words != T4T_RSP_CMD_CMPLTED) 965 { 966 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1)); 967 return; 968 } 969 970 switch (p_t4t->sub_state) 971 { 972 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN: 973 974 /* NLEN has been updated */ 975 /* if need to update data */ 976 if (p_t4t->p_update_data) 977 { 978 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_RESP; 979 980 if (!rw_t4t_update_file ()) 981 { 982 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 983 p_t4t->p_update_data = NULL; 984 } 985 } 986 else 987 { 988 p_t4t->state = RW_T4T_STATE_IDLE; 989 990 /* just finished last step of updating (updating NLEN) */ 991 if (rw_cb.p_cback) 992 { 993 rw_data.status = NFC_STATUS_OK; 994 995 (*(rw_cb.p_cback)) (RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data); 996 RW_TRACE_DEBUG0 ("rw_t4t_sm_update_ndef (): Sent RW_T4T_NDEF_UPDATE_CPLT_EVT"); 997 } 998 } 999 break; 1000 1001 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP: 1002 1003 /* if updating is not completed */ 1004 if (p_t4t->rw_length > 0) 1005 { 1006 if (!rw_t4t_update_file ()) 1007 { 1008 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 1009 p_t4t->p_update_data = NULL; 1010 } 1011 } 1012 else 1013 { 1014 p_t4t->p_update_data = NULL; 1015 1016 /* update NLEN as last step of updating file */ 1017 if (!rw_t4t_update_nlen (p_t4t->ndef_length)) 1018 { 1019 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 1020 } 1021 else 1022 { 1023 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN; 1024 } 1025 } 1026 break; 1027 1028 default: 1029 RW_TRACE_ERROR1 ("rw_t4t_sm_update_ndef (): unknown sub_state = %d", p_t4t->sub_state); 1030 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 1031 break; 1032 } 1033} 1034 1035/******************************************************************************* 1036** 1037** Function rw_t4t_sm_set_readonly 1038** 1039** Description State machine for CC update procedure 1040** 1041** Returns none 1042** 1043*******************************************************************************/ 1044static void rw_t4t_sm_set_readonly (BT_HDR *p_r_apdu) 1045{ 1046 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 1047 UINT8 *p; 1048 UINT16 status_words; 1049 tRW_DATA rw_data; 1050 1051#if (BT_TRACE_VERBOSE == TRUE) 1052 RW_TRACE_DEBUG2 ("rw_t4t_sm_set_readonly (): sub_state:%s (%d)", 1053 rw_t4t_get_sub_state_name (p_t4t->sub_state), p_t4t->sub_state); 1054#else 1055 RW_TRACE_DEBUG1 ("rw_t4t_sm_set_readonly (): sub_state=%d", p_t4t->sub_state); 1056#endif 1057 1058 /* Get status words */ 1059 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 1060 p += (p_r_apdu->len - T4T_RSP_STATUS_WORDS_SIZE); 1061 BE_STREAM_TO_UINT16 (status_words, p); 1062 1063 if (status_words != T4T_RSP_CMD_CMPLTED) 1064 { 1065 rw_t4t_handle_error (NFC_STATUS_CMD_NOT_CMPLTD, *(p-2), *(p-1)); 1066 return; 1067 } 1068 1069 switch (p_t4t->sub_state) 1070 { 1071 case RW_T4T_SUBSTATE_WAIT_SELECT_CC: 1072 1073 /* CC file has been selected then update write access to read-only in CC file */ 1074 if (!rw_t4t_update_cc_to_readonly ()) 1075 { 1076 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 1077 } 1078 else 1079 { 1080 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_CC; 1081 } 1082 break; 1083 1084 case RW_T4T_SUBSTATE_WAIT_UPDATE_CC: 1085 /* CC Updated, Select NDEF File to allow NDEF operation */ 1086 p_t4t->cc_file.ndef_fc.write_access = T4T_FC_NO_WRITE_ACCESS; 1087 p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY; 1088 1089 if (!rw_t4t_select_file (p_t4t->cc_file.ndef_fc.file_id)) 1090 { 1091 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 1092 } 1093 else 1094 { 1095 p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE; 1096 } 1097 break; 1098 1099 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE: 1100 p_t4t->state = RW_T4T_STATE_IDLE; 1101 /* just finished last step of configuring tag read only (Selecting NDEF file CC) */ 1102 if (rw_cb.p_cback) 1103 { 1104 rw_data.status = NFC_STATUS_OK; 1105 1106 RW_TRACE_DEBUG0 ("rw_t4t_sm_set_readonly (): Sent RW_T4T_SET_TO_RO_EVT"); 1107 (*(rw_cb.p_cback)) (RW_T4T_SET_TO_RO_EVT, &rw_data); 1108 } 1109 break; 1110 1111 default: 1112 RW_TRACE_ERROR1 ("rw_t4t_sm_set_readonly (): unknown sub_state = %d", p_t4t->sub_state); 1113 rw_t4t_handle_error (NFC_STATUS_FAILED, 0, 0); 1114 break; 1115 } 1116} 1117 1118/******************************************************************************* 1119** 1120** Function rw_t4t_process_timeout 1121** 1122** Description process timeout event 1123** 1124** Returns none 1125** 1126*******************************************************************************/ 1127void rw_t4t_process_timeout (TIMER_LIST_ENT *p_tle) 1128{ 1129 RW_TRACE_DEBUG1 ("rw_t4t_process_timeout () event=%d", p_tle->event); 1130 1131 if (p_tle->event == NFC_TTYPE_RW_T4T_RESPONSE) 1132 { 1133 rw_t4t_handle_error (NFC_STATUS_TIMEOUT, 0, 0); 1134 } 1135 else 1136 { 1137 RW_TRACE_ERROR1 ("rw_t4t_process_timeout () unknown event=%d", p_tle->event); 1138 } 1139} 1140 1141/******************************************************************************* 1142** 1143** Function rw_t4t_data_cback 1144** 1145** Description This callback function receives the data from NFCC. 1146** 1147** Returns none 1148** 1149*******************************************************************************/ 1150static void rw_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) 1151{ 1152 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 1153 BT_HDR *p_r_apdu; 1154 tRW_DATA rw_data; 1155 1156#if (BT_TRACE_VERBOSE == TRUE) 1157 UINT8 begin_state = p_t4t->state; 1158#endif 1159 1160 RW_TRACE_DEBUG1 ("rw_t4t_data_cback () event = 0x%X", event); 1161 nfc_stop_quick_timer (&p_t4t->timer); 1162 1163 switch (event) 1164 { 1165 case NFC_DEACTIVATE_CEVT: 1166 NFC_SetStaticRfCback (NULL); 1167 p_t4t->state = RW_T4T_STATE_NOT_ACTIVATED; 1168 return; 1169 1170 case NFC_ERROR_CEVT: 1171 rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data); 1172 1173 if (p_t4t->state != RW_T4T_STATE_IDLE) 1174 { 1175 rw_t4t_handle_error (rw_data.status, 0, 0); 1176 } 1177 else 1178 { 1179 (*(rw_cb.p_cback)) (RW_T4T_INTF_ERROR_EVT, &rw_data); 1180 } 1181 return; 1182 1183 case NFC_DATA_CEVT: 1184 p_r_apdu = (BT_HDR *) p_data->data.p_data; 1185 break; 1186 1187 default: 1188 return; 1189 } 1190 1191#if (BT_TRACE_PROTOCOL == TRUE) 1192 DispRWT4Tags (p_r_apdu, TRUE); 1193#endif 1194 1195#if (BT_TRACE_VERBOSE == TRUE) 1196 RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>", 1197 rw_t4t_get_state_name (p_t4t->state), p_t4t->state); 1198#else 1199 RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state); 1200#endif 1201 1202 switch (p_t4t->state) 1203 { 1204 case RW_T4T_STATE_IDLE: 1205 /* Unexpected R-APDU, it should be raw frame response */ 1206 /* forward to upper layer without parsing */ 1207 if (rw_cb.p_cback) 1208 { 1209 rw_data.raw_frame.status = NFC_STATUS_OK; 1210 rw_data.raw_frame.p_data = p_r_apdu; 1211 (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data); 1212 p_r_apdu = NULL; 1213 } 1214 else 1215 { 1216 GKI_freebuf (p_r_apdu); 1217 } 1218 break; 1219 case RW_T4T_STATE_DETECT_NDEF: 1220 rw_t4t_sm_detect_ndef (p_r_apdu); 1221 GKI_freebuf (p_r_apdu); 1222 break; 1223 case RW_T4T_STATE_READ_NDEF: 1224 rw_t4t_sm_read_ndef (p_r_apdu); 1225 /* p_r_apdu may send upper lyaer */ 1226 break; 1227 case RW_T4T_STATE_UPDATE_NDEF: 1228 rw_t4t_sm_update_ndef (p_r_apdu); 1229 GKI_freebuf (p_r_apdu); 1230 break; 1231 case RW_T4T_STATE_PRESENCE_CHECK: 1232 /* if any response, send presence check with ok */ 1233 rw_data.status = NFC_STATUS_OK; 1234 p_t4t->state = RW_T4T_STATE_IDLE; 1235 (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data); 1236 GKI_freebuf (p_r_apdu); 1237 break; 1238 case RW_T4T_STATE_SET_READ_ONLY: 1239 rw_t4t_sm_set_readonly (p_r_apdu); 1240 GKI_freebuf (p_r_apdu); 1241 break; 1242 default: 1243 RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state); 1244 GKI_freebuf (p_r_apdu); 1245 break; 1246 } 1247 1248#if (BT_TRACE_VERBOSE == TRUE) 1249 if (begin_state != p_t4t->state) 1250 { 1251 RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>", 1252 rw_t4t_get_state_name (begin_state), 1253 rw_t4t_get_state_name (p_t4t->state)); 1254 } 1255#endif 1256} 1257 1258 1259/******************************************************************************* 1260** 1261** Function rw_t4t_select 1262** 1263** Description Initialise T4T 1264** 1265** Returns NFC_STATUS_OK if success 1266** 1267*******************************************************************************/ 1268tNFC_STATUS rw_t4t_select (void) 1269{ 1270 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 1271 1272 RW_TRACE_DEBUG0 ("rw_t4t_select ()"); 1273 1274 NFC_SetStaticRfCback (rw_t4t_data_cback); 1275 1276 p_t4t->state = RW_T4T_STATE_IDLE; 1277 p_t4t->version = T4T_MY_VERSION; 1278 1279 /* set it min of max R-APDU data size before reading CC file */ 1280 p_t4t->cc_file.max_le = T4T_MIN_MLE; 1281 1282 /* These will be udated during NDEF detection */ 1283 p_t4t->max_read_size = T4T_MAX_LENGTH_LE; 1284 p_t4t->max_update_size = T4T_MAX_LENGTH_LC; 1285 1286 return NFC_STATUS_OK; 1287} 1288 1289/******************************************************************************* 1290** 1291** Function RW_T4tDetectNDef 1292** 1293** Description This function performs NDEF detection procedure 1294** 1295** RW_T4T_NDEF_DETECT_EVT will be returned 1296** 1297** Returns NFC_STATUS_OK if success 1298** NFC_STATUS_FAILED if T4T is busy or other error 1299** 1300*******************************************************************************/ 1301tNFC_STATUS RW_T4tDetectNDef (void) 1302{ 1303 RW_TRACE_API0 ("RW_T4tDetectNDef ()"); 1304 1305 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1306 { 1307 RW_TRACE_ERROR1 ("RW_T4tDetectNDef ():Unable to start command at state (0x%X)", 1308 rw_cb.tcb.t4t.state); 1309 return NFC_STATUS_FAILED; 1310 } 1311 1312 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1313 { 1314 /* NDEF Tag application has been selected then select CC file */ 1315 if (!rw_t4t_select_file (T4T_CC_FILE_ID)) 1316 { 1317 return NFC_STATUS_FAILED; 1318 } 1319 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC; 1320 } 1321 else 1322 { 1323 /* Select NDEF Tag Application */ 1324 if (!rw_t4t_select_application (rw_cb.tcb.t4t.version)) 1325 { 1326 return NFC_STATUS_FAILED; 1327 } 1328 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP; 1329 } 1330 1331 rw_cb.tcb.t4t.state = RW_T4T_STATE_DETECT_NDEF; 1332 1333 return NFC_STATUS_OK; 1334} 1335 1336/******************************************************************************* 1337** 1338** Function RW_T4tReadNDef 1339** 1340** Description This function performs NDEF read procedure 1341** Note: RW_T4tDetectNDef () must be called before using this 1342** 1343** The following event will be returned 1344** RW_T4T_NDEF_READ_EVT for each segmented NDEF message 1345** RW_T4T_NDEF_READ_CPLT_EVT for the last segment or complete NDEF 1346** RW_T4T_NDEF_READ_FAIL_EVT for failure 1347** 1348** Returns NFC_STATUS_OK if success 1349** NFC_STATUS_FAILED if T4T is busy or other error 1350** 1351*******************************************************************************/ 1352tNFC_STATUS RW_T4tReadNDef (void) 1353{ 1354 RW_TRACE_API0 ("RW_T4tReadNDef ()"); 1355 1356 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1357 { 1358 RW_TRACE_ERROR1 ("RW_T4tReadNDef ():Unable to start command at state (0x%X)", 1359 rw_cb.tcb.t4t.state); 1360 return NFC_STATUS_FAILED; 1361 } 1362 1363 /* if NDEF has been detected */ 1364 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1365 { 1366 /* start reading NDEF */ 1367 if (!rw_t4t_read_file (T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length, FALSE)) 1368 { 1369 return NFC_STATUS_FAILED; 1370 } 1371 1372 rw_cb.tcb.t4t.state = RW_T4T_STATE_READ_NDEF; 1373 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP; 1374 1375 return NFC_STATUS_OK; 1376 } 1377 else 1378 { 1379 RW_TRACE_ERROR0 ("RW_T4tReadNDef ():No NDEF detected"); 1380 return NFC_STATUS_FAILED; 1381 } 1382} 1383 1384/******************************************************************************* 1385** 1386** Function RW_T4tUpdateNDef 1387** 1388** Description This function performs NDEF update procedure 1389** Note: RW_T4tDetectNDef () must be called before using this 1390** Updating data must not be removed until returning event 1391** 1392** The following event will be returned 1393** RW_T4T_NDEF_UPDATE_CPLT_EVT for complete 1394** RW_T4T_NDEF_UPDATE_FAIL_EVT for failure 1395** 1396** Returns NFC_STATUS_OK if success 1397** NFC_STATUS_FAILED if T4T is busy or other error 1398** 1399*******************************************************************************/ 1400tNFC_STATUS RW_T4tUpdateNDef (UINT16 length, UINT8 *p_data) 1401{ 1402 RW_TRACE_API1 ("RW_T4tUpdateNDef () length:%d", length); 1403 1404 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1405 { 1406 RW_TRACE_ERROR1 ("RW_T4tUpdateNDef ():Unable to start command at state (0x%X)", 1407 rw_cb.tcb.t4t.state); 1408 return NFC_STATUS_FAILED; 1409 } 1410 1411 /* if NDEF has been detected */ 1412 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1413 { 1414 /* if read-only */ 1415 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) 1416 { 1417 RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():NDEF is read-only"); 1418 return NFC_STATUS_FAILED; 1419 } 1420 1421 if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size < length + T4T_FILE_LENGTH_SIZE) 1422 { 1423 RW_TRACE_ERROR2 ("RW_T4tUpdateNDef ():data (%d bytes) plus NLEN is more than max file size (%d)", 1424 length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size); 1425 return NFC_STATUS_FAILED; 1426 } 1427 1428 /* store NDEF length and data */ 1429 rw_cb.tcb.t4t.ndef_length = length; 1430 rw_cb.tcb.t4t.p_update_data = p_data; 1431 1432 rw_cb.tcb.t4t.rw_offset = T4T_FILE_LENGTH_SIZE; 1433 rw_cb.tcb.t4t.rw_length = length; 1434 1435 /* set NLEN to 0x0000 for the first step */ 1436 if (!rw_t4t_update_nlen (0x0000)) 1437 { 1438 return NFC_STATUS_FAILED; 1439 } 1440 1441 rw_cb.tcb.t4t.state = RW_T4T_STATE_UPDATE_NDEF; 1442 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN; 1443 1444 return NFC_STATUS_OK; 1445 } 1446 else 1447 { 1448 RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():No NDEF detected"); 1449 return NFC_STATUS_FAILED; 1450 } 1451} 1452 1453/***************************************************************************** 1454** 1455** Function RW_T4tPresenceCheck 1456** 1457** Description 1458** Check if the tag is still in the field. 1459** 1460** The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence 1461** or non-presence. 1462** 1463** Returns 1464** NFC_STATUS_OK, if raw data frame sent 1465** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation 1466** NFC_STATUS_FAILED: other error 1467** 1468*****************************************************************************/ 1469tNFC_STATUS RW_T4tPresenceCheck (void) 1470{ 1471 tNFC_STATUS retval = NFC_STATUS_OK; 1472 tRW_DATA evt_data; 1473 1474 RW_TRACE_API0 ("RW_T4tPresenceCheck ()"); 1475 1476 /* If RW_SelectTagType was not called (no conn_callback) return failure */ 1477 if (!rw_cb.p_cback) 1478 { 1479 retval = NFC_STATUS_FAILED; 1480 } 1481 /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with NFC_STATUS_FAILED */ 1482 else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED) 1483 { 1484 evt_data.status = NFC_STATUS_FAILED; 1485 (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data); 1486 } 1487 /* If command is pending, assume tag is still present */ 1488 else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1489 { 1490 evt_data.status = NFC_STATUS_OK; 1491 (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data); 1492 } 1493 else 1494 { 1495 if (rw_t4t_read_file (0, 1, FALSE)) 1496 { 1497 rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK; 1498 } 1499 else 1500 { 1501 retval = NFC_STATUS_NO_BUFFERS; 1502 } 1503 } 1504 1505 return (retval); 1506} 1507 1508/***************************************************************************** 1509** 1510** Function RW_T4tSetNDefReadOnly 1511** 1512** Description This function performs NDEF read-only procedure 1513** Note: RW_T4tDetectNDef() must be called before using this 1514** 1515** The RW_T4T_SET_TO_RO_EVT event will be returned. 1516** 1517** Returns NFC_STATUS_OK if success 1518** NFC_STATUS_FAILED if T4T is busy or other error 1519** 1520*****************************************************************************/ 1521tNFC_STATUS RW_T4tSetNDefReadOnly (void) 1522{ 1523 tNFC_STATUS retval = NFC_STATUS_OK; 1524 tRW_DATA evt_data; 1525 1526 RW_TRACE_API0 ("RW_T4tSetNDefReadOnly ()"); 1527 1528 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1529 { 1530 RW_TRACE_ERROR1 ("RW_T4tSetNDefReadOnly ():Unable to start command at state (0x%X)", 1531 rw_cb.tcb.t4t.state); 1532 return NFC_STATUS_FAILED; 1533 } 1534 1535 /* if NDEF has been detected */ 1536 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1537 { 1538 /* if read-only */ 1539 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) 1540 { 1541 RW_TRACE_API0 ("RW_T4tSetNDefReadOnly (): NDEF is already read-only"); 1542 1543 evt_data.status = NFC_STATUS_OK; 1544 (*rw_cb.p_cback) (RW_T4T_SET_TO_RO_EVT, &evt_data); 1545 return (retval); 1546 } 1547 1548 /* NDEF Tag application has been selected then select CC file */ 1549 if (!rw_t4t_select_file (T4T_CC_FILE_ID)) 1550 { 1551 return NFC_STATUS_FAILED; 1552 } 1553 1554 rw_cb.tcb.t4t.state = RW_T4T_STATE_SET_READ_ONLY; 1555 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC; 1556 1557 return NFC_STATUS_OK; 1558 } 1559 else 1560 { 1561 RW_TRACE_ERROR0 ("RW_T4tSetNDefReadOnly ():No NDEF detected"); 1562 return NFC_STATUS_FAILED; 1563 } 1564 return (retval); 1565} 1566 1567#if (BT_TRACE_VERBOSE == TRUE) 1568/******************************************************************************* 1569** 1570** Function rw_t4t_get_state_name 1571** 1572** Description This function returns the state name. 1573** 1574** NOTE conditionally compiled to save memory. 1575** 1576** Returns pointer to the name 1577** 1578*******************************************************************************/ 1579static char *rw_t4t_get_state_name (UINT8 state) 1580{ 1581 switch (state) 1582 { 1583 case RW_T4T_STATE_NOT_ACTIVATED: 1584 return ("NOT_ACTIVATED"); 1585 case RW_T4T_STATE_IDLE: 1586 return ("IDLE"); 1587 case RW_T4T_STATE_DETECT_NDEF: 1588 return ("NDEF_DETECTION"); 1589 case RW_T4T_STATE_READ_NDEF: 1590 return ("READ_NDEF"); 1591 case RW_T4T_STATE_UPDATE_NDEF: 1592 return ("UPDATE_NDEF"); 1593 case RW_T4T_STATE_PRESENCE_CHECK: 1594 return ("PRESENCE_CHECK"); 1595 case RW_T4T_STATE_SET_READ_ONLY: 1596 return ("SET_READ_ONLY"); 1597 1598 default: 1599 return ("???? UNKNOWN STATE"); 1600 } 1601} 1602 1603/******************************************************************************* 1604** 1605** Function rw_t4t_get_sub_state_name 1606** 1607** Description This function returns the sub_state name. 1608** 1609** NOTE conditionally compiled to save memory. 1610** 1611** Returns pointer to the name 1612** 1613*******************************************************************************/ 1614static char *rw_t4t_get_sub_state_name (UINT8 sub_state) 1615{ 1616 switch (sub_state) 1617 { 1618 case RW_T4T_SUBSTATE_WAIT_SELECT_APP: 1619 return ("WAIT_SELECT_APP"); 1620 case RW_T4T_SUBSTATE_WAIT_SELECT_CC: 1621 return ("WAIT_SELECT_CC"); 1622 case RW_T4T_SUBSTATE_WAIT_CC_FILE: 1623 return ("WAIT_CC_FILE"); 1624 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE: 1625 return ("WAIT_SELECT_NDEF_FILE"); 1626 case RW_T4T_SUBSTATE_WAIT_READ_NLEN: 1627 return ("WAIT_READ_NLEN"); 1628 1629 case RW_T4T_SUBSTATE_WAIT_READ_RESP: 1630 return ("WAIT_READ_RESP"); 1631 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP: 1632 return ("WAIT_UPDATE_RESP"); 1633 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN: 1634 return ("WAIT_UPDATE_NLEN"); 1635 default: 1636 return ("???? UNKNOWN SUBSTATE"); 1637 } 1638} 1639#endif 1640 1641#endif /* (NFC_INCLUDED == TRUE) */ 1642