ce_t4t.c revision 5c65c3a0f42e174e47fecd4e569606003217ff4e
1/****************************************************************************** 2 * 3 * Copyright (C) 2010-2013 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 20/****************************************************************************** 21 * 22 * This file contains the implementation for Type 4 tag in 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 = (BT_HDR *) p_data->data.p_data; 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#if (BT_TRACE_PROTOCOL == TRUE) 617 DispCET4Tags (p_c_apdu, TRUE); 618#endif 619 620 CE_TRACE_DEBUG1 ("ce_t4t_data_cback (): conn_id = 0x%02X", conn_id); 621 622 p_cmd = (UINT8 *) (p_c_apdu + 1) + p_c_apdu->offset; 623 624 /* Class Byte */ 625 BE_STREAM_TO_UINT8 (cla, p_cmd); 626 627 /* Don't check class if registered AID has been selected */ 628 if ( (cla != T4T_CMD_CLASS) 629 &&((ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) == 0) ) 630 { 631 CE_TRACE_ERROR1 ("CET4T: Unsupported Class byte (0x%02X)", cla); 632 GKI_freebuf (p_c_apdu); 633 ce_t4t_send_status (T4T_RSP_CLASS_NOT_SUPPORTED); 634 return; 635 } 636 637 /* Instruction Byte */ 638 BE_STREAM_TO_UINT8 (instruct, p_cmd); 639 640 if ((cla == T4T_CMD_CLASS) && (instruct == T4T_CMD_INS_SELECT)) 641 { 642 /* P1 Byte */ 643 BE_STREAM_TO_UINT8 (select_type, p_cmd); 644 645 if (select_type == T4T_CMD_P1_SELECT_BY_NAME) 646 { 647 ce_t4t_process_select_app_cmd (p_cmd, p_c_apdu); 648 return; 649 } 650 } 651 652 /* if registered AID is selected */ 653 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_REG_AID_SELECTED) 654 { 655 CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to registered AID"); 656 657 /* forward raw frame to upper layer */ 658 if (ce_cb.mem.t4t.selected_aid_idx < CE_T4T_MAX_REG_AID) 659 { 660 ce_data.raw_frame.status = NFC_STATUS_OK; 661 ce_data.raw_frame.p_data = p_c_apdu; 662 ce_data.raw_frame.aid_handle = ce_cb.mem.t4t.selected_aid_idx; 663 p_c_apdu = NULL; 664 665 (*(ce_cb.mem.t4t.reg_aid[ce_cb.mem.t4t.selected_aid_idx].p_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); 666 } 667 else 668 { 669 GKI_freebuf (p_c_apdu); 670 ce_t4t_send_status (T4T_RSP_NOT_FOUND); 671 } 672 } 673 else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_WILDCARD_AID_SELECTED) 674 { 675 CE_TRACE_DEBUG0 ("CET4T: Forward raw frame to wildcard AID handler"); 676 677 /* forward raw frame to upper layer */ 678 ce_data.raw_frame.status = NFC_STATUS_OK; 679 ce_data.raw_frame.p_data = p_c_apdu; 680 ce_data.raw_frame.aid_handle = CE_T4T_WILDCARD_AID_HANDLE; 681 p_c_apdu = NULL; 682 683 (*(ce_cb.mem.t4t.p_wildcard_aid_cback)) (CE_T4T_RAW_FRAME_EVT, &ce_data); 684 } 685 else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_T4T_APP_SELECTED) 686 { 687 if (instruct == T4T_CMD_INS_SELECT) 688 { 689 /* P1 Byte is already parsed */ 690 if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID) 691 { 692 ce_t4t_process_select_file_cmd (p_cmd); 693 } 694 else 695 { 696 CE_TRACE_ERROR1 ("CET4T: Bad P1 byte (0x%02X)", select_type); 697 ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); 698 } 699 } 700 else if (instruct == T4T_CMD_INS_READ_BINARY) 701 { 702 if ( (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) 703 ||(ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) ) 704 { 705 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_CC_FILE_SELECTED) 706 { 707 max_file_size = T4T_FC_TLV_OFFSET_IN_CC + T4T_FILE_CONTROL_TLV_SIZE; 708 } 709 else 710 { 711 max_file_size = ce_cb.mem.t4t.max_file_size; 712 } 713 714 BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */ 715 BE_STREAM_TO_UINT8 (length, p_cmd); /* Le */ 716 717 /* check if valid parameters */ 718 if (length <= CE_T4T_MAX_LE) 719 { 720 /* CE allows to read more than current file size but not max file size */ 721 if (length + offset > max_file_size) 722 { 723 if (offset < max_file_size) 724 { 725 length = (UINT8) (max_file_size - offset); 726 727 CE_TRACE_DEBUG2 ("CET4T: length is reduced to %d by max_file_size (%d)", 728 length, max_file_size); 729 } 730 else 731 { 732 CE_TRACE_ERROR2 ("CET4T: offset (%d) must be less than max_file_size (%d)", 733 offset, max_file_size); 734 length = 0; 735 } 736 } 737 } 738 else 739 { 740 CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLe (%d)", 741 length, CE_T4T_MAX_LE); 742 length = 0; 743 } 744 745 if (length > 0) 746 ce_t4t_read_binary (offset, length); 747 else 748 ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); 749 } 750 else 751 { 752 CE_TRACE_ERROR0 ("CET4T: File has not been selected"); 753 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 754 } 755 } 756 else if (instruct == T4T_CMD_INS_UPDATE_BINARY) 757 { 758 if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_FILE_READ_ONLY) 759 { 760 CE_TRACE_ERROR0 ("CET4T: No access right"); 761 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 762 } 763 else if (ce_cb.mem.t4t.status & CE_T4T_STATUS_NDEF_SELECTED) 764 { 765 BE_STREAM_TO_UINT16 (offset, p_cmd); /* Offset */ 766 BE_STREAM_TO_UINT8 (length, p_cmd); /* Lc */ 767 768 /* check if valid parameters */ 769 if (length <= CE_T4T_MAX_LC) 770 { 771 if (length + offset > ce_cb.mem.t4t.max_file_size) 772 { 773 CE_TRACE_ERROR3 ("CET4T: length (%d) + offset (%d) must be less than max_file_size (%d)", 774 length, offset, ce_cb.mem.t4t.max_file_size); 775 length = 0; 776 } 777 } 778 else 779 { 780 CE_TRACE_ERROR2 ("CET4T: length (%d) must be less than MLc (%d)", 781 length, CE_T4T_MAX_LC); 782 length = 0; 783 } 784 785 if (length > 0) 786 ce_t4t_update_binary (offset, length, p_cmd); 787 else 788 ce_t4t_send_status (T4T_RSP_WRONG_PARAMS); 789 } 790 else 791 { 792 CE_TRACE_ERROR0 ("CET4T: NDEF File has not been selected"); 793 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 794 } 795 } 796 else 797 { 798 CE_TRACE_ERROR1 ("CET4T: Unsupported Instruction byte (0x%02X)", instruct); 799 ce_t4t_send_status (T4T_RSP_INSTR_NOT_SUPPORTED); 800 } 801 } 802 else 803 { 804 CE_TRACE_ERROR0 ("CET4T: Application has not been selected"); 805 ce_t4t_send_status (T4T_RSP_CMD_NOT_ALLOWED); 806 } 807 808 if (p_c_apdu) 809 GKI_freebuf (p_c_apdu); 810} 811 812/******************************************************************************* 813** 814** Function ce_select_t4t 815** 816** Description Select Type 4 Tag 817** 818** Returns NFC_STATUS_OK if success 819** 820*******************************************************************************/ 821tNFC_STATUS ce_select_t4t (void) 822{ 823 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 824 825 CE_TRACE_DEBUG0 ("ce_select_t4t ()"); 826 827 nfc_stop_quick_timer (&p_t4t->timer); 828 829 /* clear other than read-only flag */ 830 p_t4t->status &= CE_T4T_STATUS_NDEF_FILE_READ_ONLY; 831 832 NFC_SetStaticRfCback (ce_t4t_data_cback); 833 834 return NFC_STATUS_OK; 835} 836 837/******************************************************************************* 838** 839** Function CE_T4tSetLocalNDEFMsg 840** 841** Description Initialise CE Type 4 Tag with mandatory NDEF message 842** 843** The following event may be returned 844** CE_T4T_UPDATE_START_EVT for starting update 845** CE_T4T_UPDATE_CPLT_EVT for complete update 846** CE_T4T_UPDATE_ABORT_EVT for failure of update 847** CE_T4T_RAW_FRAME_EVT for raw frame 848** 849** read_only: TRUE if read only 850** ndef_msg_max: Max NDEF message size 851** ndef_msg_len: NDEF message size 852** p_ndef_msg: NDEF message (excluding NLEN) 853** p_scratch_buf: temp storage for update 854** 855** Returns NFC_STATUS_OK if success 856** 857*******************************************************************************/ 858tNFC_STATUS CE_T4tSetLocalNDEFMsg (BOOLEAN read_only, 859 UINT16 ndef_msg_max, 860 UINT16 ndef_msg_len, 861 UINT8 *p_ndef_msg, 862 UINT8 *p_scratch_buf) 863{ 864 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 865 UINT8 *p; 866 867 CE_TRACE_API3 ("CE_T4tSetLocalNDEFMsg () read_only=%d, ndef_msg_max=%d, ndef_msg_len=%d", 868 read_only, ndef_msg_max, ndef_msg_len); 869 870 if (!p_ndef_msg) 871 { 872 p_t4t->p_ndef_msg = NULL; 873 874 CE_TRACE_DEBUG0 ("CE_T4tSetLocalNDEFMsg (): T4T is disabled"); 875 return NFC_STATUS_OK; 876 } 877 878 if ((!read_only) && (!p_scratch_buf)) 879 { 880 CE_TRACE_ERROR0 ("CE_T4tSetLocalNDEFMsg (): p_scratch_buf cannot be NULL if not read-only"); 881 return NFC_STATUS_FAILED; 882 } 883 884#if (CE_TEST_INCLUDED == TRUE) 885 mapping_aid_test_enabled = FALSE; 886#endif 887 888 /* Initialise CC file */ 889 p = p_t4t->cc_file; 890 891 UINT16_TO_BE_STREAM (p, T4T_CC_FILE_MIN_LEN); 892 UINT8_TO_BE_STREAM (p, T4T_MY_VERSION); 893 UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LE); 894 UINT16_TO_BE_STREAM (p, CE_T4T_MAX_LC); 895 896 /* Mandatory NDEF File Control TLV */ 897 UINT8_TO_BE_STREAM (p, T4T_NDEF_FILE_CONTROL_TYPE); /* type */ 898 UINT8_TO_BE_STREAM (p, T4T_FILE_CONTROL_LENGTH); /* length */ 899 UINT16_TO_BE_STREAM (p, CE_T4T_MANDATORY_NDEF_FILE_ID); /* file ID */ 900 UINT16_TO_BE_STREAM (p, ndef_msg_max + T4T_FILE_LENGTH_SIZE); /* max NDEF file size */ 901 UINT8_TO_BE_STREAM (p, T4T_FC_READ_ACCESS); /* read access */ 902 903 if (read_only) 904 { 905 UINT8_TO_BE_STREAM (p, T4T_FC_NO_WRITE_ACCESS); /* read only */ 906 p_t4t->status |= CE_T4T_STATUS_NDEF_FILE_READ_ONLY; 907 } 908 else 909 { 910 UINT8_TO_BE_STREAM (p, T4T_FC_WRITE_ACCESS); /* write access */ 911 p_t4t->status &= ~ (CE_T4T_STATUS_NDEF_FILE_READ_ONLY); 912 } 913 914 /* set mandatory NDEF file */ 915 p_t4t->p_ndef_msg = p_ndef_msg; 916 p_t4t->nlen = ndef_msg_len; 917 p_t4t->max_file_size = ndef_msg_max + T4T_FILE_LENGTH_SIZE; 918 919 /* Initialize scratch buffer */ 920 p_t4t->p_scratch_buf = p_scratch_buf; 921 922 if (p_scratch_buf) 923 { 924 memcpy (p_scratch_buf, p_ndef_msg, ndef_msg_len); 925 } 926 927 return NFC_STATUS_OK; 928} 929 930/******************************************************************************* 931** 932** Function CE_T4tRegisterAID 933** 934** Description Register AID in CE T4T 935** 936** aid_len: length of AID (up to NFC_MAX_AID_LEN) 937** p_aid: AID 938** p_cback: Raw frame will be forwarded with CE_RAW_FRAME_EVT 939** 940** Returns tCE_T4T_AID_HANDLE if successful, 941** CE_T4T_AID_HANDLE_INVALID otherwisse 942** 943*******************************************************************************/ 944tCE_T4T_AID_HANDLE CE_T4tRegisterAID (UINT8 aid_len, UINT8 *p_aid, tCE_CBACK *p_cback) 945{ 946 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 947 UINT8 xx; 948 949 /* Handle registering callback for wildcard AID (all AIDs) */ 950 if (aid_len == 0) 951 { 952 CE_TRACE_API0 ("CE_T4tRegisterAID (): registering callback for wildcard AID "); 953 954 /* Check if a wildcard callback is already registered (only one is allowed) */ 955 if (p_t4t->p_wildcard_aid_cback != NULL) 956 { 957 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): only one wildcard AID can be registered at time."); 958 return CE_T4T_AID_HANDLE_INVALID; 959 } 960 961 CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered (for wildcard AID)", CE_T4T_WILDCARD_AID_HANDLE); 962 p_t4t->p_wildcard_aid_cback = p_cback; 963 return CE_T4T_WILDCARD_AID_HANDLE; 964 } 965 966 967 CE_TRACE_API5 ("CE_T4tRegisterAID () AID [%02X%02X%02X%02X...], %d bytes", 968 *p_aid, *(p_aid+1), *(p_aid+2), *(p_aid+3), aid_len); 969 970 if (aid_len > NFC_MAX_AID_LEN) 971 { 972 CE_TRACE_ERROR1 ("CE_T4tRegisterAID (): AID is up to %d bytes", NFC_MAX_AID_LEN); 973 return CE_T4T_AID_HANDLE_INVALID; 974 } 975 976 if (p_cback == NULL) 977 { 978 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): callback must be provided"); 979 return CE_T4T_AID_HANDLE_INVALID; 980 } 981 982 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) 983 { 984 if ( (p_t4t->reg_aid[xx].aid_len == aid_len) 985 &&(!(memcmp(p_t4t->reg_aid[xx].aid, p_aid, aid_len))) ) 986 { 987 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): already registered"); 988 return CE_T4T_AID_HANDLE_INVALID; 989 } 990 } 991 992 for (xx = 0; xx < CE_T4T_MAX_REG_AID; xx++) 993 { 994 if (p_t4t->reg_aid[xx].aid_len == 0) 995 { 996 p_t4t->reg_aid[xx].aid_len = aid_len; 997 p_t4t->reg_aid[xx].p_cback = p_cback; 998 memcpy (p_t4t->reg_aid[xx].aid, p_aid, aid_len); 999 break; 1000 } 1001 } 1002 1003 if (xx >= CE_T4T_MAX_REG_AID) 1004 { 1005 CE_TRACE_ERROR0 ("CE_T4tRegisterAID (): No resource"); 1006 return CE_T4T_AID_HANDLE_INVALID; 1007 } 1008 else 1009 { 1010 CE_TRACE_DEBUG1 ("CE_T4tRegisterAID (): handle 0x%02x registered", xx); 1011 } 1012 1013 return (xx); 1014} 1015 1016/******************************************************************************* 1017** 1018** Function CE_T4tDeregisterAID 1019** 1020** Description Deregister AID in CE T4T 1021** 1022** Returns NFC_STATUS_OK if success 1023** 1024*******************************************************************************/ 1025NFC_API extern void CE_T4tDeregisterAID (tCE_T4T_AID_HANDLE aid_handle) 1026{ 1027 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 1028 1029 CE_TRACE_API1 ("CE_T4tDeregisterAID () handle 0x%02x", aid_handle); 1030 1031 /* Check if deregistering wildcard AID */ 1032 if (aid_handle == CE_T4T_WILDCARD_AID_HANDLE) 1033 { 1034 if (p_t4t->p_wildcard_aid_cback != NULL) 1035 { 1036 p_t4t->p_wildcard_aid_cback = NULL; 1037 } 1038 else 1039 { 1040 CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle"); 1041 } 1042 return; 1043 } 1044 1045 /* Deregister AID */ 1046 if ((aid_handle >= CE_T4T_MAX_REG_AID) || (p_t4t->reg_aid[aid_handle].aid_len==0)) 1047 { 1048 CE_TRACE_ERROR0 ("CE_T4tDeregisterAID (): Invalid handle"); 1049 } 1050 else 1051 { 1052 p_t4t->reg_aid[aid_handle].aid_len = 0; 1053 p_t4t->reg_aid[aid_handle].p_cback = NULL; 1054 } 1055} 1056 1057/******************************************************************************* 1058** 1059** Function CE_T4TTestSetCC 1060** 1061** Description Set fields in Capability Container File for testing 1062** 1063** Returns NFC_STATUS_OK if success 1064** 1065*******************************************************************************/ 1066tNFC_STATUS CE_T4TTestSetCC (UINT16 cc_len, 1067 UINT8 version, 1068 UINT16 max_le, 1069 UINT16 max_lc) 1070{ 1071#if (CE_TEST_INCLUDED == TRUE) 1072 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 1073 UINT8 *p; 1074 1075 CE_TRACE_DEBUG4 ("CE_T4TTestSetCC (): CCLen:0x%04X, Ver:0x%02X, MaxLe:0x%04X, MaxLc:0x%04X", 1076 cc_len, version, max_le, max_lc); 1077 1078 /* CC file */ 1079 p = p_t4t->cc_file; 1080 1081 if (cc_len != 0xFFFF) 1082 { 1083 UINT16_TO_BE_STREAM (p, cc_len); 1084 } 1085 else 1086 p += 2; 1087 1088 if (version != 0xFF) 1089 { 1090 mapping_aid_test_enabled = TRUE; 1091 if (version == T4T_VERSION_1_0) 1092 ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x00; 1093 else if (version == T4T_VERSION_2_0) 1094 ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0x01; 1095 else /* Undefined version */ 1096 ce_test_tag_app_id[T4T_V20_NDEF_TAG_AID_LEN - 1] = 0xFF; 1097 1098 UINT8_TO_BE_STREAM (p, version); 1099 } 1100 else 1101 { 1102 mapping_aid_test_enabled = FALSE; 1103 p += 1; 1104 } 1105 1106 if (max_le != 0xFFFF) 1107 { 1108 UINT16_TO_BE_STREAM (p, max_le); 1109 } 1110 else 1111 p += 2; 1112 1113 if (max_lc != 0xFFFF) 1114 { 1115 UINT16_TO_BE_STREAM (p, max_lc); 1116 } 1117 else 1118 p += 2; 1119 1120 return NFC_STATUS_OK; 1121#else 1122 return NFC_STATUS_FAILED; 1123#endif 1124} 1125 1126/******************************************************************************* 1127** 1128** Function CE_T4TTestSetNDEFCtrlTLV 1129** 1130** Description Set fields in NDEF File Control TLV for testing 1131** 1132** Returns NFC_STATUS_OK if success 1133** 1134*******************************************************************************/ 1135tNFC_STATUS CE_T4TTestSetNDEFCtrlTLV (UINT8 type, 1136 UINT8 length, 1137 UINT16 file_id, 1138 UINT16 max_file_size, 1139 UINT8 read_access, 1140 UINT8 write_access) 1141{ 1142#if (CE_TEST_INCLUDED == TRUE) 1143 tCE_T4T_MEM *p_t4t = &ce_cb.mem.t4t; 1144 UINT8 *p; 1145 1146 CE_TRACE_DEBUG6 ("CE_T4TTestSetNDEFCtrlTLV (): type:0x%02X, len:0x%02X, FileID:0x%04X, MaxFile:0x%04X, RdAcc:0x%02X, WrAcc:0x%02X", 1147 type, length, file_id, max_file_size, read_access, write_access); 1148 1149 /* NDEF File control TLV */ 1150 p = p_t4t->cc_file + T4T_FC_TLV_OFFSET_IN_CC; 1151 1152 if (type != 0xFF) 1153 { 1154 UINT8_TO_BE_STREAM (p, type); 1155 } 1156 else 1157 p += 1; 1158 1159 if (length != 0xFF) 1160 { 1161 UINT8_TO_BE_STREAM (p, length); 1162 } 1163 else 1164 p += 1; 1165 1166 if (file_id != 0xFFFF) 1167 { 1168 UINT16_TO_BE_STREAM (p, file_id); 1169 } 1170 else 1171 p += 2; 1172 1173 if (max_file_size != 0xFFFF) 1174 { 1175 UINT16_TO_BE_STREAM (p, max_file_size); 1176 } 1177 else 1178 p += 2; 1179 1180 if (read_access != 0xFF) 1181 { 1182 UINT8_TO_BE_STREAM (p, read_access); 1183 } 1184 else 1185 p += 1; 1186 1187 if (write_access != 0xFF) 1188 { 1189 UINT8_TO_BE_STREAM (p, write_access); 1190 } 1191 else 1192 p += 1; 1193 1194 return NFC_STATUS_OK; 1195#else 1196 return NFC_STATUS_FAILED; 1197#endif 1198} 1199#endif /* NFC_INCLUDED == TRUE */ 1200