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