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 Card Emulation 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#include "nfc_api.h" 33#include "nfc_int.h" 34#include "ce_api.h" 35#include "ce_int.h" 36#include "tags_int.h" 37#include "gki.h" 38 39#if (CE_TEST_INCLUDED == TRUE) /* test only */ 40BOOLEAN mapping_aid_test_enabled = FALSE; 41UINT8 ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}; 42#endif 43 44/******************************************************************************* 45** 46** Function ce_t4t_send_to_lower 47** 48** Description Send packet to lower layer 49** 50** Returns TRUE if success 51** 52*******************************************************************************/ 53static BOOLEAN ce_t4t_send_to_lower (BT_HDR *p_r_apdu) 54{ 55#if (BT_TRACE_PROTOCOL == TRUE) 56 DispCET4Tags (p_r_apdu, FALSE); 57#endif 58 59 if (NFC_SendData (NFC_RF_CONN_ID, p_r_apdu) != NFC_STATUS_OK) 60 { 61 CE_TRACE_ERROR0 ("ce_t4t_send_to_lower (): NFC_SendData () failed"); 62 return FALSE; 63 } 64 return TRUE; 65} 66 67/******************************************************************************* 68** 69** Function ce_t4t_send_status 70** 71** Description Send status on R-APDU to peer 72** 73** Returns TRUE if success 74** 75*******************************************************************************/ 76static BOOLEAN ce_t4t_send_status (UINT16 status) 77{ 78 BT_HDR *p_r_apdu; 79 UINT8 *p; 80 81 CE_TRACE_DEBUG1 ("ce_t4t_send_status (): Status:0x%04X", status); 82 83 p_r_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID); 84 85 if (!p_r_apdu) 86 { 87 CE_TRACE_ERROR0 ("ce_t4t_send_status (): Cannot allocate buffer"); 88 return FALSE; 89 } 90 91 p_r_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 92 p = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 93 94 UINT16_TO_BE_STREAM (p, status); 95 96 p_r_apdu->len = T4T_RSP_STATUS_WORDS_SIZE; 97 98 if (!ce_t4t_send_to_lower (p_r_apdu)) 99 { 100 return FALSE; 101 } 102 return TRUE; 103} 104 105/******************************************************************************* 106** 107** Function ce_t4t_select_file 108** 109** Description Select a file 110** 111** Returns TRUE if success 112** 113*******************************************************************************/ 114static BOOLEAN ce_t4t_select_file (UINT16 file_id) 115{ 116 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 117 118 CE_TRACE_DEBUG1 ("ce_t4t_select_file (): FileID:0x%04X", file_id); 119 120 if (file_id == T4T_CC_FILE_ID) 121 { 122 CE_TRACE_DEBUG0 ("ce_t4t_select_file (): Select CC file"); 123 124 p_t4t->status |= CE_T4T_STATUS_CC_FILE_SELECTED; 125 p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_SELECTED); 126 127 return TRUE; 128 } 129 130 if (file_id == CE_T4T_MANDATORY_NDEF_FILE_ID) 131 { 132 CE_TRACE_DEBUG3 ("ce_t4t_select_file (): NLEN:0x%04X, MaxFileSize:0x%04X, WriteAccess:%s", 133 p_t4t->nlen, 134 p_t4t->max_file_size, 135 (p_t4t->status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY ? "RW" : "RO")); 136 137 p_t4t->status |= CE_T4T_STATUS_NDEF_SELECTED; 138 p_t4t->status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED); 139 140 return TRUE; 141 } 142 else 143 { 144 CE_TRACE_ERROR1 ("ce_t4t_select_file (): Cannot find file ID (0x%04X)", file_id); 145 146 p_t4t->status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED); 147 p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_SELECTED); 148 149 return FALSE; 150 } 151} 152 153/******************************************************************************* 154** 155** Function ce_t4t_read_binary 156** 157** Description Read data from selected file and send R-APDU to peer 158** 159** Returns TRUE if success 160** 161*******************************************************************************/ 162static BOOLEAN ce_t4t_read_binary (UINT16 offset, UINT8 length) 163{ 164 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 165 UINT8 *p_src = NULL, *p_dst; 166 BT_HDR *p_r_apdu; 167 168 CE_TRACE_DEBUG3 ("ce_t4t_read_binary (): Offset:0x%04X, Length:0x%04X, selected status = 0x%02X", 169 offset, length, p_t4t->status); 170 171 if (p_t4t->status & CE_T4T_STATUS_CC_FILE_SELECTED) 172 { 173 p_src = p_t4t->cc_file; 174 } 175 else if (p_t4t->status & CE_T4T_STATUS_NDEF_SELECTED) 176 { 177 if (p_t4t->p_scratch_buf) 178 p_src = p_t4t->p_scratch_buf; 179 else 180 p_src = p_t4t->p_ndef_msg; 181 } 182 183 if (p_src) 184 { 185 p_r_apdu = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID); 186 187 if (!p_r_apdu) 188 { 189 CE_TRACE_ERROR0 ("ce_t4t_read_binary (): Cannot allocate buffer"); 190 return FALSE; 191 } 192 193 p_r_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE; 194 p_dst = (UINT8 *) (p_r_apdu + 1) + p_r_apdu->offset; 195 196 p_r_apdu->len = length; 197 198 /* add NLEN before NDEF message and adjust offset */ 199 /* if NDEF file is selected and offset < T4T_FILE_LENGTH_SIZE */ 200 if ((p_t4t->status & CE_T4T_STATUS_NDEF_SELECTED) && (length > 0)) 201 { 202 if (offset == 0) 203 { 204 UINT16_TO_BE_STREAM (p_dst, p_t4t->nlen); 205 206 if (length == 1) 207 { 208 length = 0; 209 p_dst--; 210 } 211 else /* length >= 2 */ 212 length -= T4T_FILE_LENGTH_SIZE; 213 } 214 else if (offset == 1) 215 { 216 UINT8_TO_BE_STREAM (p_dst, (UINT8) (p_t4t->nlen)); 217 218 offset = 0; 219 length--; 220 } 221 else 222 { 223 offset -= T4T_FILE_LENGTH_SIZE; 224 } 225 } 226 227 if (length > 0) 228 { 229 memcpy (p_dst, p_src + offset, length); 230 p_dst += length; 231 } 232 233 UINT16_TO_BE_STREAM (p_dst, T4T_RSP_CMD_CMPLTED); 234 p_r_apdu->len += T4T_RSP_STATUS_WORDS_SIZE; 235 236 if (!ce_t4t_send_to_lower (p_r_apdu)) 237 { 238 return FALSE; 239 } 240 return TRUE; 241 } 242 else 243 { 244 CE_TRACE_ERROR0 ("ce_t4t_read_binary (): No selected file"); 245 246 if (!ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED)) 247 { 248 return FALSE; 249 } 250 return TRUE; 251 } 252} 253 254/******************************************************************************* 255** 256** Function ce_t4t_update_binary 257** 258** Description Update file and send R-APDU to peer 259** 260** Returns TRUE if success 261** 262*******************************************************************************/ 263static BOOLEAN ce_t4t_update_binary (UINT16 offset, UINT8 length, UINT8 *p_data) 264{ 265 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 266 UINT8 *p; 267 UINT8 file_length[2]; 268 UINT16 starting_offset; 269 tCE_DATA ce_data; 270 271 CE_TRACE_DEBUG3 ("ce_t4t_update_binary (): Offset:0x%04X, Length:0x%04X, selected status = 0x%02X", 272 offset, length, p_t4t->status); 273 274 starting_offset = offset; 275 276 /* update file size (NLEN) */ 277 if ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0)) 278 { 279 p = file_length; 280 UINT16_TO_BE_STREAM (p, p_t4t->nlen); 281 282 while ((offset < T4T_FILE_LENGTH_SIZE) && (length > 0)) 283 { 284 *(file_length + offset++) = *(p_data++); 285 length--; 286 } 287 288 p = file_length; 289 BE_STREAM_TO_UINT16 (p_t4t->nlen, p); 290 } 291 292 if (length > 0) 293 memcpy (p_t4t->p_scratch_buf + offset - T4T_FILE_LENGTH_SIZE, p_data, length); 294 295 /* if this is the last step: writing non-zero length in NLEN */ 296 if ((starting_offset == 0) && (p_t4t->nlen > 0)) 297 { 298 nfc_stop_quick_timer (&p_t4t->timer); 299 300 if (ce_cb.p_cback) 301 { 302 ce_data.update_info.status = NFC_STATUS_OK; 303 ce_data.update_info.length = p_t4t->nlen; 304 ce_data.update_info.p_data = p_t4t->p_scratch_buf; 305 306 (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_CPLT_EVT, &ce_data); 307 CE_TRACE_DEBUG0 ("ce_t4t_update_binary (): Sent CE_T4T_NDEF_UPDATE_CPLT_EVT"); 308 } 309 310 p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_UPDATING); 311 } 312 else if (!(p_t4t->status & CE_T4T_STATUS_NDEF_FILE_UPDATING)) 313 { 314 /* starting of updating */ 315 p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_UPDATING; 316 317 nfc_start_quick_timer (&p_t4t->timer, NFC_TTYPE_CE_T4T_UPDATE, 318 (CE_T4T_TOUT_UPDATE * QUICK_TIMER_TICKS_PER_SEC) / 1000); 319 320 if (ce_cb.p_cback) 321 (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_START_EVT, NULL); 322 } 323 324 if (!ce_t4t_send_status (T4T_RSP_CMD_CMPLTED)) 325 { 326 return FALSE; 327 } 328 else 329 { 330 return TRUE; 331 } 332} 333 334/******************************************************************************* 335** 336** Function ce_t4t_set_version_in_cc 337** 338** Description update version in CC file 339** If reader selects NDEF Tag Application with V1.0 AID then 340** set V1.0 into CC file. 341** If reader selects NDEF Tag Application with V2.0 AID then 342** set V2.0 into CC file. 343** 344** Returns None 345** 346*******************************************************************************/ 347static void ce_t4t_set_version_in_cc (UINT8 version) 348{ 349 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 350 UINT8 *p; 351 352 CE_TRACE_DEBUG1 ("ce_t4t_set_version_in_cc (): version = 0x%02X", version); 353 354 p = p_t4t->cc_file + T4T_VERSION_OFFSET_IN_CC; 355 356 UINT8_TO_BE_STREAM (p, version); 357} 358 359/******************************************************************************* 360** 361** Function ce_t4t_process_select_file_cmd 362** 363** Description This function processes Select Command by file ID. 364** 365** Returns TRUE if success 366** 367*******************************************************************************/ 368static BOOLEAN ce_t4t_process_select_file_cmd (UINT8 *p_cmd) 369{ 370 UINT8 data_len; 371 UINT16 file_id, status_words; 372 373 CE_TRACE_DEBUG0 ("ce_t4t_process_select_file_cmd ()"); 374 375 p_cmd++; /* skip P2 */ 376 377 /* Lc Byte */ 378 BE_STREAM_TO_UINT8 (data_len, p_cmd); 379 380 if (data_len == T4T_FILE_ID_SIZE) 381 { 382 /* File ID */ 383 BE_STREAM_TO_UINT16 (file_id, p_cmd); 384 385 if (ce_t4t_select_file (file_id)) 386 { 387 status_words = T4T_RSP_CMD_CMPLTED; 388 } 389 else 390 { 391 status_words = T4T_RSP_NOT_FOUND; 392 } 393 } 394 else 395 { 396 status_words = T4T_RSP_WRONG_LENGTH; 397 } 398 399 if (!ce_t4t_send_status (status_words)) 400 { 401 return FALSE; 402 } 403 404 if (status_words == T4T_RSP_CMD_CMPLTED) 405 { 406 return TRUE; 407 } 408 return FALSE; 409} 410 411/******************************************************************************* 412** 413** Function ce_t4t_process_select_app_cmd 414** 415** Description This function processes Select Command by AID. 416** 417** Returns none 418** 419*******************************************************************************/ 420static void ce_t4t_process_select_app_cmd (UINT8 *p_cmd, BT_HDR *p_c_apdu) 421{ 422 UINT8 data_len; 423 UINT16 status_words = 0x0000; /* invalid status words */ 424 tCE_DATA ce_data; 425 UINT8 xx; 426 427 CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd ()"); 428 429 p_cmd++; /* skip P2 */ 430 431 /* Lc Byte */ 432 BE_STREAM_TO_UINT8 (data_len, p_cmd); 433 434#if (CE_TEST_INCLUDED == TRUE) 435 if (mapping_aid_test_enabled) 436 { 437 if ( (data_len == T4T_V20_NDEF_TAG_AID_LEN) 438 &&(!memcmp(p_cmd, ce_test_tag_app_id, data_len)) 439 &&(ce_cb.mem.t4t.p_ndef_msg) ) 440 { 441 GKI_freebuf (p_c_apdu); 442 ce_t4t_send_status ((UINT16) T4T_RSP_CMD_CMPLTED); 443 return; 444 } 445 } 446#endif 447 448 /* 449 ** Compare AIDs registered by applications 450 ** if found, use callback of the application 451 ** otherwise, return error and maintain the same status 452 */ 453 ce_cb.mem.t4t.selected_aid_idx = CE_T4T_MAX_REG_AID; 454 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) 455 { 456 if ( (ce_cb.mem.t4t.reg_aid[xx].aid_len > 0) 457 &&(ce_cb.mem.t4t.reg_aid[xx].aid_len == data_len) 458 &&(!(memcmp(ce_cb.mem.t4t.reg_aid[xx].aid, p_cmd, data_len))) ) 459 { 460 ce_cb.mem.t4t.selected_aid_idx = xx; 461 break; 462 } 463 } 464 465 /* if found matched AID */ 466 if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID) 467 { 468 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED); 469 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_NDEF_SELECTED); 470 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_T4T_APP_SELECTED); 471 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_WILDCARD_AID_SELECTED); 472 ce_cb.mem.t4t.status |= CE_T4T_STATUS_REG_AID_SELECTED; 473 474 CE_TRACE_DEBUG4 ("ce_t4t_process_select_app_cmd (): Registered AID[%02X%02X%02X%02X...] is selected", 475 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[0], 476 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[1], 477 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[2], 478 ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].aid[3]); 479 480 ce_data.raw_frame.status = NFC_STATUS_OK; 481 ce_data.raw_frame.p_data = p_c_apdu; 482 ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx; 483 484 p_c_apdu = NULL; 485 486 (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); 487 } 488 else if ( (data_len == T4T_V20_NDEF_TAG_AID_LEN) 489 &&(!memcmp(p_cmd, t4t_v20_ndef_tag_aid, data_len - 1)) 490 &&(ce_cb.mem.t4t.p_ndef_msg) ) 491 { 492 p_cmd += data_len - 1; 493 494 /* adjust version if possible */ 495 if ((*p_cmd) == 0x00) 496 { 497 ce_t4t_set_version_in_cc (T4T_VERSION_1_0); 498 status_words = T4T_RSP_CMD_CMPLTED; 499 } 500 else if ((*p_cmd) == 0x01) 501 { 502 ce_t4t_set_version_in_cc (T4T_VERSION_2_0); 503 status_words = T4T_RSP_CMD_CMPLTED; 504 } 505 else 506 { 507 CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd (): Not found matched AID"); 508 status_words = T4T_RSP_NOT_FOUND; 509 } 510 } 511 else if (ce_cb.mem.t4t.p_wildcard_aid_cback) 512 { 513 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED); 514 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_NDEF_SELECTED); 515 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_T4T_APP_SELECTED); 516 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_REG_AID_SELECTED); 517 ce_cb.mem.t4t.status |= CE_T4T_STATUS_WILDCARD_AID_SELECTED; 518 519 ce_data.raw_frame.status = NFC_STATUS_OK; 520 ce_data.raw_frame.p_data = p_c_apdu; 521 ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE; 522 p_c_apdu = NULL; 523 524 CE_TRACE_DEBUG0 ("CET4T: Forward raw frame (SELECT APP) to wildcard AID handler"); 525 (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); 526 } 527 else 528 { 529 CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd (): Not found matched AID or not listening T4T NDEF"); 530 status_words = T4T_RSP_NOT_FOUND; 531 } 532 533 if (status_words) 534 { 535 /* if T4T CE can support */ 536 if (status_words == T4T_RSP_CMD_CMPLTED) 537 { 538 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_CC_FILE_SELECTED); 539 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_NDEF_SELECTED); 540 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_REG_AID_SELECTED); 541 ce_cb.mem.t4t.status &= ~ (CE_T4T_STATUS_WILDCARD_AID_SELECTED); 542 ce_cb.mem.t4t.status |= CE_T4T_STATUS_T4T_APP_SELECTED; 543 544 CE_TRACE_DEBUG0 ("ce_t4t_process_select_app_cmd (): T4T CE App selected"); 545 } 546 547 ce_t4t_send_status (status_words); 548 GKI_freebuf (p_c_apdu); 549 } 550 /* if status_words is not set then upper layer will send R-APDU */ 551 552 return; 553} 554 555/******************************************************************************* 556** 557** Function ce_t4t_process_timeout 558** 559** Description process timeout event 560** 561** Returns none 562** 563*******************************************************************************/ 564void ce_t4t_process_timeout (TIMER_LIST_ENT *p_tle) 565{ 566 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 567 tCE_DATA ce_data; 568 569 CE_TRACE_DEBUG1 ("ce_t4t_process_timeout () event=%d", p_tle->event); 570 571 if (p_tle->event == NFC_TTYPE_CE_T4T_UPDATE) 572 { 573 if (p_t4t->status & CE_T4T_STATUS_NDEF_FILE_UPDATING) 574 { 575 ce_data.status = NFC_STATUS_TIMEOUT; 576 577 if (ce_cb.p_cback) 578 (*ce_cb.p_cback) (CE_T4T_NDEF_UPDATE_ABORT_EVT, &ce_data); 579 580 p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_UPDATING); 581 } 582 } 583 else 584 { 585 CE_TRACE_ERROR1 ("ce_t4t_process_timeout () unknown event=%d", p_tle->event); 586 } 587} 588 589/******************************************************************************* 590** 591** Function ce_t4t_data_cback 592** 593** Description This callback function receives the data from NFCC. 594** 595** Returns none 596** 597*******************************************************************************/ 598static void ce_t4t_data_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) 599{ 600 BT_HDR *p_c_apdu; 601 UINT8 *p_cmd; 602 UINT8 cla, instruct, select_type = 0, length; 603 UINT16 offset, max_file_size; 604 tCE_DATA ce_data; 605 606 if (event == NFC_DEACTIVATE_CEVT) 607 { 608 NFC_SetStaticRfCback (NULL); 609 return; 610 } 611 if (event != NFC_DATA_CEVT) 612 { 613 return; 614 } 615 616 p_c_apdu = (BT_HDR *) p_data->data.p_data; 617 618#if (BT_TRACE_PROTOCOL == TRUE) 619 DispCET4Tags (p_c_apdu, TRUE); 620#endif 621 622 CE_TRACE_DEBUG1 ("ce_t4t_data_cback (): conn_id = 0x%02X", conn_id); 623 624 p_cmd = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 625 626 /* Class Byte */ 627 BE_STREAM_TO_UINT8 (cla, p_cmd); 628 629 /* Don't check class if registered AID has been selected */ 630 if ( (cla != T4T_CMD_CLASS) 631 &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) == 0) 632 &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) == 0) ) 633 { 634 GKI_freebuf (p_c_apdu); 635 ce_t4t_send_status (T4T_RSP_CLASS_NOT_SUPPORTED); 636 return; 637 } 638 639 /* Instruction Byte */ 640 BE_STREAM_TO_UINT8 (instruct, p_cmd); 641 642 if ((cla == T4T_CMD_CLASS) && (instruct == T4T_CMD_INS_SELECT)) 643 { 644 /* P1 Byte */ 645 BE_STREAM_TO_UINT8 (select_type, p_cmd); 646 647 if (select_type == T4T_CMD_P1_SELECT_BY_NAME) 648 { 649 ce_t4t_process_select_app_cmd (p_cmd, p_c_apdu); 650 return; 651 } 652 } 653 654 /* if registered AID is selected */ 655 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) 656 { 657 CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to registered AID"); 658 659 /* forward raw frame to upper layer */ 660 if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID) 661 { 662 ce_data.raw_frame.status = p_data->data.status; 663 ce_data.raw_frame.p_data = p_c_apdu; 664 ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx; 665 p_c_apdu = NULL; 666 667 (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); 668 } 669 else 670 { 671 GKI_freebuf (p_c_apdu); 672 ce_t4t_send_status (T4T_RSP_NOT_FOUND); 673 } 674 } 675 else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) 676 { 677 CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to wildcard AID handler"); 678 679 /* forward raw frame to upper layer */ 680 ce_data.raw_frame.status = p_data->data.status; 681 ce_data.raw_frame.p_data = p_c_apdu; 682 ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE; 683 p_c_apdu = NULL; 684 685 (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); 686 } 687 else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED) 688 { 689 if (instruct == T4T_CMD_INS_SELECT) 690 { 691 /* P1 Byte is already parsed */ 692 if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID) 693 { 694 ce_t4t_process_select_file_cmd (p_cmd); 695 } 696 else 697 { 698 CE_TRACE_ERROR1 ("CET4T: Bad P1 byte (0x%02X)", select_type); 699 ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); 700 } 701 } 702 else if (instruct == T4T_CMD_INS_READ_BINARY) 703 { 704 if ( (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) 705 ||(ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) ) 706 { 707 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) 708 { 709 max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE; 710 } 711 else 712 { 713 max_file_size = ce_cb.mem.t4t.max_file_size; 714 } 715 716 BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */ 717 BE_STREAM_TO_UINT8 (length, p_cmd); /* Le */ 718 719 /* check if valid parameters */ 720 if (length <= CE_T4T_MAX_LE) 721 { 722 /* CE allows to read more than current file size but not max file size */ 723 if (length + offset > max_file_size) 724 { 725 if (offset < max_file_size) 726 { 727 length = (UINT8) (max_file_size - offset); 728 729 CE_TRACE_DEBUG2 ("CET4T: length is reduced to %d by max_file_size (%d)", 730 length, max_file_size); 731 } 732 else 733 { 734 CE_TRACE_ERROR2 ("CET4T: offset (%d) must be less than max_file_size (%d)", 735 offset, max_file_size); 736 length = 0; 737 } 738 } 739 } 740 else 741 { 742 CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLe (%d)", 743 length, CE_T4T_MAX_LE); 744 length = 0; 745 } 746 747 if (length > 0) 748 ce_t4t_read_binary (offset, length); 749 else 750 ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); 751 } 752 else 753 { 754 CE_TRACE_ERROR0 ("CET4T: File has not been selected"); 755 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 756 } 757 } 758 else if (instruct == T4T_CMD_INS_UPDATE_BINARY) 759 { 760 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY) 761 { 762 CE_TRACE_ERROR0 ("CET4T: No access right"); 763 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 764 } 765 else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) 766 { 767 BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */ 768 BE_STREAM_TO_UINT8 (length, p_cmd); /* Lc */ 769 770 /* check if valid parameters */ 771 if (length <= CE_T4T_MAX_LC) 772 { 773 if (length + offset > ce_cb.mem.t4t.max_file_size) 774 { 775 CE_TRACE_ERROR3 ("CET4T: length (%d) + offset (%d) must be less than max_file_size (%d)", 776 length, offset, ce_cb.mem.t4t.max_file_size); 777 length = 0; 778 } 779 } 780 else 781 { 782 CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLc (%d)", 783 length, CE_T4T_MAX_LC); 784 length = 0; 785 } 786 787 if (length > 0) 788 ce_t4t_update_binary (offset, length, p_cmd); 789 else 790 ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); 791 } 792 else 793 { 794 CE_TRACE_ERROR0 ("CET4T: NDEF File has not been selected"); 795 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 796 } 797 } 798 else 799 { 800 CE_TRACE_ERROR1 ("CET4T: Unsupported Instruction byte (0x%02X)", instruct); 801 ce_t4t_send_status (T4T_RSP_INSTR_NOT_SUPPORTED); 802 } 803 } 804 else 805 { 806 CE_TRACE_ERROR0 ("CET4T: Application has not been selected"); 807 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 808 } 809 810 if (p_c_apdu) 811 GKI_freebuf (p_c_apdu); 812} 813 814/******************************************************************************* 815** 816** Function ce_select_t4t 817** 818** Description Select Type 4 Tag 819** 820** Returns NFC_STATUS_OK if success 821** 822*******************************************************************************/ 823tNFC_STATUS ce_select_t4t (void) 824{ 825 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 826 827 CE_TRACE_DEBUG0 ("ce_select_t4t ()"); 828 829 nfc_stop_quick_timer (&p_t4t->timer); 830 831 /* clear other than read-only flag */ 832 p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY; 833 834 NFC_SetStaticRfCback (ce_t4t_data_cback); 835 836 return NFC_STATUS_OK; 837} 838 839/******************************************************************************* 840** 841** Function CE_T4tSetLocalNDEFMsg 842** 843** Description Initialise CE Type 4 Tag with mandatory NDEF message 844** 845** The following event may be returned 846** CE_T4T_UPDATE_START_EVT for starting update 847** CE_T4T_UPDATE_CPLT_EVT for complete update 848** CE_T4T_UPDATE_ABORT_EVT for failure of update 849** CE_T4T_RAW_FRAME_EVT for raw frame 850** 851** read_only: TRUE if read only 852** ndef_msg_max: Max NDEF message size 853** ndef_msg_len: NDEF message size 854** p_ndef_msg: NDEF message (excluding NLEN) 855** p_scratch_buf: temp storage for update 856** 857** Returns NFC_STATUS_OK if success 858** 859*******************************************************************************/ 860tNFC_STATUS CE_T4tSetLocalNDEFMsg (BOOLEAN read_only, 861 UINT16 ndef_msg_max, 862 UINT16 ndef_msg_len, 863 UINT8 *p_ndef_msg, 864 UINT8 *p_scratch_buf) 865{ 866 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 867 UINT8 *p; 868 869 CE_TRACE_API3 ("CE_T4tSetLocalNDEFMsg () read_only=%d, ndef_msg_max=%d, ndef_msg_len=%d", 870 read_only, ndef_msg_max, ndef_msg_len); 871 872 if (!p_ndef_msg) 873 { 874 p_t4t->p_ndef_msg = NULL; 875 876 CE_TRACE_DEBUG0 ("CE_T4tSetLocalNDEFMsg (): T4T is disabled"); 877 return NFC_STATUS_OK; 878 } 879 880 if ((!read_only) && (!p_scratch_buf)) 881 { 882 CE_TRACE_ERROR0 ("CE_T4tSetLocalNDEFMsg (): p_scratch_buf cannot be NULL if not read-only"); 883 return NFC_STATUS_FAILED; 884 } 885 886#if (CE_TEST_INCLUDED == TRUE) 887 mapping_aid_test_enabled = FALSE; 888#endif 889 890 /* Initialise CC file */ 891 p = p_t4t->cc_file; 892 893 UINT16_TO_BE_STREAM (p, T4T_CC_FILE_MIN_LEN); 894 UINT8_TO_BE_STREAM (p, T4T_MY_VERSION); 895 UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LE); 896 UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LC); 897 898 /* Mandatory NDEF File Control TLV */ 899 UINT8_TO_BE_STREAM (p, T4T_NDEF_FILE_CONTROL_TYPE); /* type */ 900 UINT8_TO_BE_STREAM (p, T4T_FILE_CONTROL_LENGTH); /* length */ 901 UINT16_TO_BE_STREAM (p, CE_T4T_MANDATORY_NDEF_FILE_ID); /* file ID */ 902 UINT16_TO_BE_STREAM (p, ndef_msg_max + T4T_FILE_LENGTH_SIZE); /* max NDEF file size */ 903 UINT8_TO_BE_STREAM (p, T4T_FC_READ_ACCESS); /* read access */ 904 905 if (read_only) 906 { 907 UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS); /* read only */ 908 p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_READ_ONLY; 909 } 910 else 911 { 912 UINT8_TO_BE_STREAM (p, T4T_FC_WRITE_ACCESS); /* write access */ 913 p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_READ_ONLY); 914 } 915 916 /* set mandatory NDEF file */ 917 p_t4t->p_ndef_msg = p_ndef_msg; 918 p_t4t->nlen = ndef_msg_len; 919 p_t4t->max_file_size = ndef_msg_max + T4T_FILE_LENGTH_SIZE; 920 921 /* Initialize scratch buffer */ 922 p_t4t->p_scratch_buf = p_scratch_buf; 923 924 if (p_scratch_buf) 925 { 926 memcpy (p_scratch_buf, p_ndef_msg, ndef_msg_len); 927 } 928 929 return NFC_STATUS_OK; 930} 931 932/******************************************************************************* 933** 934** Function CE_T4tRegisterAID 935** 936** Description Register AID in CE T4T 937** 938** aid_len: length of AID (up to NFC_MAX_AID_LEN) 939** p_aid: AID 940** p_cback: Raw frame will be forwarded with CE_RAW_FRAME_EVT 941** 942** Returns tCE_T4T_AID_HANDLE if successful, 943** CE_T4T_AID_HANDLE_INVALID otherwisse 944** 945*******************************************************************************/ 946tCE_T4T_AID_HANDLE CE_T4tRegisterAID (UINT8 aid_len, UINT8 *p_aid, tCE_CBACK *p_cback) 947{ 948 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 949 UINT8 xx; 950 951 /* Handle registering callback for wildcard AID (all AIDs) */ 952 if (aid_len == 0) 953 { 954 CE_TRACE_API0 ("CE_T4tRegisterAID (): registering callback for wildcard AID "); 955 956 /* Check if a wildcard callback is already registered (only one is allowed) */ 957 if (p_t4t->p_wildcard_aid_cback != NULL) 958 { 959 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): only one wildcard AID can be registered at time."); 960 return CE_T4T_AID_HANDLE_INVALID; 961 } 962 963 CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered (for wildcard AID)", CE_T4T_WILDCARD_AID_HANDLE); 964 p_t4t->p_wildcard_aid_cback = p_cback; 965 return CE_T4T_WILDCARD_AID_HANDLE; 966 } 967 968 969 CE_TRACE_API5 ("CE_T4tRegisterAID () AID [%02X%02X%02X%02X...], %d bytes", 970 *p_aid, *(p_aid+1), *(p_aid+2), *(p_aid+3), aid_len); 971 972 if (aid_len > NFC_MAX_AID_LEN) 973 { 974 CE_TRACE_ERROR1 ("CE_T4tRegisterAID (): AID is up to %d bytes", NFC_MAX_AID_LEN); 975 return CE_T4T_AID_HANDLE_INVALID; 976 } 977 978 if (p_cback == NULL) 979 { 980 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): callback must be provided"); 981 return CE_T4T_AID_HANDLE_INVALID; 982 } 983 984 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) 985 { 986 if ( (p_t4t->reg_aid[xx].aid_len == aid_len) 987 &&(!(memcmp(p_t4t->reg_aid[xx].aid, p_aid, aid_len))) ) 988 { 989 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): already registered"); 990 return CE_T4T_AID_HANDLE_INVALID; 991 } 992 } 993 994 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) 995 { 996 if (p_t4t->reg_aid[xx].aid_len == 0) 997 { 998 p_t4t->reg_aid[xx].aid_len = aid_len; 999 p_t4t->reg_aid[xx].p_cback = p_cback; 1000 memcpy (p_t4t->reg_aid[xx].aid, p_aid, aid_len); 1001 break; 1002 } 1003 } 1004 1005 if (xx >= CE_T4T_MAX_REG_AID) 1006 { 1007 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): No resource"); 1008 return CE_T4T_AID_HANDLE_INVALID; 1009 } 1010 else 1011 { 1012 CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered", xx); 1013 } 1014 1015 return (xx); 1016} 1017 1018/******************************************************************************* 1019** 1020** Function CE_T4tDeregisterAID 1021** 1022** Description Deregister AID in CE T4T 1023** 1024** Returns NFC_STATUS_OK if success 1025** 1026*******************************************************************************/ 1027NFC_API extern void CE_T4tDeregisterAID (tCE_T4T_AID_HANDLE aid_handle) 1028{ 1029 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 1030 1031 CE_TRACE_API1 ("CE_T4tDeregisterAID () handle 0x%02x", aid_handle); 1032 1033 /* Check if deregistering wildcard AID */ 1034 if (aid_handle == CE_T4T_WILDCARD_AID_HANDLE) 1035 { 1036 if (p_t4t->p_wildcard_aid_cback != NULL) 1037 { 1038 p_t4t->p_wildcard_aid_cback = NULL; 1039 } 1040 else 1041 { 1042 CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle"); 1043 } 1044 return; 1045 } 1046 1047 /* Deregister AID */ 1048 if ((aid_handle >= CE_T4T_MAX_REG_AID) || (p_t4t->reg_aid[aid_handle].aid_len==0)) 1049 { 1050 CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle"); 1051 } 1052 else 1053 { 1054 p_t4t->reg_aid[aid_handle].aid_len = 0; 1055 p_t4t->reg_aid[aid_handle].p_cback = NULL; 1056 } 1057} 1058 1059/******************************************************************************* 1060** 1061** Function CE_T4TTestSetCC 1062** 1063** Description Set fields in Capability Container File for testing 1064** 1065** Returns NFC_STATUS_OK if success 1066** 1067*******************************************************************************/ 1068tNFC_STATUS CE_T4TTestSetCC (UINT16 cc_len, 1069 UINT8 version, 1070 UINT16 max_le, 1071 UINT16 max_lc) 1072{ 1073#if (CE_TEST_INCLUDED == TRUE) 1074 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 1075 UINT8 *p; 1076 1077 CE_TRACE_DEBUG4 ("CE_T4TTestSetCC (): CCLen:0x%04X, Ver:0x%02X, MaxLe:0x%04X, MaxLc:0x%04X", 1078 cc_len, version, max_le, max_lc); 1079 1080 /* CC file */ 1081 p = p_t4t->cc_file; 1082 1083 if (cc_len != 0xFFFF) 1084 { 1085 UINT16_TO_BE_STREAM (p, cc_len); 1086 } 1087 else 1088 p += 2; 1089 1090 if (version != 0xFF) 1091 { 1092 mapping_aid_test_enabled = TRUE; 1093 if (version == T4T_VERSION_1_0) 1094 ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x00; 1095 else if (version == T4T_VERSION_2_0) 1096 ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x01; 1097 else /* Undefined version */ 1098 ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0xFF; 1099 1100 UINT8_TO_BE_STREAM (p, version); 1101 } 1102 else 1103 { 1104 mapping_aid_test_enabled = FALSE; 1105 p += 1; 1106 } 1107 1108 if (max_le != 0xFFFF) 1109 { 1110 UINT16_TO_BE_STREAM (p, max_le); 1111 } 1112 else 1113 p += 2; 1114 1115 if (max_lc != 0xFFFF) 1116 { 1117 UINT16_TO_BE_STREAM (p, max_lc); 1118 } 1119 else 1120 p += 2; 1121 1122 return NFC_STATUS_OK; 1123#else 1124 return NFC_STATUS_FAILED; 1125#endif 1126} 1127 1128/******************************************************************************* 1129** 1130** Function CE_T4TTestSetNDEFCtrlTLV 1131** 1132** Description Set fields in NDEF File Control TLV for testing 1133** 1134** Returns NFC_STATUS_OK if success 1135** 1136*******************************************************************************/ 1137tNFC_STATUS CE_T4TTestSetNDEFCtrlTLV (UINT8 type, 1138 UINT8 length, 1139 UINT16 file_id, 1140 UINT16 max_file_size, 1141 UINT8 read_access, 1142 UINT8 write_access) 1143{ 1144#if (CE_TEST_INCLUDED == TRUE) 1145 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 1146 UINT8 *p; 1147 1148 CE_TRACE_DEBUG6 ("CE_T4TTestSetNDEFCtrlTLV (): type:0x%02X, len:0x%02X, FileID:0x%04X, MaxFile:0x%04X, RdAcc:0x%02X, WrAcc:0x%02X", 1149 type, length, file_id, max_file_size, read_access, write_access); 1150 1151 /* NDEF File control TLV */ 1152 p = p_t4t->cc_file + T4T_FC_TLV_OFFSET_IN_CC; 1153 1154 if (type != 0xFF) 1155 { 1156 UINT8_TO_BE_STREAM (p, type); 1157 } 1158 else 1159 p += 1; 1160 1161 if (length != 0xFF) 1162 { 1163 UINT8_TO_BE_STREAM (p, length); 1164 } 1165 else 1166 p += 1; 1167 1168 if (file_id != 0xFFFF) 1169 { 1170 UINT16_TO_BE_STREAM (p, file_id); 1171 } 1172 else 1173 p += 2; 1174 1175 if (max_file_size != 0xFFFF) 1176 { 1177 UINT16_TO_BE_STREAM (p, max_file_size); 1178 } 1179 else 1180 p += 2; 1181 1182 if (read_access != 0xFF) 1183 { 1184 UINT8_TO_BE_STREAM (p, read_access); 1185 } 1186 else 1187 p += 1; 1188 1189 if (write_access != 0xFF) 1190 { 1191 UINT8_TO_BE_STREAM (p, write_access); 1192 } 1193 else 1194 p += 1; 1195 1196 return NFC_STATUS_OK; 1197#else 1198 return NFC_STATUS_FAILED; 1199#endif 1200} 1201#endif /* NFC_INCLUDED == TRUE */ 1202