ce_t3t.c revision a24be4f06674b2707b57904deaa0dff5a95823bd
1/****************************************************************************** 2 * 3 * Copyright (C) 2010-2014 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 20/****************************************************************************** 21 * 22 * This file contains the implementation for Type 3 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 39enum { 40 CE_T3T_COMMAND_INVALID, 41 CE_T3T_COMMAND_NFC_FORUM, 42 CE_T3T_COMMAND_FELICA 43}; 44 45/* T3T CE states */ 46enum { 47 CE_T3T_STATE_NOT_ACTIVATED, 48 CE_T3T_STATE_IDLE, 49 CE_T3T_STATE_UPDATING 50}; 51 52/* Bitmasks to indicate type of UPDATE */ 53#define CE_T3T_UPDATE_FL_NDEF_UPDATE_START 0x01 54#define CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT 0x02 55#define CE_T3T_UPDATE_FL_UPDATE 0x04 56 57/******************************************************************************* 58* Static constant definitions 59*******************************************************************************/ 60static const UINT8 CE_DEFAULT_LF_PMM[NCI_T3T_PMM_LEN] = {0x20, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; /* Default PMm param */ 61 62/******************************************************************************* 63** 64** Function ce_t3t_init 65** 66** Description Initialize tag-specific fields of ce control block 67** 68** Returns none 69** 70*******************************************************************************/ 71void ce_t3t_init (void) 72{ 73 memcpy (ce_cb.mem.t3t.local_pmm, CE_DEFAULT_LF_PMM, NCI_T3T_PMM_LEN); 74 ce_cb.mem.t3t.ndef_info.nbr = CE_T3T_DEFAULT_CHECK_MAXBLOCKS; 75 ce_cb.mem.t3t.ndef_info.nbw = CE_T3T_DEFAULT_UPDATE_MAXBLOCKS; 76} 77 78/******************************************************************************* 79** 80** Function ce_t3t_send_to_lower 81** 82** Description Send C-APDU to lower layer 83** 84** Returns none 85** 86*******************************************************************************/ 87void ce_t3t_send_to_lower (BT_HDR *p_msg) 88{ 89 UINT8 *p; 90 91 /* Set NFC-F SoD field (payload len + 1) */ 92 p_msg->offset -= 1; /* Point to SoD field */ 93 p = (UINT8 *) (p_msg+1) + p_msg->offset; 94 UINT8_TO_STREAM (p, (p_msg->len+1)); 95 p_msg->len += 1; /* Increment len to include SoD */ 96 97#if (BT_TRACE_PROTOCOL == TRUE) 98 DispT3TagMessage (p_msg, FALSE); 99#endif 100 101 if (NFC_SendData (NFC_RF_CONN_ID, p_msg) != NFC_STATUS_OK) 102 { 103 CE_TRACE_ERROR0 ("ce_t3t_send_to_lower (): NFC_SendData () failed"); 104 } 105} 106 107/******************************************************************************* 108** 109** Function ce_t3t_is_valid_opcode 110** 111** Description Valid opcode 112** 113** Returns Type of command 114** 115*******************************************************************************/ 116UINT8 ce_t3t_is_valid_opcode (UINT8 cmd_id) 117{ 118 UINT8 retval = CE_T3T_COMMAND_INVALID; 119 120 if ( (cmd_id == T3T_MSG_OPC_CHECK_CMD) 121 ||(cmd_id == T3T_MSG_OPC_UPDATE_CMD) ) 122 { 123 retval = CE_T3T_COMMAND_NFC_FORUM; 124 } 125 else if ( (cmd_id == T3T_MSG_OPC_POLL_CMD) 126 ||(cmd_id == T3T_MSG_OPC_REQ_SERVICE_CMD) 127 ||(cmd_id == T3T_MSG_OPC_REQ_RESPONSE_CMD) 128 ||(cmd_id == T3T_MSG_OPC_REQ_SYSTEMCODE_CMD) ) 129 { 130 retval = CE_T3T_COMMAND_FELICA; 131 } 132 133 return (retval); 134} 135 136/***************************************************************************** 137** 138** Function ce_t3t_get_rsp_buf 139** 140** Description Get a buffer for sending T3T messages 141** 142** Returns BT_HDR * 143** 144*****************************************************************************/ 145BT_HDR *ce_t3t_get_rsp_buf (void) 146{ 147 BT_HDR *p_cmd_buf; 148 149 if ((p_cmd_buf = (BT_HDR *) GKI_getpoolbuf (NFC_CE_POOL_ID)) != NULL) 150 { 151 /* Reserve offset for NCI_DATA_HDR and NFC-F Sod (LEN) field */ 152 p_cmd_buf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + 1; 153 p_cmd_buf->len = 0; 154 } 155 156 return (p_cmd_buf); 157} 158 159/******************************************************************************* 160** 161** Function ce_t3t_send_rsp 162** 163** Description Send response to reader/writer 164** 165** Returns none 166** 167*******************************************************************************/ 168void ce_t3t_send_rsp (tCE_CB *p_ce_cb, UINT8 *p_nfcid2, UINT8 opcode, UINT8 status1, UINT8 status2) 169{ 170 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 171 BT_HDR *p_rsp_msg; 172 UINT8 *p_dst, *p_rsp_start; 173 174 /* If p_nfcid2 is NULL, then used activated NFCID2 */ 175 if (p_nfcid2 == NULL) 176 { 177 p_nfcid2 = p_cb->local_nfcid2; 178 } 179 180 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 181 { 182 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 183 184 /* Response Code */ 185 UINT8_TO_STREAM (p_dst, opcode); 186 187 /* Manufacturer ID */ 188 ARRAY_TO_STREAM (p_dst, p_nfcid2, NCI_RF_F_UID_LEN); 189 190 /* Status1 and Status2 */ 191 UINT8_TO_STREAM (p_dst, status1); 192 UINT8_TO_STREAM (p_dst, status2); 193 194 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 195 ce_t3t_send_to_lower (p_rsp_msg); 196 } 197 else 198 { 199 CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message"); 200 } 201} 202 203/******************************************************************************* 204** 205** Function ce_t3t_handle_update_cmd 206** 207** Description Handle UPDATE command from reader/writer 208** 209** Returns none 210** 211*******************************************************************************/ 212void ce_t3t_handle_update_cmd (tCE_CB *p_ce_cb, BT_HDR *p_cmd_msg) 213{ 214 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 215 UINT8 *p_temp; 216 UINT8 *p_block_list = p_cb->cur_cmd.p_block_list_start; 217 UINT8 *p_block_data = p_cb->cur_cmd.p_block_data_start; 218 UINT8 i, j, bl0; 219 UINT16 block_number, service_code, checksum, checksum_rx; 220 UINT32 newlen_hiword; 221 tCE_T3T_NDEF_INFO ndef_info; 222 tNFC_STATUS nfc_status = NFC_STATUS_OK; 223 UINT8 update_flags = 0; 224 tCE_UPDATE_INFO update_info; 225 226 /* If in idle state, notify app that update is starting */ 227 if (p_cb->state == CE_T3T_STATE_IDLE) 228 { 229 p_cb->state = CE_T3T_STATE_UPDATING; 230 } 231 232 for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) 233 { 234 /* Read byte0 of block list */ 235 STREAM_TO_UINT8 (bl0, p_block_list); 236 237 if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) 238 { 239 STREAM_TO_UINT8 (block_number, p_block_list); 240 } 241 else 242 { 243 STREAM_TO_UINT16 (block_number, p_block_list); 244 } 245 246 /* Read the block from memory */ 247 service_code = p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK]; 248 249 /* Reject UPDATE command if service code=T3T_MSG_NDEF_SC_RO */ 250 if (service_code == T3T_MSG_NDEF_SC_RO) 251 { 252 /* Error: invalid block number to update */ 253 CE_TRACE_ERROR0 ("CE: UPDATE request using read-only service"); 254 nfc_status = NFC_STATUS_FAILED; 255 break; 256 } 257 258 /* Check for NDEF */ 259 if (service_code == T3T_MSG_NDEF_SC_RW) 260 { 261 if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbw) 262 { 263 CE_TRACE_ERROR2 ("CE: Requested too many blocks to update (requested: %i, max: %i)", p_cb->cur_cmd.num_blocks, p_cb->ndef_info.nbw); 264 nfc_status = NFC_STATUS_FAILED; 265 break; 266 } 267 else if (p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RO) 268 { 269 CE_TRACE_ERROR0 ("CE: error: write-request to read-only NDEF message."); 270 nfc_status = NFC_STATUS_FAILED; 271 break; 272 } 273 else if (block_number == 0) 274 { 275 CE_TRACE_DEBUG2 ("CE: Update sc 0x%04x block %i.", service_code, block_number); 276 277 /* Special caes: NDEF block0 is the ndef attribute block */ 278 p_temp = p_block_data; 279 STREAM_TO_UINT8 (ndef_info.version, p_block_data); 280 p_block_data+=8; /* Ignore nbr,nbw,maxb,and reserved (reader/writer not allowed to update this) */ 281 STREAM_TO_UINT8 (ndef_info.writef, p_block_data); 282 p_block_data++; /* Ignore rwflag (reader/writer not allowed to update this) */ 283 STREAM_TO_UINT8 (newlen_hiword, p_block_data); 284 BE_STREAM_TO_UINT16 (ndef_info.ln, p_block_data); 285 ndef_info.ln += (newlen_hiword<<16); 286 BE_STREAM_TO_UINT16 (checksum_rx, p_block_data); 287 288 checksum=0; 289 for (j=0; j<T3T_MSG_NDEF_ATTR_INFO_SIZE; j++) 290 { 291 checksum+=p_temp[j]; 292 } 293 294 /* Compare calcuated checksum with received checksum */ 295 if (checksum != checksum_rx) 296 { 297 CE_TRACE_ERROR0 ("CE: Checksum failed for NDEF attribute block."); 298 nfc_status = NFC_STATUS_FAILED; 299 } 300 else 301 { 302 /* Update NDEF attribute block (only allowed to update current length and writef fields) */ 303 p_cb->ndef_info.scratch_ln = ndef_info.ln; 304 p_cb->ndef_info.scratch_writef = ndef_info.writef; 305 306 /* If writef=0 indicates completion of NDEF update */ 307 if (ndef_info.writef == 0) 308 { 309 update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT; 310 } 311 /* writef=1 indicates start of NDEF update */ 312 else 313 { 314 update_flags |= CE_T3T_UPDATE_FL_NDEF_UPDATE_START; 315 } 316 } 317 } 318 else 319 { 320 CE_TRACE_DEBUG2 ("CE: Udpate sc 0x%04x block %i.", service_code, block_number); 321 322 /* Verify that block_number is within NDEF memory */ 323 if (block_number > p_cb->ndef_info.nmaxb) 324 { 325 /* Error: invalid block number to update */ 326 CE_TRACE_ERROR2 ("CE: Requested invalid NDEF block number to update %i (max is %i).", block_number, p_cb->ndef_info.nmaxb); 327 nfc_status = NFC_STATUS_FAILED; 328 break; 329 } 330 else 331 { 332 /* Update NDEF memory block */ 333 STREAM_TO_ARRAY ((&p_cb->ndef_info.p_scratch_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), p_block_data, T3T_MSG_BLOCKSIZE); 334 } 335 336 /* Set flag to indicate that this UPDATE contained at least one block */ 337 update_flags |= CE_T3T_UPDATE_FL_UPDATE; 338 } 339 } 340 else 341 { 342 /* Error: invalid service code */ 343 CE_TRACE_ERROR1 ("CE: Requested invalid service code: 0x%04x.", service_code); 344 nfc_status = NFC_STATUS_FAILED; 345 break; 346 } 347 } 348 349 /* Send appropriate response to reader/writer */ 350 if (nfc_status == NFC_STATUS_OK) 351 { 352 ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, T3T_MSG_RSP_STATUS_OK, T3T_MSG_RSP_STATUS_OK); 353 } 354 else 355 { 356 ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, T3T_MSG_RSP_STATUS_ERROR, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 357 p_cb->state = CE_T3T_STATE_IDLE; 358 } 359 360 361 /* Notify the app of what got updated */ 362 if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_START) 363 { 364 /* NDEF attribute got updated with WriteF=TRUE */ 365 p_ce_cb->p_cback (CE_T3T_NDEF_UPDATE_START_EVT, NULL); 366 } 367 368 if (update_flags & CE_T3T_UPDATE_FL_UPDATE) 369 { 370 /* UPDATE message contained at least one non-NDEF block */ 371 p_ce_cb->p_cback (CE_T3T_UPDATE_EVT, NULL); 372 } 373 374 375 if (update_flags & CE_T3T_UPDATE_FL_NDEF_UPDATE_CPLT) 376 { 377 /* NDEF attribute got updated with WriteF=FALSE */ 378 update_info.status = nfc_status; 379 update_info.p_data = p_cb->ndef_info.p_scratch_buf; 380 update_info.length = p_cb->ndef_info.scratch_ln; 381 p_cb->state = CE_T3T_STATE_IDLE; 382 p_ce_cb->p_cback (CE_T3T_NDEF_UPDATE_CPLT_EVT, (tCE_DATA *) &update_info); 383 } 384 385 GKI_freebuf (p_cmd_msg); 386} 387 388/******************************************************************************* 389** 390** Function ce_t3t_handle_check_cmd 391** 392** Description Handle CHECK command from reader/writer 393** 394** Returns Nothing 395** 396*******************************************************************************/ 397void ce_t3t_handle_check_cmd (tCE_CB *p_ce_cb, BT_HDR *p_cmd_msg) 398{ 399 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 400 BT_HDR *p_rsp_msg; 401 UINT8 *p_rsp_start; 402 UINT8 *p_dst, *p_temp, *p_status; 403 UINT8 *p_src = p_cb->cur_cmd.p_block_list_start; 404 UINT8 i, bl0; 405 UINT8 ndef_writef; 406 UINT32 ndef_len; 407 UINT16 block_number, service_code, checksum; 408 409 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 410 { 411 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 412 413 /* Response Code */ 414 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_CHECK_RSP); 415 416 /* Manufacturer ID */ 417 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 418 419 /* Save pointer to start of status field */ 420 p_status = p_dst; 421 422 /* Status1 and Status2 (assume success initially */ 423 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_OK); 424 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_OK); 425 UINT8_TO_STREAM (p_dst, p_cb->cur_cmd.num_blocks); 426 427 for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) 428 { 429 /* Read byte0 of block list */ 430 STREAM_TO_UINT8 (bl0, p_src); 431 432 if (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) 433 { 434 STREAM_TO_UINT8 (block_number, p_src); 435 } 436 else 437 { 438 STREAM_TO_UINT16 (block_number, p_src); 439 } 440 441 /* Read the block from memory */ 442 service_code = p_cb->cur_cmd.service_code_list[bl0 & T3T_MSG_SERVICE_LIST_MASK]; 443 444 /* Check for NDEF */ 445 if ((service_code == T3T_MSG_NDEF_SC_RO) || (service_code == T3T_MSG_NDEF_SC_RW)) 446 { 447 /* Verify Nbr (NDEF only) */ 448 if (p_cb->cur_cmd.num_blocks > p_cb->ndef_info.nbr) 449 { 450 /* Error: invalid number of blocks to check */ 451 CE_TRACE_ERROR2 ("CE: Requested too many blocks to check (requested: %i, max: %i)", p_cb->cur_cmd.num_blocks, p_cb->ndef_info.nbr); 452 453 p_dst = p_status; 454 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR); 455 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 456 break; 457 } 458 else if (block_number == 0) 459 { 460 /* Special caes: NDEF block0 is the ndef attribute block */ 461 p_temp = p_dst; 462 463 /* For rw ndef, use scratch buffer's attributes (in case reader/writer had previously updated NDEF) */ 464 if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) && (p_cb->ndef_info.p_scratch_buf)) 465 { 466 ndef_writef = p_cb->ndef_info.scratch_writef; 467 ndef_len = p_cb->ndef_info.scratch_ln; 468 } 469 else 470 { 471 ndef_writef = p_cb->ndef_info.writef; 472 ndef_len = p_cb->ndef_info.ln; 473 } 474 475 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.version); 476 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.nbr); 477 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.nbw); 478 UINT16_TO_BE_STREAM (p_dst, p_cb->ndef_info.nmaxb); 479 UINT32_TO_STREAM (p_dst, 0); 480 UINT8_TO_STREAM (p_dst, ndef_writef); 481 UINT8_TO_STREAM (p_dst, p_cb->ndef_info.rwflag); 482 UINT8_TO_STREAM (p_dst, (ndef_len >> 16 & 0xFF)); 483 UINT16_TO_BE_STREAM (p_dst, (ndef_len & 0xFFFF)); 484 485 checksum = 0; 486 for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++) 487 { 488 checksum+=p_temp[i]; 489 } 490 UINT16_TO_BE_STREAM (p_dst, checksum); 491 } 492 else 493 { 494 /* Verify that block_number is within NDEF memory */ 495 if (block_number > p_cb->ndef_info.nmaxb) 496 { 497 /* Invalid block number */ 498 p_dst = p_status; 499 500 CE_TRACE_ERROR1 ("CE: Requested block number to check %i.", block_number); 501 502 /* Error: invalid number of blocks to check */ 503 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR); 504 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 505 break; 506 } 507 else 508 { 509 /* If card is RW, then read from the scratch buffer (so reader/write can read back what it had just written */ 510 if ((p_cb->ndef_info.rwflag == T3T_MSG_NDEF_RWFLAG_RW) && (p_cb->ndef_info.p_scratch_buf)) 511 { 512 ARRAY_TO_STREAM (p_dst, (&p_cb->ndef_info.p_scratch_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), T3T_MSG_BLOCKSIZE); 513 } 514 else 515 { 516 ARRAY_TO_STREAM (p_dst, (&p_cb->ndef_info.p_buf[(block_number-1) * T3T_MSG_BLOCKSIZE]), T3T_MSG_BLOCKSIZE); 517 } 518 } 519 } 520 } 521 else 522 { 523 /* Error: invalid service code */ 524 CE_TRACE_ERROR1 ("CE: Requested invalid service code: 0x%04x.", service_code); 525 526 p_dst = p_status; 527 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS_ERROR); 528 UINT8_TO_STREAM (p_dst, T3T_MSG_RSP_STATUS2_ERROR_MEMORY); 529 break; 530 } 531 } 532 533 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 534 ce_t3t_send_to_lower (p_rsp_msg); 535 } 536 else 537 { 538 CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message"); 539 } 540 541 GKI_freebuf (p_cmd_msg); 542} 543 544 545/******************************************************************************* 546** 547** Function ce_t3t_handle_non_nfc_forum_cmd 548** 549** Description Handle POLL command from reader/writer 550** 551** Returns Nothing 552** 553*******************************************************************************/ 554void ce_t3t_handle_non_nfc_forum_cmd (tCE_CB *p_mem_cb, UINT8 cmd_id, BT_HDR *p_cmd_msg) 555{ 556 tCE_T3T_MEM *p_cb = &p_mem_cb->mem.t3t; 557 BT_HDR *p_rsp_msg; 558 UINT8 *p_rsp_start; 559 UINT8 *p_dst; 560 UINT8 *p = (UINT8 *) (p_cmd_msg +1) + p_cmd_msg->offset; 561 UINT16 sc; 562 UINT8 rc; 563 BOOLEAN send_response = TRUE; 564 565 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 566 { 567 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 568 569 switch (cmd_id) 570 { 571 case T3T_MSG_OPC_POLL_CMD: 572 /* Get system code and RC */ 573 /* Skip over sod and cmd_id */ 574 p+=2; 575 BE_STREAM_TO_UINT16 (sc, p); 576 STREAM_TO_UINT8 (rc, p); 577 578 /* If requesting wildcard system code, or specifically our system code, then send POLL response */ 579 if ((sc == 0xFFFF) || (sc == p_cb->system_code)) 580 { 581 /* Response Code */ 582 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_POLL_RSP); 583 584 /* Manufacturer ID */ 585 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 586 587 /* Manufacturer Parameter PMm */ 588 ARRAY_TO_STREAM (p_dst, p_cb->local_pmm, NCI_T3T_PMM_LEN); 589 590 /* If requesting system code */ 591 if (rc == T3T_POLL_RC_SC) 592 { 593 UINT16_TO_BE_STREAM (p_dst, p_cb->system_code); 594 } 595 } 596 else 597 { 598 send_response = FALSE; 599 } 600 break; 601 602 603 case T3T_MSG_OPC_REQ_RESPONSE_CMD: 604 /* Response Code */ 605 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_REQ_RESPONSE_RSP); 606 607 /* Manufacturer ID */ 608 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 609 610 /* Mode */ 611 UINT8_TO_STREAM (p_dst, 0); 612 break; 613 614 case T3T_MSG_OPC_REQ_SYSTEMCODE_CMD: 615 /* Response Code */ 616 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_REQ_SYSTEMCODE_RSP); 617 618 /* Manufacturer ID */ 619 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 620 621 /* Number of system codes */ 622 UINT8_TO_STREAM (p_dst, 1); 623 624 /* system codes */ 625 UINT16_TO_BE_STREAM (p_dst, T3T_SYSTEM_CODE_NDEF); 626 break; 627 628 629 case T3T_MSG_OPC_REQ_SERVICE_CMD: 630 default: 631 /* Unhandled command */ 632 CE_TRACE_ERROR1 ("Unhandled CE opcode: %02x", cmd_id); 633 send_response = FALSE; 634 break; 635 } 636 637 if (send_response) 638 { 639 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 640 ce_t3t_send_to_lower (p_rsp_msg); 641 } 642 else 643 { 644 GKI_freebuf (p_rsp_msg); 645 } 646 } 647 else 648 { 649 CE_TRACE_ERROR0 ("CE: Unable to allocat buffer for response message"); 650 } 651 GKI_freebuf (p_cmd_msg); 652} 653 654/******************************************************************************* 655** 656** Function ce_t3t_data_cback 657** 658** Description This callback function receives the data from NFCC. 659** 660** Returns none 661** 662*******************************************************************************/ 663void ce_t3t_data_cback (UINT8 conn_id, tNFC_DATA_CEVT *p_data) 664{ 665 tCE_CB *p_ce_cb = &ce_cb; 666 tCE_T3T_MEM *p_cb = &p_ce_cb->mem.t3t; 667 BT_HDR *p_msg = p_data->p_data; 668 tCE_DATA ce_data; 669 UINT8 cmd_id, bl0, entry_len, i; 670 UINT8 *p_nfcid2 = NULL; 671 UINT8 *p = (UINT8 *) (p_msg +1) + p_msg->offset; 672 UINT8 cmd_nfcid2[NCI_RF_F_UID_LEN]; 673 UINT16 block_list_start_offset, remaining; 674 BOOLEAN msg_processed = FALSE; 675 BOOLEAN block_list_ok; 676 UINT8 sod; 677 UINT8 cmd_type; 678 679#if (BT_TRACE_PROTOCOL == TRUE) 680 DispT3TagMessage (p_msg, TRUE); 681#endif 682 683 /* If activate system code is not NDEF, or if no local NDEF contents was set, then pass data up to the app */ 684 if ((p_cb->system_code != T3T_SYSTEM_CODE_NDEF) || (!p_cb->ndef_info.initialized)) 685 { 686 ce_data.raw_frame.status = p_data->status; 687 ce_data.raw_frame.p_data = p_msg; 688 p_ce_cb->p_cback (CE_T3T_RAW_FRAME_EVT, &ce_data); 689 return; 690 } 691 692 /* Verify that message contains at least Sod and cmd_id */ 693 if (p_msg->len < 2) 694 { 695 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid length: %i)", p_msg->len); 696 } 697 else 698 { 699 700 /* Get and validate command opcode */ 701 STREAM_TO_UINT8 (sod, p); 702 STREAM_TO_UINT8 (cmd_id, p); 703 704 /* Valid command and message length */ 705 cmd_type = ce_t3t_is_valid_opcode (cmd_id); 706 if (cmd_type == CE_T3T_COMMAND_INVALID) 707 { 708 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid command: 0x%02X)", cmd_id); 709 } 710 else if (cmd_type == CE_T3T_COMMAND_FELICA) 711 { 712 ce_t3t_handle_non_nfc_forum_cmd (p_ce_cb, cmd_id, p_msg); 713 msg_processed = TRUE; 714 } 715 else 716 { 717 /* Verify that message contains at least NFCID2 and NUM services */ 718 if (p_msg->len < T3T_MSG_CMD_COMMON_HDR_LEN) 719 { 720 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid length: %i)", p_msg->len); 721 } 722 else 723 { 724 /* Handle NFC_FORUM command (UPDATE or CHECK) */ 725 STREAM_TO_ARRAY (cmd_nfcid2, p, NCI_RF_F_UID_LEN); 726 STREAM_TO_UINT8 (p_cb->cur_cmd.num_services, p); 727 728 /* Calculate offset of block-list-start */ 729 block_list_start_offset = T3T_MSG_CMD_COMMON_HDR_LEN + 2*p_cb->cur_cmd.num_services + 1; 730 731 if (p_cb->state == CE_T3T_STATE_NOT_ACTIVATED) 732 { 733 CE_TRACE_ERROR2 ("CE: received command 0x%02X while in bad state (%i))", cmd_id, p_cb->state); 734 } 735 else if (memcmp (cmd_nfcid2, p_cb->local_nfcid2, NCI_RF_F_UID_LEN) != 0) 736 { 737 CE_TRACE_ERROR0 ("CE: received invalid T3t message (invalid NFCID2)"); 738 p_nfcid2 = cmd_nfcid2; /* respond with ERROR using the NFCID2 from the command message */ 739 } 740 else if (p_msg->len < block_list_start_offset) 741 { 742 /* Does not have minimum (including number_of_blocks field) */ 743 CE_TRACE_ERROR0 ("CE: incomplete message"); 744 } 745 else 746 { 747 /* Parse service code list */ 748 for (i = 0; i < p_cb->cur_cmd.num_services; i++) 749 { 750 STREAM_TO_UINT16 (p_cb->cur_cmd.service_code_list[i], p); 751 } 752 753 /* Verify that block list */ 754 block_list_ok = TRUE; 755 STREAM_TO_UINT8 (p_cb->cur_cmd.num_blocks, p); 756 remaining = p_msg->len - block_list_start_offset; 757 p_cb->cur_cmd.p_block_list_start = p; 758 for (i = 0; i < p_cb->cur_cmd.num_blocks; i++) 759 { 760 /* Each entry is at lease 2 bytes long */ 761 if (remaining < 2) 762 { 763 /* Unexpected end of message (while reading block-list) */ 764 CE_TRACE_ERROR0 ("CE: received invalid T3t message (unexpected end of block-list)"); 765 block_list_ok = FALSE; 766 break; 767 } 768 769 /* Get byte0 of block-list entry */ 770 bl0 = *p; 771 772 /* Validate service code index and size of block-list */ 773 if ((bl0 & T3T_MSG_SERVICE_LIST_MASK) >= p_cb->cur_cmd.num_services) 774 { 775 /* Invalid service code */ 776 CE_TRACE_ERROR1 ("CE: received invalid T3t message (invalid service index: %i)", (bl0 & T3T_MSG_SERVICE_LIST_MASK)); 777 block_list_ok = FALSE; 778 break; 779 } 780 else if ((!(bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT)) && (remaining < 3)) 781 { 782 /* Unexpected end of message (while reading 3-byte entry) */ 783 CE_TRACE_ERROR0 ("CE: received invalid T3t message (unexpected end of block-list)"); 784 block_list_ok = FALSE; 785 break; 786 } 787 788 /* Advance pointers to next block-list entry */ 789 entry_len = (bl0 & T3T_MSG_MASK_TWO_BYTE_BLOCK_DESC_FORMAT) ? 2 : 3; 790 p+=entry_len; 791 remaining-=entry_len; 792 } 793 794 /* Block list is verified. Call CHECK or UPDATE handler */ 795 if (block_list_ok) 796 { 797 p_cb->cur_cmd.p_block_data_start = p; 798 if (cmd_id == T3T_MSG_OPC_CHECK_CMD) 799 { 800 /* This is a CHECK command. Sanity check: there shouldn't be any more data remaining after reading block list */ 801 if (remaining) 802 { 803 CE_TRACE_ERROR1 ("CE: unexpected data after after CHECK command (#i bytes)", remaining); 804 } 805 ce_t3t_handle_check_cmd (p_ce_cb, p_msg); 806 msg_processed = TRUE; 807 } 808 else 809 { 810 /* This is an UPDATE command. See if message contains all the expected block data */ 811 if (remaining < p_cb->cur_cmd.num_blocks*T3T_MSG_BLOCKSIZE) 812 { 813 CE_TRACE_ERROR0 ("CE: unexpected end of block-data"); 814 } 815 else 816 { 817 ce_t3t_handle_update_cmd (p_ce_cb, p_msg); 818 msg_processed = TRUE; 819 } 820 } 821 } 822 } 823 } 824 } 825 } 826 827 if (!msg_processed) 828 { 829 ce_t3t_send_rsp (p_ce_cb, p_nfcid2, T3T_MSG_OPC_CHECK_RSP, T3T_MSG_RSP_STATUS_ERROR, T3T_MSG_RSP_STATUS2_ERROR_PROCESSING); 830 GKI_freebuf (p_msg); 831 } 832 833 834} 835 836/******************************************************************************* 837** 838** Function ce_t3t_conn_cback 839** 840** Description This callback function receives the events/data from NFCC. 841** 842** Returns none 843** 844*******************************************************************************/ 845void ce_t3t_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data) 846{ 847 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 848 849 CE_TRACE_DEBUG2 ("ce_t3t_conn_cback: conn_id=%i, evt=%i", conn_id, event); 850 851 switch (event) 852 { 853 case NFC_CONN_CREATE_CEVT: 854 break; 855 856 case NFC_CONN_CLOSE_CEVT: 857 p_cb->state = CE_T3T_STATE_NOT_ACTIVATED; 858 break; 859 860 case NFC_DATA_CEVT: 861 if (p_data->data.status == NFC_STATUS_OK) 862 { 863 ce_t3t_data_cback (conn_id, &p_data->data); 864 } 865 break; 866 867 case NFC_DEACTIVATE_CEVT: 868 p_cb->state = CE_T3T_STATE_NOT_ACTIVATED; 869 NFC_SetStaticRfCback (NULL); 870 break; 871 872 default: 873 break; 874 875 } 876} 877 878/******************************************************************************* 879** 880** Function ce_select_t3t 881** 882** Description Select Type 3 Tag 883** 884** Returns NFC_STATUS_OK if success 885** 886*******************************************************************************/ 887tNFC_STATUS ce_select_t3t (UINT16 system_code, UINT8 nfcid2[NCI_RF_F_UID_LEN]) 888{ 889 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 890 891 CE_TRACE_DEBUG0 ("ce_select_t3t ()"); 892 893 p_cb->state = CE_T3T_STATE_IDLE; 894 p_cb->system_code = system_code; 895 memcpy (p_cb->local_nfcid2, nfcid2, NCI_RF_F_UID_LEN); 896 897 NFC_SetStaticRfCback (ce_t3t_conn_cback); 898 return NFC_STATUS_OK; 899} 900 901 902/******************************************************************************* 903** 904** Function CE_T3tSetLocalNDEFMsg 905** 906** Description Initialise CE Type 3 Tag with mandatory NDEF message 907** 908** Returns NFC_STATUS_OK if success 909** 910*******************************************************************************/ 911tNFC_STATUS CE_T3tSetLocalNDEFMsg (BOOLEAN read_only, 912 UINT32 size_max, 913 UINT32 size_current, 914 UINT8 *p_buf, 915 UINT8 *p_scratch_buf) 916{ 917 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 918 919 CE_TRACE_API3 ("CE_T3tSetContent: ro=%i, size_max=%i, size_current=%i", read_only, size_max, size_current); 920 921 /* Verify scratch buffer was provided if NDEF message is read/write */ 922 if ((!read_only) && (!p_scratch_buf)) 923 { 924 CE_TRACE_ERROR0 ("CE_T3tSetLocalNDEFMsg (): p_scratch_buf cannot be NULL if not read-only"); 925 return NFC_STATUS_FAILED; 926 } 927 928 /* Check if disabling the local NDEF */ 929 if (!p_buf) 930 { 931 p_cb->ndef_info.initialized = FALSE; 932 } 933 /* Save ndef attributes */ 934 else 935 { 936 p_cb->ndef_info.initialized = TRUE; 937 p_cb->ndef_info.ln = size_current; /* Current length */ 938 p_cb->ndef_info.nmaxb = (UINT16) ((size_max + 15) / T3T_MSG_BLOCKSIZE); /* Max length (in blocks) */ 939 p_cb->ndef_info.rwflag = (read_only) ? T3T_MSG_NDEF_RWFLAG_RO : T3T_MSG_NDEF_RWFLAG_RW; 940 p_cb->ndef_info.writef = T3T_MSG_NDEF_WRITEF_OFF; 941 p_cb->ndef_info.version = 0x10; 942 p_cb->ndef_info.p_buf = p_buf; 943 p_cb->ndef_info.p_scratch_buf = p_scratch_buf; 944 945 /* Initiate scratch buffer with same contents as read-buffer */ 946 if (p_scratch_buf) 947 { 948 p_cb->ndef_info.scratch_ln = p_cb->ndef_info.ln; 949 p_cb->ndef_info.scratch_writef = T3T_MSG_NDEF_WRITEF_OFF; 950 memcpy (p_scratch_buf, p_buf, p_cb->ndef_info.ln); 951 } 952 } 953 954 return (NFC_STATUS_OK); 955} 956 957/******************************************************************************* 958** 959** Function CE_T3tSetLocalNDefParams 960** 961** Description Sets T3T-specific NDEF parameters. (Optional - if not 962** called, then CE will use default parameters) 963** 964** Returns NFC_STATUS_OK if success 965** 966*******************************************************************************/ 967tNFC_STATUS CE_T3tSetLocalNDefParams (UINT8 nbr, UINT8 nbw) 968{ 969 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 970 971 CE_TRACE_API2 ("CE_T3tSetLocalNDefParams: nbr=%i, nbw=%i", nbr, nbw); 972 973 /* Validate */ 974 if ((nbr > T3T_MSG_NUM_BLOCKS_CHECK_MAX) || (nbw>T3T_MSG_NUM_BLOCKS_UPDATE_MAX) || (nbr < 1) || (nbw < 1)) 975 { 976 CE_TRACE_ERROR0 ("CE_T3tSetLocalNDefParams: invalid params"); 977 return NFC_STATUS_FAILED; 978 } 979 980 p_cb->ndef_info.nbr = nbr; 981 p_cb->ndef_info.nbw = nbw; 982 983 return NFC_STATUS_OK; 984} 985 986/******************************************************************************* 987** 988** Function CE_T3tSendCheckRsp 989** 990** Description Send CHECK response message 991** 992** Returns NFC_STATUS_OK if success 993** 994*******************************************************************************/ 995tNFC_STATUS CE_T3tSendCheckRsp (UINT8 status1, UINT8 status2, UINT8 num_blocks, UINT8 *p_block_data) 996{ 997 tCE_T3T_MEM *p_cb = &ce_cb.mem.t3t; 998 tNFC_STATUS retval = NFC_STATUS_OK; 999 BT_HDR *p_rsp_msg; 1000 UINT8 *p_dst, *p_rsp_start; 1001 1002 CE_TRACE_API3 ("CE_T3tCheckRsp: status1=0x%02X, status2=0x%02X, num_blocks=%i", status1, status2, num_blocks); 1003 1004 /* Validate num_blocks */ 1005 if (num_blocks > T3T_MSG_NUM_BLOCKS_CHECK_MAX) 1006 { 1007 CE_TRACE_ERROR2 ("CE_T3tCheckRsp num_blocks (%i) exceeds maximum (%i)", num_blocks, T3T_MSG_NUM_BLOCKS_CHECK_MAX); 1008 return (NFC_STATUS_FAILED); 1009 } 1010 1011 if ((p_rsp_msg = ce_t3t_get_rsp_buf ()) != NULL) 1012 { 1013 p_dst = p_rsp_start = (UINT8 *) (p_rsp_msg+1) + p_rsp_msg->offset; 1014 1015 /* Response Code */ 1016 UINT8_TO_STREAM (p_dst, T3T_MSG_OPC_CHECK_RSP); 1017 1018 /* Manufacturer ID */ 1019 ARRAY_TO_STREAM (p_dst, p_cb->local_nfcid2, NCI_RF_F_UID_LEN); 1020 1021 /* Status1 and Status2 */ 1022 UINT8_TO_STREAM (p_dst, status1); 1023 UINT8_TO_STREAM (p_dst, status2); 1024 1025 if (status1 == T3T_MSG_RSP_STATUS_OK) 1026 { 1027 UINT8_TO_STREAM (p_dst, num_blocks); 1028 ARRAY_TO_STREAM (p_dst, p_block_data, (num_blocks * T3T_MSG_BLOCKSIZE)); 1029 } 1030 1031 p_rsp_msg->len = (UINT16) (p_dst - p_rsp_start); 1032 ce_t3t_send_to_lower (p_rsp_msg); 1033 } 1034 else 1035 { 1036 CE_TRACE_ERROR0 ("CE: Unable to allocate buffer for response message"); 1037 } 1038 1039 return (retval); 1040} 1041 1042/******************************************************************************* 1043** 1044** Function CE_T3tSendUpdateRsp 1045** 1046** Description Send UPDATE response message 1047** 1048** Returns NFC_STATUS_OK if success 1049** 1050*******************************************************************************/ 1051tNFC_STATUS CE_T3tSendUpdateRsp (UINT8 status1, UINT8 status2) 1052{ 1053 tNFC_STATUS retval = NFC_STATUS_OK; 1054 tCE_CB *p_ce_cb = &ce_cb; 1055 1056 CE_TRACE_API2 ("CE_T3tUpdateRsp: status1=0x%02X, status2=0x%02X", status1, status2); 1057 ce_t3t_send_rsp (p_ce_cb, NULL, T3T_MSG_OPC_UPDATE_RSP, status1, status2); 1058 1059 return (retval); 1060} 1061 1062#endif /* NFC_INCLUDED == TRUE */ 1063