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