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