rw_t4t.c revision 5c65c3a0f42e174e47fecd4e569606003217ff4e
1/****************************************************************************** 2 * 3 * Copyright (C) 2010-2013 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:0%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 = (BT_HDR *) p_data->data.p_data; 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 if (p_t4t->state == RW_T4T_STATE_PRESENCE_CHECK) 1172 { 1173 p_t4t->state = RW_T4T_STATE_IDLE; 1174 rw_data.status = NFC_STATUS_FAILED; 1175 (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data); 1176 } 1177 else 1178 { 1179 p_t4t->state = RW_T4T_STATE_IDLE; 1180 rw_data.status = (tNFC_STATUS) (*(UINT8*) p_data); 1181 (*(rw_cb.p_cback)) (RW_T4T_INTF_ERROR_EVT, &rw_data); 1182 } 1183 return; 1184 1185 case NFC_DATA_CEVT: 1186 break; 1187 1188 default: 1189 return; 1190 } 1191 1192#if (BT_TRACE_PROTOCOL == TRUE) 1193 DispRWT4Tags (p_r_apdu, TRUE); 1194#endif 1195 1196#if (BT_TRACE_VERBOSE == TRUE) 1197 RW_TRACE_DEBUG2 ("RW T4T state: <%s (%d)>", 1198 rw_t4t_get_state_name (p_t4t->state), p_t4t->state); 1199#else 1200 RW_TRACE_DEBUG1 ("RW T4T state: %d", p_t4t->state); 1201#endif 1202 1203 switch (p_t4t->state) 1204 { 1205 case RW_T4T_STATE_IDLE: 1206 /* Unexpected R-APDU, it should be raw frame response */ 1207 /* forward to upper layer without parsing */ 1208 if (rw_cb.p_cback) 1209 { 1210 rw_data.raw_frame.status = NFC_STATUS_OK; 1211 rw_data.raw_frame.p_data = p_r_apdu; 1212 (*(rw_cb.p_cback)) (RW_T4T_RAW_FRAME_EVT, &rw_data); 1213 p_r_apdu = NULL; 1214 } 1215 else 1216 { 1217 GKI_freebuf (p_r_apdu); 1218 } 1219 break; 1220 case RW_T4T_STATE_DETECT_NDEF: 1221 rw_t4t_sm_detect_ndef (p_r_apdu); 1222 GKI_freebuf (p_r_apdu); 1223 break; 1224 case RW_T4T_STATE_READ_NDEF: 1225 rw_t4t_sm_read_ndef (p_r_apdu); 1226 /* p_r_apdu may send upper lyaer */ 1227 break; 1228 case RW_T4T_STATE_UPDATE_NDEF: 1229 rw_t4t_sm_update_ndef (p_r_apdu); 1230 GKI_freebuf (p_r_apdu); 1231 break; 1232 case RW_T4T_STATE_PRESENCE_CHECK: 1233 /* if any response, send presence check with ok */ 1234 rw_data.status = NFC_STATUS_OK; 1235 p_t4t->state = RW_T4T_STATE_IDLE; 1236 (*(rw_cb.p_cback)) (RW_T4T_PRESENCE_CHECK_EVT, &rw_data); 1237 GKI_freebuf (p_r_apdu); 1238 break; 1239 case RW_T4T_STATE_SET_READ_ONLY: 1240 rw_t4t_sm_set_readonly (p_r_apdu); 1241 GKI_freebuf (p_r_apdu); 1242 break; 1243 default: 1244 RW_TRACE_ERROR1 ("rw_t4t_data_cback (): invalid state=%d", p_t4t->state); 1245 GKI_freebuf (p_r_apdu); 1246 break; 1247 } 1248 1249#if (BT_TRACE_VERBOSE == TRUE) 1250 if (begin_state != p_t4t->state) 1251 { 1252 RW_TRACE_DEBUG2 ("RW T4T state changed:<%s> -> <%s>", 1253 rw_t4t_get_state_name (begin_state), 1254 rw_t4t_get_state_name (p_t4t->state)); 1255 } 1256#endif 1257} 1258 1259 1260/******************************************************************************* 1261** 1262** Function rw_t4t_select 1263** 1264** Description Initialise T4T 1265** 1266** Returns NFC_STATUS_OK if success 1267** 1268*******************************************************************************/ 1269tNFC_STATUS rw_t4t_select (void) 1270{ 1271 tRW_T4T_CB *p_t4t = &rw_cb.tcb.t4t; 1272 1273 RW_TRACE_DEBUG0 ("rw_t4t_select ()"); 1274 1275 NFC_SetStaticRfCback (rw_t4t_data_cback); 1276 1277 p_t4t->state = RW_T4T_STATE_IDLE; 1278 p_t4t->version = T4T_MY_VERSION; 1279 1280 /* set it min of max R-APDU data size before reading CC file */ 1281 p_t4t->cc_file.max_le = T4T_MIN_MLE; 1282 1283 /* These will be udated during NDEF detection */ 1284 p_t4t->max_read_size = T4T_MAX_LENGTH_LE; 1285 p_t4t->max_update_size = T4T_MAX_LENGTH_LC; 1286 1287 return NFC_STATUS_OK; 1288} 1289 1290/******************************************************************************* 1291** 1292** Function RW_T4tDetectNDef 1293** 1294** Description This function performs NDEF detection procedure 1295** 1296** RW_T4T_NDEF_DETECT_EVT will be returned 1297** 1298** Returns NFC_STATUS_OK if success 1299** NFC_STATUS_FAILED if T4T is busy or other error 1300** 1301*******************************************************************************/ 1302tNFC_STATUS RW_T4tDetectNDef (void) 1303{ 1304 RW_TRACE_API0 ("RW_T4tDetectNDef ()"); 1305 1306 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1307 { 1308 RW_TRACE_ERROR1 ("RW_T4tDetectNDef ():Unable to start command at state (0x%X)", 1309 rw_cb.tcb.t4t.state); 1310 return NFC_STATUS_FAILED; 1311 } 1312 1313 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1314 { 1315 /* NDEF Tag application has been selected then select CC file */ 1316 if (!rw_t4t_select_file (T4T_CC_FILE_ID)) 1317 { 1318 return NFC_STATUS_FAILED; 1319 } 1320 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC; 1321 } 1322 else 1323 { 1324 /* Select NDEF Tag Application */ 1325 if (!rw_t4t_select_application (rw_cb.tcb.t4t.version)) 1326 { 1327 return NFC_STATUS_FAILED; 1328 } 1329 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_APP; 1330 } 1331 1332 rw_cb.tcb.t4t.state = RW_T4T_STATE_DETECT_NDEF; 1333 1334 return NFC_STATUS_OK; 1335} 1336 1337/******************************************************************************* 1338** 1339** Function RW_T4tReadNDef 1340** 1341** Description This function performs NDEF read procedure 1342** Note: RW_T4tDetectNDef () must be called before using this 1343** 1344** The following event will be returned 1345** RW_T4T_NDEF_READ_EVT for each segmented NDEF message 1346** RW_T4T_NDEF_READ_CPLT_EVT for the last segment or complete NDEF 1347** RW_T4T_NDEF_READ_FAIL_EVT for failure 1348** 1349** Returns NFC_STATUS_OK if success 1350** NFC_STATUS_FAILED if T4T is busy or other error 1351** 1352*******************************************************************************/ 1353tNFC_STATUS RW_T4tReadNDef (void) 1354{ 1355 RW_TRACE_API0 ("RW_T4tReadNDef ()"); 1356 1357 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1358 { 1359 RW_TRACE_ERROR1 ("RW_T4tReadNDef ():Unable to start command at state (0x%X)", 1360 rw_cb.tcb.t4t.state); 1361 return NFC_STATUS_FAILED; 1362 } 1363 1364 /* if NDEF has been detected */ 1365 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1366 { 1367 /* start reading NDEF */ 1368 if (!rw_t4t_read_file (T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length, FALSE)) 1369 { 1370 return NFC_STATUS_FAILED; 1371 } 1372 1373 rw_cb.tcb.t4t.state = RW_T4T_STATE_READ_NDEF; 1374 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_READ_RESP; 1375 1376 return NFC_STATUS_OK; 1377 } 1378 else 1379 { 1380 RW_TRACE_ERROR0 ("RW_T4tReadNDef ():No NDEF detected"); 1381 return NFC_STATUS_FAILED; 1382 } 1383} 1384 1385/******************************************************************************* 1386** 1387** Function RW_T4tUpdateNDef 1388** 1389** Description This function performs NDEF update procedure 1390** Note: RW_T4tDetectNDef () must be called before using this 1391** Updating data must not be removed until returning event 1392** 1393** The following event will be returned 1394** RW_T4T_NDEF_UPDATE_CPLT_EVT for complete 1395** RW_T4T_NDEF_UPDATE_FAIL_EVT for failure 1396** 1397** Returns NFC_STATUS_OK if success 1398** NFC_STATUS_FAILED if T4T is busy or other error 1399** 1400*******************************************************************************/ 1401tNFC_STATUS RW_T4tUpdateNDef (UINT16 length, UINT8 *p_data) 1402{ 1403 RW_TRACE_API1 ("RW_T4tUpdateNDef () length:%d", length); 1404 1405 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1406 { 1407 RW_TRACE_ERROR1 ("RW_T4tUpdateNDef ():Unable to start command at state (0x%X)", 1408 rw_cb.tcb.t4t.state); 1409 return NFC_STATUS_FAILED; 1410 } 1411 1412 /* if NDEF has been detected */ 1413 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1414 { 1415 /* if read-only */ 1416 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) 1417 { 1418 RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():NDEF is read-only"); 1419 return NFC_STATUS_FAILED; 1420 } 1421 1422 if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size < length + T4T_FILE_LENGTH_SIZE) 1423 { 1424 RW_TRACE_ERROR2 ("RW_T4tUpdateNDef ():data (%d bytes) plus NLEN is more than max file size (%d)", 1425 length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size); 1426 return NFC_STATUS_FAILED; 1427 } 1428 1429 /* store NDEF length and data */ 1430 rw_cb.tcb.t4t.ndef_length = length; 1431 rw_cb.tcb.t4t.p_update_data = p_data; 1432 1433 rw_cb.tcb.t4t.rw_offset = T4T_FILE_LENGTH_SIZE; 1434 rw_cb.tcb.t4t.rw_length = length; 1435 1436 /* set NLEN to 0x0000 for the first step */ 1437 if (!rw_t4t_update_nlen (0x0000)) 1438 { 1439 return NFC_STATUS_FAILED; 1440 } 1441 1442 rw_cb.tcb.t4t.state = RW_T4T_STATE_UPDATE_NDEF; 1443 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN; 1444 1445 return NFC_STATUS_OK; 1446 } 1447 else 1448 { 1449 RW_TRACE_ERROR0 ("RW_T4tUpdateNDef ():No NDEF detected"); 1450 return NFC_STATUS_FAILED; 1451 } 1452} 1453 1454/***************************************************************************** 1455** 1456** Function RW_T4tPresenceCheck 1457** 1458** Description 1459** Check if the tag is still in the field. 1460** 1461** The RW_T4T_PRESENCE_CHECK_EVT w/ status is used to indicate presence 1462** or non-presence. 1463** 1464** Returns 1465** NFC_STATUS_OK, if raw data frame sent 1466** NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this operation 1467** NFC_STATUS_FAILED: other error 1468** 1469*****************************************************************************/ 1470tNFC_STATUS RW_T4tPresenceCheck (void) 1471{ 1472 tNFC_STATUS retval = NFC_STATUS_OK; 1473 tRW_DATA evt_data; 1474 1475 RW_TRACE_API0 ("RW_T4tPresenceCheck ()"); 1476 1477 /* If RW_SelectTagType was not called (no conn_callback) return failure */ 1478 if (!rw_cb.p_cback) 1479 { 1480 retval = NFC_STATUS_FAILED; 1481 } 1482 /* If we are not activated, then RW_T4T_PRESENCE_CHECK_EVT with NFC_STATUS_FAILED */ 1483 else if (rw_cb.tcb.t4t.state == RW_T4T_STATE_NOT_ACTIVATED) 1484 { 1485 evt_data.status = NFC_STATUS_FAILED; 1486 (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data); 1487 } 1488 /* If command is pending, assume tag is still present */ 1489 else if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1490 { 1491 evt_data.status = NFC_STATUS_OK; 1492 (*rw_cb.p_cback) (RW_T4T_PRESENCE_CHECK_EVT, &evt_data); 1493 } 1494 else 1495 { 1496 if (rw_t4t_read_file (0, 1, FALSE)) 1497 { 1498 rw_cb.tcb.t4t.state = RW_T4T_STATE_PRESENCE_CHECK; 1499 } 1500 else 1501 { 1502 retval = NFC_STATUS_NO_BUFFERS; 1503 } 1504 } 1505 1506 return (retval); 1507} 1508 1509/***************************************************************************** 1510** 1511** Function RW_T4tSetNDefReadOnly 1512** 1513** Description This function performs NDEF read-only procedure 1514** Note: RW_T4tDetectNDef() must be called before using this 1515** 1516** The RW_T4T_SET_TO_RO_EVT event will be returned. 1517** 1518** Returns NFC_STATUS_OK if success 1519** NFC_STATUS_FAILED if T4T is busy or other error 1520** 1521*****************************************************************************/ 1522tNFC_STATUS RW_T4tSetNDefReadOnly (void) 1523{ 1524 tNFC_STATUS retval = NFC_STATUS_OK; 1525 tRW_DATA evt_data; 1526 1527 RW_TRACE_API0 ("RW_T4tSetNDefReadOnly ()"); 1528 1529 if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) 1530 { 1531 RW_TRACE_ERROR1 ("RW_T4tSetNDefReadOnly ():Unable to start command at state (0x%X)", 1532 rw_cb.tcb.t4t.state); 1533 return NFC_STATUS_FAILED; 1534 } 1535 1536 /* if NDEF has been detected */ 1537 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) 1538 { 1539 /* if read-only */ 1540 if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) 1541 { 1542 evt_data.status = NFC_STATUS_OK; 1543 (*rw_cb.p_cback) (RW_T4T_SET_TO_RO_EVT, &evt_data); 1544 return (retval); 1545 } 1546 1547 /* NDEF Tag application has been selected then select CC file */ 1548 if (!rw_t4t_select_file (T4T_CC_FILE_ID)) 1549 { 1550 return NFC_STATUS_FAILED; 1551 } 1552 1553 rw_cb.tcb.t4t.state = RW_T4T_STATE_SET_READ_ONLY; 1554 rw_cb.tcb.t4t.sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_CC; 1555 1556 return NFC_STATUS_OK; 1557 } 1558 else 1559 { 1560 RW_TRACE_ERROR0 ("RW_T4tSetNDefReadOnly ():No NDEF detected"); 1561 return NFC_STATUS_FAILED; 1562 } 1563 return (retval); 1564} 1565 1566#if (BT_TRACE_VERBOSE == TRUE) 1567/******************************************************************************* 1568** 1569** Function rw_t4t_get_state_name 1570** 1571** Description This function returns the state name. 1572** 1573** NOTE conditionally compiled to save memory. 1574** 1575** Returns pointer to the name 1576** 1577*******************************************************************************/ 1578static char *rw_t4t_get_state_name (UINT8 state) 1579{ 1580 switch (state) 1581 { 1582 case RW_T4T_STATE_NOT_ACTIVATED: 1583 return ("NOT_ACTIVATED"); 1584 case RW_T4T_STATE_IDLE: 1585 return ("IDLE"); 1586 case RW_T4T_STATE_DETECT_NDEF: 1587 return ("NDEF_DETECTION"); 1588 case RW_T4T_STATE_READ_NDEF: 1589 return ("READ_NDEF"); 1590 case RW_T4T_STATE_UPDATE_NDEF: 1591 return ("UPDATE_NDEF"); 1592 case RW_T4T_STATE_PRESENCE_CHECK: 1593 return ("PRESENCE_CHECK"); 1594 default: 1595 return ("???? UNKNOWN STATE"); 1596 } 1597} 1598 1599/******************************************************************************* 1600** 1601** Function rw_t4t_get_sub_state_name 1602** 1603** Description This function returns the sub_state name. 1604** 1605** NOTE conditionally compiled to save memory. 1606** 1607** Returns pointer to the name 1608** 1609*******************************************************************************/ 1610static char *rw_t4t_get_sub_state_name (UINT8 sub_state) 1611{ 1612 switch (sub_state) 1613 { 1614 case RW_T4T_SUBSTATE_WAIT_SELECT_APP: 1615 return ("WAIT_SELECT_APP"); 1616 case RW_T4T_SUBSTATE_WAIT_SELECT_CC: 1617 return ("WAIT_SELECT_CC"); 1618 case RW_T4T_SUBSTATE_WAIT_CC_FILE: 1619 return ("WAIT_CC_FILE"); 1620 case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE: 1621 return ("WAIT_SELECT_NDEF_FILE"); 1622 case RW_T4T_SUBSTATE_WAIT_READ_NLEN: 1623 return ("WAIT_READ_NLEN"); 1624 1625 case RW_T4T_SUBSTATE_WAIT_READ_RESP: 1626 return ("WAIT_READ_RESP"); 1627 case RW_T4T_SUBSTATE_WAIT_UPDATE_RESP: 1628 return ("WAIT_UPDATE_RESP"); 1629 case RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN: 1630 return ("WAIT_UPDATE_NLEN"); 1631 default: 1632 return ("???? UNKNOWN SUBSTATE"); 1633 } 1634} 1635#endif 1636 1637#endif /* (NFC_INCLUDED == TRUE) */ 1638