1 /****************************************************************************** 2 * 3 * Copyright (C) 2011-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 * This file contains the action functions the NFA_CE state machine. 22 * 23 ******************************************************************************/ 24 #include <string.h> 25 #include "ce_api.h" 26 #include "ndef_utils.h" 27 #include "nfa_ce_int.h" 28 #include "nfa_dm_int.h" 29 #include "nfa_mem_co.h" 30 #include "nfa_sys_int.h" 31 #if (NFC_NFCEE_INCLUDED == TRUE) 32 #include "nfa_ee_int.h" 33 #endif 34 35 /***************************************************************************** 36 * Protocol-specific event handlers 37 *****************************************************************************/ 38 39 /******************************************************************************* 40 ** 41 ** Function nfa_ce_handle_t3t_evt 42 ** 43 ** Description Handler for Type-3 tag card emulation events 44 ** 45 ** Returns Nothing 46 ** 47 *******************************************************************************/ 48 void nfa_ce_handle_t3t_evt(tCE_EVENT event, tCE_DATA* p_ce_data) { 49 tNFA_CE_CB* p_cb = &nfa_ce_cb; 50 tNFA_CONN_EVT_DATA conn_evt; 51 52 NFA_TRACE_DEBUG1("nfa_ce_handle_t3t_evt: event 0x%x", event); 53 54 switch (event) { 55 case CE_T3T_NDEF_UPDATE_START_EVT: 56 /* Notify app using callback associated with the active ndef */ 57 if (p_cb->idx_cur_active == NFA_CE_LISTEN_INFO_IDX_NDEF) { 58 conn_evt.status = NFA_STATUS_OK; 59 (*p_cb->p_active_conn_cback)(NFA_CE_NDEF_WRITE_START_EVT, &conn_evt); 60 } else { 61 NFA_TRACE_ERROR0( 62 "nfa_ce_handle_t3t_evt: got CE_T3T_UPDATE_START_EVT, but no active " 63 "NDEF"); 64 } 65 break; 66 67 case CE_T3T_NDEF_UPDATE_CPLT_EVT: 68 /* Notify app using callback associated with the active ndef */ 69 if (p_cb->idx_cur_active == NFA_CE_LISTEN_INFO_IDX_NDEF) { 70 conn_evt.ndef_write_cplt.status = NFA_STATUS_OK; 71 conn_evt.ndef_write_cplt.len = p_ce_data->update_info.length; 72 conn_evt.ndef_write_cplt.p_data = p_ce_data->update_info.p_data; 73 (*p_cb->p_active_conn_cback)(NFA_CE_NDEF_WRITE_CPLT_EVT, &conn_evt); 74 } else { 75 NFA_TRACE_ERROR0( 76 "nfa_ce_handle_t3t_evt: got CE_T3T_UPDATE_CPLT_EVT, but no active " 77 "NDEF"); 78 } 79 break; 80 81 case CE_T3T_RAW_FRAME_EVT: 82 if (p_cb->idx_cur_active == NFA_CE_LISTEN_INFO_IDX_NDEF) { 83 conn_evt.data.status = p_ce_data->raw_frame.status; 84 conn_evt.data.p_data = (uint8_t*)(p_ce_data->raw_frame.p_data + 1) + 85 p_ce_data->raw_frame.p_data->offset; 86 conn_evt.data.len = p_ce_data->raw_frame.p_data->len; 87 (*p_cb->p_active_conn_cback)(NFA_DATA_EVT, &conn_evt); 88 } else { 89 conn_evt.ce_data.status = p_ce_data->raw_frame.status; 90 conn_evt.ce_data.handle = 91 (NFA_HANDLE_GROUP_CE | ((tNFA_HANDLE)p_cb->idx_cur_active)); 92 conn_evt.ce_data.p_data = (uint8_t*)(p_ce_data->raw_frame.p_data + 1) + 93 p_ce_data->raw_frame.p_data->offset; 94 conn_evt.ce_data.len = p_ce_data->raw_frame.p_data->len; 95 (*p_cb->p_active_conn_cback)(NFA_CE_DATA_EVT, &conn_evt); 96 } 97 GKI_freebuf(p_ce_data->raw_frame.p_data); 98 break; 99 100 default: 101 NFA_TRACE_DEBUG1("nfa_ce_handle_t3t_evt unhandled event=0x%02x", event); 102 break; 103 } 104 } 105 106 /******************************************************************************* 107 ** 108 ** Function nfa_ce_handle_t4t_evt 109 ** 110 ** Description Handler for Type-4 tag card emulation events (for NDEF case) 111 ** 112 ** Returns Nothing 113 ** 114 *******************************************************************************/ 115 void nfa_ce_handle_t4t_evt(tCE_EVENT event, tCE_DATA* p_ce_data) { 116 tNFA_CE_CB* p_cb = &nfa_ce_cb; 117 tNFA_CONN_EVT_DATA conn_evt; 118 119 NFA_TRACE_DEBUG1("nfa_ce_handle_t4t_evt: event 0x%x", event); 120 121 /* AID for NDEF selected. we had notified the app of activation. */ 122 p_cb->idx_cur_active = NFA_CE_LISTEN_INFO_IDX_NDEF; 123 if (p_cb->listen_info[p_cb->idx_cur_active].flags & 124 NFA_CE_LISTEN_INFO_T4T_ACTIVATE_PND) { 125 p_cb->p_active_conn_cback = 126 p_cb->listen_info[p_cb->idx_cur_active].p_conn_cback; 127 } 128 129 switch (event) { 130 case CE_T4T_NDEF_UPDATE_START_EVT: 131 conn_evt.status = NFA_STATUS_OK; 132 (*p_cb->p_active_conn_cback)(NFA_CE_NDEF_WRITE_START_EVT, &conn_evt); 133 break; 134 135 case CE_T4T_NDEF_UPDATE_CPLT_EVT: 136 conn_evt.ndef_write_cplt.len = p_ce_data->update_info.length; 137 conn_evt.ndef_write_cplt.p_data = p_ce_data->update_info.p_data; 138 139 if (NDEF_MsgValidate(p_ce_data->update_info.p_data, 140 p_ce_data->update_info.length, true) != NDEF_OK) 141 conn_evt.ndef_write_cplt.status = NFA_STATUS_FAILED; 142 else 143 conn_evt.ndef_write_cplt.status = NFA_STATUS_OK; 144 145 (*p_cb->p_active_conn_cback)(NFA_CE_NDEF_WRITE_CPLT_EVT, &conn_evt); 146 break; 147 148 case CE_T4T_NDEF_UPDATE_ABORT_EVT: 149 conn_evt.ndef_write_cplt.len = 0; 150 conn_evt.ndef_write_cplt.status = NFA_STATUS_FAILED; 151 conn_evt.ndef_write_cplt.p_data = NULL; 152 (*p_cb->p_active_conn_cback)(NFA_CE_NDEF_WRITE_CPLT_EVT, &conn_evt); 153 break; 154 155 default: 156 /* CE_T4T_RAW_FRAME_EVT is not used in NFA CE */ 157 NFA_TRACE_DEBUG1("nfa_ce_handle_t4t_evt unhandled event=0x%02x", event); 158 break; 159 } 160 } 161 162 /******************************************************************************* 163 ** 164 ** Function nfa_ce_handle_t4t_aid_evt 165 ** 166 ** Description Handler for Type-4 tag AID events (for AIDs registered using 167 ** NFA_CeRegisterT4tAidOnDH) 168 ** 169 ** Returns Nothing 170 ** 171 *******************************************************************************/ 172 void nfa_ce_handle_t4t_aid_evt(tCE_EVENT event, tCE_DATA* p_ce_data) { 173 tNFA_CE_CB* p_cb = &nfa_ce_cb; 174 uint8_t listen_info_idx; 175 tNFA_CONN_EVT_DATA conn_evt; 176 177 NFA_TRACE_DEBUG1("nfa_ce_handle_t4t_aid_evt: event 0x%x", event); 178 179 /* Get listen_info for this aid callback */ 180 for (listen_info_idx = 0; listen_info_idx < NFA_CE_LISTEN_INFO_IDX_INVALID; 181 listen_info_idx++) { 182 if ((p_cb->listen_info[listen_info_idx].flags & 183 NFA_CE_LISTEN_INFO_IN_USE) && 184 (p_cb->listen_info[listen_info_idx].flags & 185 NFA_CE_LISTEN_INFO_T4T_AID) && 186 (p_cb->listen_info[listen_info_idx].t4t_aid_handle == 187 p_ce_data->raw_frame.aid_handle)) { 188 p_cb->idx_cur_active = listen_info_idx; 189 p_cb->p_active_conn_cback = 190 p_cb->listen_info[p_cb->idx_cur_active].p_conn_cback; 191 break; 192 } 193 } 194 195 if (event == CE_T4T_RAW_FRAME_EVT) { 196 if (listen_info_idx != NFA_CE_LISTEN_INFO_IDX_INVALID) { 197 /* Found listen_info entry */ 198 conn_evt.ce_activated.handle = 199 NFA_HANDLE_GROUP_CE | ((tNFA_HANDLE)p_cb->idx_cur_active); 200 201 /* If we have not notified the app of activation, do so now */ 202 if (p_cb->listen_info[p_cb->idx_cur_active].flags & 203 NFA_CE_LISTEN_INFO_T4T_ACTIVATE_PND) { 204 p_cb->listen_info[p_cb->idx_cur_active].flags &= 205 ~NFA_CE_LISTEN_INFO_T4T_ACTIVATE_PND; 206 207 memcpy(&(conn_evt.ce_activated.activate_ntf), &p_cb->activation_params, 208 sizeof(tNFC_ACTIVATE_DEVT)); 209 conn_evt.ce_activated.status = NFA_STATUS_OK; 210 (*p_cb->p_active_conn_cback)(NFA_CE_ACTIVATED_EVT, &conn_evt); 211 } 212 213 /* Notify app of AID data */ 214 conn_evt.ce_data.status = p_ce_data->raw_frame.status; 215 conn_evt.ce_data.handle = 216 NFA_HANDLE_GROUP_CE | ((tNFA_HANDLE)p_cb->idx_cur_active); 217 conn_evt.ce_data.p_data = (uint8_t*)(p_ce_data->raw_frame.p_data + 1) + 218 p_ce_data->raw_frame.p_data->offset; 219 conn_evt.ce_data.len = p_ce_data->raw_frame.p_data->len; 220 (*p_cb->p_active_conn_cback)(NFA_CE_DATA_EVT, &conn_evt); 221 } else { 222 NFA_TRACE_ERROR1( 223 "nfa_ce_handle_t4t_aid_evt: unable to find listen_info for aid hdl " 224 "%i", 225 p_ce_data->raw_frame.aid_handle) 226 } 227 228 GKI_freebuf(p_ce_data->raw_frame.p_data); 229 } 230 } 231 232 /***************************************************************************** 233 * Discovery configuration and discovery event handlers 234 *****************************************************************************/ 235 236 /******************************************************************************* 237 ** 238 ** Function nfa_ce_discovery_cback 239 ** 240 ** Description Processing event from discovery callback 241 ** 242 ** Returns None 243 ** 244 *******************************************************************************/ 245 void nfa_ce_discovery_cback(tNFA_DM_RF_DISC_EVT event, tNFC_DISCOVER* p_data) { 246 tNFA_CE_MSG ce_msg; 247 NFA_TRACE_DEBUG1("nfa_ce_discovery_cback(): event:0x%02X", event); 248 249 switch (event) { 250 case NFA_DM_RF_DISC_START_EVT: 251 NFA_TRACE_DEBUG1("nfa_ce_handle_disc_start (status=0x%x)", p_data->start); 252 break; 253 254 case NFA_DM_RF_DISC_ACTIVATED_EVT: 255 ce_msg.activate_ntf.hdr.event = NFA_CE_ACTIVATE_NTF_EVT; 256 ce_msg.activate_ntf.p_activation_params = &p_data->activate; 257 nfa_ce_hdl_event((NFC_HDR*)&ce_msg); 258 break; 259 260 case NFA_DM_RF_DISC_DEACTIVATED_EVT: 261 /* DM broadcasts deactivaiton event in listen sleep state, so check before 262 * processing */ 263 if (nfa_ce_cb.flags & NFA_CE_FLAGS_LISTEN_ACTIVE_SLEEP) { 264 ce_msg.hdr.event = NFA_CE_DEACTIVATE_NTF_EVT; 265 ce_msg.hdr.layer_specific = p_data->deactivate.type; 266 nfa_ce_hdl_event((NFC_HDR*)&ce_msg); 267 } 268 break; 269 270 default: 271 NFA_TRACE_ERROR0("Unexpected event"); 272 break; 273 } 274 } 275 276 /******************************************************************************* 277 ** 278 ** Function nfc_ce_t3t_set_listen_params 279 ** 280 ** Description Set t3t listening parameters 281 ** 282 ** Returns Nothing 283 ** 284 *******************************************************************************/ 285 void nfc_ce_t3t_set_listen_params(void) { 286 uint8_t i; 287 tNFA_CE_CB* p_cb = &nfa_ce_cb; 288 uint8_t tlv[32], *p_params; 289 uint8_t tlv_size; 290 uint16_t t3t_flags2_mask = 0xFFFF; /* Mask of which T3T_IDs are disabled */ 291 uint8_t t3t_idx = 0; 292 293 /* Point to start of tlv buffer */ 294 p_params = tlv; 295 296 /* Set system code and NFCID2 */ 297 for (i = 0; i < NFA_CE_LISTEN_INFO_MAX; i++) { 298 if ((p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_IN_USE) && 299 (p_cb->listen_info[i].protocol_mask & NFA_PROTOCOL_MASK_T3T)) { 300 /* Set tag's system code and NFCID2 */ 301 UINT8_TO_STREAM(p_params, NFC_PMID_LF_T3T_ID1 + t3t_idx); /* type */ 302 UINT8_TO_STREAM(p_params, NCI_PARAM_LEN_LF_T3T_ID); /* length */ 303 /* System Code */ 304 UINT16_TO_BE_STREAM(p_params, p_cb->listen_info[i].t3t_system_code); 305 ARRAY_TO_BE_STREAM(p_params, p_cb->listen_info[i].t3t_nfcid2, 306 NCI_RF_F_UID_LEN); 307 308 /* Set mask for this ID */ 309 t3t_flags2_mask &= ~((uint16_t)(1 << t3t_idx)); 310 t3t_idx++; 311 } 312 } 313 314 /* For NCI draft 22+, the polarity of NFC_PMID_LF_T3T_FLAGS2 is flipped */ 315 t3t_flags2_mask = ~t3t_flags2_mask; 316 317 UINT8_TO_STREAM(p_params, NFC_PMID_LF_T3T_FLAGS2); /* type */ 318 UINT8_TO_STREAM(p_params, NCI_PARAM_LEN_LF_T3T_FLAGS2); /* length */ 319 /* Mask of IDs to disable listening */ 320 UINT16_TO_STREAM(p_params, t3t_flags2_mask); 321 322 tlv_size = (uint8_t)(p_params - tlv); 323 nfa_dm_check_set_config(tlv_size, (uint8_t*)tlv, false); 324 } 325 326 /******************************************************************************* 327 ** 328 ** Function nfa_ce_t3t_generate_rand_nfcid 329 ** 330 ** Description Generate a random NFCID2 for Type-3 tag 331 ** 332 ** Returns Nothing 333 ** 334 *******************************************************************************/ 335 void nfa_ce_t3t_generate_rand_nfcid(uint8_t nfcid2[NCI_RF_F_UID_LEN]) { 336 uint32_t rand_seed = GKI_get_tick_count(); 337 338 /* For Type-3 tag, nfcid2 starts witn 02:fe */ 339 nfcid2[0] = 0x02; 340 nfcid2[1] = 0xFE; 341 342 /* The remaining 6 bytes are random */ 343 nfcid2[2] = (uint8_t)(rand_seed & 0xFF); 344 nfcid2[3] = (uint8_t)(rand_seed >> 8 & 0xFF); 345 rand_seed >>= (rand_seed & 3); 346 nfcid2[4] = (uint8_t)(rand_seed & 0xFF); 347 nfcid2[5] = (uint8_t)(rand_seed >> 8 & 0xFF); 348 rand_seed >>= (rand_seed & 3); 349 nfcid2[6] = (uint8_t)(rand_seed & 0xFF); 350 nfcid2[7] = (uint8_t)(rand_seed >> 8 & 0xFF); 351 } 352 353 /******************************************************************************* 354 ** 355 ** Function nfa_ce_start_listening 356 ** 357 ** Description Start listening 358 ** 359 ** Returns NFA_STATUS_OK if successful 360 ** 361 *******************************************************************************/ 362 tNFA_STATUS nfa_ce_start_listening(void) { 363 tNFA_DM_DISC_TECH_PROTO_MASK listen_mask; 364 tNFA_CE_CB* p_cb = &nfa_ce_cb; 365 tNFA_HANDLE disc_handle; 366 uint8_t listen_info_idx; 367 368 /*************************************************************************/ 369 /* Construct protocol preference list to listen for */ 370 371 /* First, get protocol preference for active NDEF (if any) */ 372 if ((p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags & 373 NFA_CE_LISTEN_INFO_IN_USE) && 374 (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle == 375 NFA_HANDLE_INVALID)) { 376 listen_mask = 0; 377 378 if (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].protocol_mask & 379 NFA_PROTOCOL_MASK_T3T) { 380 /* set T3T config params */ 381 nfc_ce_t3t_set_listen_params(); 382 383 listen_mask |= NFA_DM_DISC_MASK_LF_T3T; 384 } 385 386 if (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].protocol_mask & 387 NFA_PROTOCOL_MASK_ISO_DEP) { 388 listen_mask |= nfa_ce_cb.isodep_disc_mask; 389 } 390 391 disc_handle = nfa_dm_add_rf_discover(listen_mask, NFA_DM_DISC_HOST_ID_DH, 392 nfa_ce_discovery_cback); 393 394 if (disc_handle == NFA_HANDLE_INVALID) 395 return (NFA_STATUS_FAILED); 396 else 397 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle = 398 disc_handle; 399 } 400 401 /* Next, add protocols from non-NDEF, if any */ 402 for (listen_info_idx = 0; listen_info_idx < NFA_CE_LISTEN_INFO_IDX_INVALID; 403 listen_info_idx++) { 404 /* add RF discovery to DM only if it is not added yet */ 405 if ((p_cb->listen_info[listen_info_idx].flags & 406 NFA_CE_LISTEN_INFO_IN_USE) && 407 (p_cb->listen_info[listen_info_idx].rf_disc_handle == 408 NFA_HANDLE_INVALID)) { 409 if (p_cb->listen_info[listen_info_idx].flags & 410 NFA_CE_LISTEN_INFO_FELICA) { 411 /* set T3T config params */ 412 nfc_ce_t3t_set_listen_params(); 413 414 disc_handle = nfa_dm_add_rf_discover(NFA_DM_DISC_MASK_LF_T3T, 415 NFA_DM_DISC_HOST_ID_DH, 416 nfa_ce_discovery_cback); 417 418 if (disc_handle == NFA_HANDLE_INVALID) 419 return (NFA_STATUS_FAILED); 420 else 421 p_cb->listen_info[listen_info_idx].rf_disc_handle = disc_handle; 422 } else if (p_cb->listen_info[listen_info_idx].flags & 423 NFA_CE_LISTEN_INFO_T4T_AID) { 424 disc_handle = nfa_dm_add_rf_discover(nfa_ce_cb.isodep_disc_mask, 425 NFA_DM_DISC_HOST_ID_DH, 426 nfa_ce_discovery_cback); 427 428 if (disc_handle == NFA_HANDLE_INVALID) 429 return (NFA_STATUS_FAILED); 430 else 431 p_cb->listen_info[listen_info_idx].rf_disc_handle = disc_handle; 432 } 433 #if (NFC_NFCEE_INCLUDED == TRUE) 434 else if (p_cb->listen_info[listen_info_idx].flags & 435 NFA_CE_LISTEN_INFO_UICC) { 436 listen_mask = 0; 437 if (nfa_ee_is_active(p_cb->listen_info[listen_info_idx].ee_handle)) { 438 if (p_cb->listen_info[listen_info_idx].tech_mask & 439 NFA_TECHNOLOGY_MASK_A) { 440 listen_mask |= NFA_DM_DISC_MASK_LA_ISO_DEP; 441 } 442 if (p_cb->listen_info[listen_info_idx].tech_mask & 443 NFA_TECHNOLOGY_MASK_B) { 444 listen_mask |= NFA_DM_DISC_MASK_LB_ISO_DEP; 445 } 446 if (p_cb->listen_info[listen_info_idx].tech_mask & 447 NFA_TECHNOLOGY_MASK_F) { 448 listen_mask |= NFA_DM_DISC_MASK_LF_T3T; 449 } 450 if (p_cb->listen_info[listen_info_idx].tech_mask & 451 NFA_TECHNOLOGY_MASK_B_PRIME) { 452 listen_mask |= NFA_DM_DISC_MASK_L_B_PRIME; 453 } 454 } 455 456 if (listen_mask) { 457 /* Start listening for requested technologies */ 458 /* register discovery callback to NFA DM */ 459 disc_handle = nfa_dm_add_rf_discover( 460 listen_mask, 461 (tNFA_DM_DISC_HOST_ID)( 462 p_cb->listen_info[listen_info_idx].ee_handle & 0x00FF), 463 nfa_ce_discovery_cback); 464 465 if (disc_handle == NFA_HANDLE_INVALID) 466 return (NFA_STATUS_FAILED); 467 else { 468 p_cb->listen_info[listen_info_idx].rf_disc_handle = disc_handle; 469 p_cb->listen_info[listen_info_idx].tech_proto_mask = listen_mask; 470 } 471 } else { 472 NFA_TRACE_ERROR1("UICC[0x%x] is not activated", 473 p_cb->listen_info[listen_info_idx].ee_handle); 474 } 475 } 476 #endif 477 } 478 } 479 480 return NFA_STATUS_OK; 481 } 482 483 /******************************************************************************* 484 ** 485 ** Function nfa_ce_restart_listen_check 486 ** 487 ** Description Called on deactivation. Check if any active listen_info 488 ** entries to listen for 489 ** 490 ** Returns TRUE if listening is restarted. 491 ** FALSE if listening not restarted 492 ** 493 *******************************************************************************/ 494 bool nfa_ce_restart_listen_check(void) { 495 tNFA_CE_CB* p_cb = &nfa_ce_cb; 496 uint8_t listen_info_idx; 497 498 /* Check if any active entries in listen_info table */ 499 for (listen_info_idx = 0; listen_info_idx < NFA_CE_LISTEN_INFO_MAX; 500 listen_info_idx++) { 501 if (p_cb->listen_info[listen_info_idx].flags & NFA_CE_LISTEN_INFO_IN_USE) 502 break; 503 } 504 505 /* Restart listening if there are any active listen_info entries */ 506 if (listen_info_idx != NFA_CE_LISTEN_INFO_IDX_INVALID) { 507 /* restart listening */ 508 nfa_ce_start_listening(); 509 } else { 510 /* No active listen_info entries */ 511 return false; 512 } 513 514 return true; 515 } 516 517 /******************************************************************************* 518 ** 519 ** Function nfa_ce_remove_listen_info_entry 520 ** 521 ** Description Remove entry from listen_info table. (when API deregister is 522 ** called or listen_start failed) 523 ** 524 ** 525 ** Returns Nothing 526 ** 527 *******************************************************************************/ 528 void nfa_ce_remove_listen_info_entry(uint8_t listen_info_idx, bool notify_app) { 529 tNFA_CE_CB* p_cb = &nfa_ce_cb; 530 tNFA_CONN_EVT_DATA conn_evt; 531 532 NFA_TRACE_DEBUG1("NFA_CE: removing listen_info entry %i", listen_info_idx); 533 534 /* Notify app that listening has stopped if requested (for API deregister) */ 535 /* For LISTEN_START failures, app has already notified of NFA_LISTEN_START_EVT 536 * failure */ 537 if (notify_app) { 538 if (listen_info_idx == NFA_CE_LISTEN_INFO_IDX_NDEF) { 539 conn_evt.status = NFA_STATUS_OK; 540 (*p_cb->listen_info[listen_info_idx].p_conn_cback)( 541 NFA_CE_LOCAL_TAG_CONFIGURED_EVT, &conn_evt); 542 } 543 #if (NFC_NFCEE_INCLUDED == TRUE) 544 else if (p_cb->listen_info[listen_info_idx].flags & 545 NFA_CE_LISTEN_INFO_UICC) { 546 conn_evt.status = NFA_STATUS_OK; 547 (*p_cb->listen_info[listen_info_idx].p_conn_cback)( 548 NFA_CE_UICC_LISTEN_CONFIGURED_EVT, &conn_evt); 549 } 550 #endif 551 else { 552 conn_evt.ce_deregistered.handle = NFA_HANDLE_GROUP_CE | listen_info_idx; 553 (*p_cb->listen_info[listen_info_idx].p_conn_cback)( 554 NFA_CE_DEREGISTERED_EVT, &conn_evt); 555 } 556 } 557 558 /* Handle NDEF stopping */ 559 if (listen_info_idx == NFA_CE_LISTEN_INFO_IDX_NDEF) { 560 /* clear NDEF contents */ 561 CE_T3tSetLocalNDEFMsg(true, 0, 0, NULL, NULL); 562 CE_T4tSetLocalNDEFMsg(true, 0, 0, NULL, NULL); 563 564 if (p_cb->listen_info[listen_info_idx].protocol_mask & 565 NFA_PROTOCOL_MASK_T3T) { 566 p_cb->listen_info[listen_info_idx].protocol_mask = 0; 567 568 /* clear T3T Flags for NDEF */ 569 nfc_ce_t3t_set_listen_params(); 570 } 571 572 /* Free scratch buffer for this NDEF, if one was allocated */ 573 nfa_ce_free_scratch_buf(); 574 } 575 /* If stopping listening Felica system code, then clear T3T Flags for this */ 576 else if (p_cb->listen_info[listen_info_idx].flags & 577 NFA_CE_LISTEN_INFO_FELICA) { 578 p_cb->listen_info[listen_info_idx].protocol_mask = 0; 579 580 /* clear T3T Flags for registered Felica system code */ 581 nfc_ce_t3t_set_listen_params(); 582 } 583 /* If stopping listening T4T AID, then deregister this AID from CE_T4T */ 584 else if (p_cb->listen_info[listen_info_idx].flags & 585 NFA_CE_LISTEN_INFO_T4T_AID) { 586 /* Free t4t_aid_cback used by this AID */ 587 CE_T4tDeregisterAID(p_cb->listen_info[listen_info_idx].t4t_aid_handle); 588 } 589 590 if (p_cb->listen_info[listen_info_idx].rf_disc_handle != NFA_HANDLE_INVALID) { 591 nfa_dm_delete_rf_discover( 592 p_cb->listen_info[listen_info_idx].rf_disc_handle); 593 p_cb->listen_info[listen_info_idx].rf_disc_handle = NFA_HANDLE_INVALID; 594 } 595 596 /* Remove entry from listen_info table */ 597 p_cb->listen_info[listen_info_idx].flags = 0; 598 } 599 600 /******************************************************************************* 601 ** 602 ** Function nfa_ce_free_scratch_buf 603 ** 604 ** Description free scratch buffer (if one is allocated) 605 ** 606 ** Returns nothing 607 ** 608 *******************************************************************************/ 609 void nfa_ce_free_scratch_buf(void) { 610 tNFA_CE_CB* p_cb = &nfa_ce_cb; 611 if (p_cb->p_scratch_buf) { 612 nfa_mem_co_free(p_cb->p_scratch_buf); 613 p_cb->p_scratch_buf = NULL; 614 } 615 } 616 617 /******************************************************************************* 618 ** 619 ** Function nfa_ce_realloc_scratch_buffer 620 ** 621 ** Description Set scratch buffer if necessary (for writable NDEF messages) 622 ** 623 ** Returns NFA_STATUS_OK if successful 624 ** 625 *******************************************************************************/ 626 tNFA_STATUS nfa_ce_realloc_scratch_buffer(void) { 627 tNFA_STATUS result = NFA_STATUS_OK; 628 629 /* If current NDEF message is read-only, then we do not need a scratch buffer 630 */ 631 if (nfa_ce_cb.listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags & 632 NFC_CE_LISTEN_INFO_READONLY_NDEF) { 633 /* Free existing scratch buffer, if one was allocated */ 634 nfa_ce_free_scratch_buf(); 635 } else { 636 /* If no scratch buffer allocated yet, or if current scratch buffer size is 637 * different from current ndef size, */ 638 /* then allocate a new scratch buffer. */ 639 if ((nfa_ce_cb.p_scratch_buf == NULL) || 640 (nfa_ce_cb.scratch_buf_size != nfa_ce_cb.ndef_max_size)) { 641 /* Free existing scratch buffer, if one was allocated */ 642 nfa_ce_free_scratch_buf(); 643 644 nfa_ce_cb.p_scratch_buf = 645 (uint8_t*)nfa_mem_co_alloc(nfa_ce_cb.ndef_max_size); 646 if (nfa_ce_cb.p_scratch_buf != NULL) { 647 nfa_ce_cb.scratch_buf_size = nfa_ce_cb.ndef_max_size; 648 } else { 649 NFA_TRACE_ERROR1( 650 "Unable to allocate scratch buffer for writable NDEF message (%i " 651 "bytes)", 652 nfa_ce_cb.ndef_max_size); 653 result = NFA_STATUS_FAILED; 654 } 655 } 656 } 657 658 return (result); 659 } 660 661 /******************************************************************************* 662 ** 663 ** Function nfa_ce_set_content 664 ** 665 ** Description Set NDEF contents 666 ** 667 ** Returns void 668 ** 669 *******************************************************************************/ 670 tNFC_STATUS nfa_ce_set_content(void) { 671 tNFC_STATUS status; 672 tNFA_CE_CB* p_cb = &nfa_ce_cb; 673 tNFA_PROTOCOL_MASK ndef_protocol_mask; 674 bool readonly; 675 676 /* Check if listening for NDEF */ 677 if (!(p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags & 678 NFA_CE_LISTEN_INFO_IN_USE)) { 679 /* Not listening for NDEF */ 680 return (NFA_STATUS_OK); 681 } 682 683 NFA_TRACE_DEBUG0("Setting NDEF contents"); 684 685 readonly = (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags & 686 NFC_CE_LISTEN_INFO_READONLY_NDEF) 687 ? true 688 : false; 689 ndef_protocol_mask = 690 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].protocol_mask; 691 692 /* Allocate a scratch buffer if needed (for handling write-requests) */ 693 status = nfa_ce_realloc_scratch_buffer(); 694 if (status == NFA_STATUS_OK) { 695 if ((ndef_protocol_mask & NFA_PROTOCOL_MASK_T3T) && 696 (status == NFA_STATUS_OK)) { 697 /* Type3Tag - NFC-F */ 698 status = CE_T3tSetLocalNDEFMsg(readonly, p_cb->ndef_max_size, 699 p_cb->ndef_cur_size, p_cb->p_ndef_data, 700 p_cb->p_scratch_buf); 701 } 702 703 if ((ndef_protocol_mask & NFA_PROTOCOL_MASK_ISO_DEP) && 704 (status == NFA_STATUS_OK)) { 705 /* ISODEP/4A,4B- NFC-A or NFC-B */ 706 status = CE_T4tSetLocalNDEFMsg(readonly, p_cb->ndef_max_size, 707 p_cb->ndef_cur_size, p_cb->p_ndef_data, 708 p_cb->p_scratch_buf); 709 } 710 } 711 712 if (status != NFA_STATUS_OK) { 713 /* clear NDEF contents */ 714 CE_T3tSetLocalNDEFMsg(true, 0, 0, NULL, NULL); 715 CE_T4tSetLocalNDEFMsg(true, 0, 0, NULL, NULL); 716 717 NFA_TRACE_ERROR1("Unable to set contents (error %02x)", status); 718 } 719 720 return (status); 721 } 722 723 /******************************************************************************* 724 ** 725 ** Function nfa_ce_activate_ntf 726 ** 727 ** Description Action when activation has occured (NFA_CE_ACTIVATE_NTF_EVT) 728 ** 729 ** - Find the listen_info entry assocated with this activation 730 ** - get the app callback that registered for this listen 731 ** - call CE_SetActivatedTagType with activation parameters 732 ** 733 ** Returns TRUE (message buffer to be freed by caller) 734 ** 735 *******************************************************************************/ 736 bool nfa_ce_activate_ntf(tNFA_CE_MSG* p_ce_msg) { 737 tNFC_ACTIVATE_DEVT* p_activation_params = 738 p_ce_msg->activate_ntf.p_activation_params; 739 tNFA_CE_CB* p_cb = &nfa_ce_cb; 740 tNFA_CONN_EVT_DATA conn_evt; 741 tCE_CBACK* p_ce_cback = NULL; 742 uint16_t t3t_system_code = 0xFFFF; 743 uint8_t listen_info_idx = NFA_CE_LISTEN_INFO_IDX_INVALID; 744 uint8_t* p_nfcid2 = NULL; 745 uint8_t i; 746 bool t4t_activate_pending = false; 747 748 NFA_TRACE_DEBUG1("nfa_ce_activate_ntf () protocol=%d", 749 p_ce_msg->activate_ntf.p_activation_params->protocol); 750 751 /* Tag is in listen active state */ 752 p_cb->flags |= NFA_CE_FLAGS_LISTEN_ACTIVE_SLEEP; 753 754 /* Store activation parameters */ 755 memcpy(&p_cb->activation_params, p_activation_params, 756 sizeof(tNFC_ACTIVATE_DEVT)); 757 758 /* Find the listen_info entry corresponding to this activation */ 759 if (p_cb->activation_params.protocol == NFA_PROTOCOL_T3T) { 760 /* Look for T3T entries in listen_info table that match activated system 761 * code and NFCID2 */ 762 for (listen_info_idx = 0; listen_info_idx < NFA_CE_LISTEN_INFO_IDX_INVALID; 763 listen_info_idx++) { 764 /* Look for entries with NFA_PROTOCOL_MASK_T3T */ 765 if (p_cb->listen_info[listen_info_idx].flags & 766 NFA_CE_LISTEN_INFO_IN_USE) { 767 if (p_cb->listen_info[listen_info_idx].protocol_mask & 768 NFA_PROTOCOL_MASK_T3T) { 769 /* Check if system_code and nfcid2 that matches activation params */ 770 p_nfcid2 = p_cb->listen_info[listen_info_idx].t3t_nfcid2; 771 t3t_system_code = p_cb->listen_info[listen_info_idx].t3t_system_code; 772 773 /* Compare NFCID2 (note: NFCC currently does not return system code in 774 * activation parameters) */ 775 if ((memcmp(p_nfcid2, 776 p_cb->activation_params.rf_tech_param.param.lf.nfcid2, 777 NCI_RF_F_UID_LEN) == 0) 778 /* && (t3t_system_code == p_ce_msg->activation.p_activate_info->rf_tech_param.param.lf.system_code) */) { 779 /* Found listen_info corresponding to this activation */ 780 break; 781 } 782 } 783 784 /* Check if entry is for T3T UICC */ 785 if ((p_cb->listen_info[listen_info_idx].flags & 786 NFA_CE_LISTEN_INFO_UICC) && 787 (p_cb->listen_info[listen_info_idx].tech_mask & 788 NFA_TECHNOLOGY_MASK_F)) { 789 break; 790 } 791 } 792 } 793 794 p_ce_cback = nfa_ce_handle_t3t_evt; 795 } else if (p_cb->activation_params.protocol == NFA_PROTOCOL_ISO_DEP) { 796 p_ce_cback = nfa_ce_handle_t4t_evt; 797 798 /* For T4T, we do not know which AID will be selected yet */ 799 800 /* For all T4T entries in listen_info, set T4T_ACTIVATE_NOTIFY_PENDING flag 801 */ 802 for (i = 0; i < NFA_CE_LISTEN_INFO_IDX_INVALID; i++) { 803 if (p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_IN_USE) { 804 if (p_cb->listen_info[i].protocol_mask & NFA_PROTOCOL_MASK_ISO_DEP) { 805 /* Found listen_info table entry for T4T raw listen */ 806 p_cb->listen_info[i].flags |= NFA_CE_LISTEN_INFO_T4T_ACTIVATE_PND; 807 808 /* If entry if for NDEF, select it, so application gets nofitifed of 809 * ACTIVATE_EVT now */ 810 if (i == NFA_CE_LISTEN_INFO_IDX_NDEF) { 811 listen_info_idx = NFA_CE_LISTEN_INFO_IDX_NDEF; 812 } 813 814 t4t_activate_pending = true; 815 } 816 817 #if (NFC_NFCEE_INCLUDED == TRUE) 818 /* Check if entry is for ISO_DEP UICC */ 819 if (p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_UICC) { 820 if (((p_cb->activation_params.rf_tech_param.mode == 821 NFC_DISCOVERY_TYPE_LISTEN_A) && 822 (p_cb->listen_info[i].tech_proto_mask & 823 NFA_DM_DISC_MASK_LA_ISO_DEP)) || 824 ((p_cb->activation_params.rf_tech_param.mode == 825 NFC_DISCOVERY_TYPE_LISTEN_B) && 826 (p_cb->listen_info[i].tech_proto_mask & 827 NFA_DM_DISC_MASK_LB_ISO_DEP))) { 828 listen_info_idx = i; 829 } 830 } 831 #endif 832 } 833 } 834 835 /* If listening for ISO_DEP, but not NDEF nor UICC, then notify CE module 836 * now and wait for reader/writer to SELECT an AID */ 837 if (t4t_activate_pending && 838 (listen_info_idx == NFA_CE_LISTEN_INFO_IDX_INVALID)) { 839 CE_SetActivatedTagType(&p_cb->activation_params, 0, p_ce_cback); 840 return true; 841 } 842 } else if (p_cb->activation_params.intf_param.type == 843 NFC_INTERFACE_EE_DIRECT_RF) { 844 /* search any entry listening UICC */ 845 for (i = 0; i < NFA_CE_LISTEN_INFO_IDX_INVALID; i++) { 846 if ((p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_IN_USE) && 847 (p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_UICC)) { 848 listen_info_idx = i; 849 break; 850 } 851 } 852 } 853 854 /* Check if valid listen_info entry was found */ 855 if ((listen_info_idx == NFA_CE_LISTEN_INFO_IDX_INVALID) || 856 ((listen_info_idx == NFA_CE_LISTEN_INFO_IDX_NDEF) && 857 !(p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags & 858 NFA_CE_LISTEN_INFO_IN_USE))) { 859 NFA_TRACE_DEBUG1( 860 "No listen_info found for this activation. listen_info_idx=%d", 861 listen_info_idx); 862 return true; 863 } 864 865 p_cb->listen_info[listen_info_idx].flags &= 866 ~NFA_CE_LISTEN_INFO_T4T_ACTIVATE_PND; 867 868 /* Get CONN_CBACK for this activation */ 869 p_cb->p_active_conn_cback = p_cb->listen_info[listen_info_idx].p_conn_cback; 870 p_cb->idx_cur_active = listen_info_idx; 871 872 if ((p_cb->idx_cur_active == NFA_CE_LISTEN_INFO_IDX_NDEF) || 873 (p_cb->listen_info[p_cb->idx_cur_active].flags & 874 NFA_CE_LISTEN_INFO_UICC)) { 875 memcpy(&(conn_evt.activated.activate_ntf), &p_cb->activation_params, 876 sizeof(tNFC_ACTIVATE_DEVT)); 877 878 (*p_cb->p_active_conn_cback)(NFA_ACTIVATED_EVT, &conn_evt); 879 } else { 880 conn_evt.ce_activated.handle = 881 NFA_HANDLE_GROUP_CE | ((tNFA_HANDLE)p_cb->idx_cur_active); 882 memcpy(&(conn_evt.ce_activated.activate_ntf), &p_cb->activation_params, 883 sizeof(tNFC_ACTIVATE_DEVT)); 884 conn_evt.ce_activated.status = NFA_STATUS_OK; 885 886 (*p_cb->p_active_conn_cback)(NFA_CE_ACTIVATED_EVT, &conn_evt); 887 } 888 889 /* we don't need any CE subsystem in case of NFCEE direct RF interface */ 890 if (p_ce_cback) { 891 /* Notify CE subsystem */ 892 CE_SetActivatedTagType(&p_cb->activation_params, t3t_system_code, 893 p_ce_cback); 894 } 895 return true; 896 } 897 898 /******************************************************************************* 899 ** 900 ** Function nfa_ce_deactivate_ntf 901 ** 902 ** Description Action when deactivate occurs. (NFA_CE_DEACTIVATE_NTF_EVT) 903 ** 904 ** - If deactivate due to API deregister, then remove its entry 905 ** from listen_info table 906 ** 907 ** - If NDEF was modified while activated, then restore 908 ** original NDEF contents 909 ** 910 ** - Restart listening (if any active entries in listen table) 911 ** 912 ** Returns TRUE (message buffer to be freed by caller) 913 ** 914 *******************************************************************************/ 915 bool nfa_ce_deactivate_ntf(tNFA_CE_MSG* p_ce_msg) { 916 tNFC_DEACT_TYPE deact_type = (tNFC_DEACT_TYPE)p_ce_msg->hdr.layer_specific; 917 tNFA_CE_CB* p_cb = &nfa_ce_cb; 918 tNFA_CONN_EVT_DATA conn_evt; 919 uint8_t i; 920 921 NFA_TRACE_DEBUG1("nfa_ce_deactivate_ntf () deact_type=%d", deact_type); 922 923 /* Check if deactivating to SLEEP mode */ 924 if ((deact_type == NFC_DEACTIVATE_TYPE_SLEEP) || 925 (deact_type == NFC_DEACTIVATE_TYPE_SLEEP_AF)) { 926 if (nfa_ce_cb.idx_wild_card == NFA_CE_LISTEN_INFO_IDX_INVALID) { 927 /* notify deactivated as sleep and wait for reactivation or deactivation 928 * to idle */ 929 conn_evt.deactivated.type = deact_type; 930 931 /* if T4T AID application has not been selected then p_active_conn_cback 932 * could be NULL */ 933 if (p_cb->p_active_conn_cback) 934 (*p_cb->p_active_conn_cback)(NFA_DEACTIVATED_EVT, &conn_evt); 935 } else { 936 conn_evt.ce_deactivated.handle = 937 NFA_HANDLE_GROUP_CE | ((tNFA_HANDLE)nfa_ce_cb.idx_wild_card); 938 conn_evt.ce_deactivated.type = deact_type; 939 if (p_cb->p_active_conn_cback) 940 (*p_cb->p_active_conn_cback)(NFA_CE_DEACTIVATED_EVT, &conn_evt); 941 } 942 943 return true; 944 } else { 945 deact_type = NFC_DEACTIVATE_TYPE_IDLE; 946 } 947 948 /* Tag is in idle state */ 949 p_cb->flags &= ~NFA_CE_FLAGS_LISTEN_ACTIVE_SLEEP; 950 951 /* First, notify app of deactivation */ 952 for (i = 0; i < NFA_CE_LISTEN_INFO_IDX_INVALID; i++) { 953 if (p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_IN_USE) { 954 if ((p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_UICC) && 955 (i == p_cb->idx_cur_active)) { 956 conn_evt.deactivated.type = deact_type; 957 (*p_cb->p_active_conn_cback)(NFA_DEACTIVATED_EVT, &conn_evt); 958 } else if ((p_cb->activation_params.protocol == NFA_PROTOCOL_ISO_DEP) && 959 (p_cb->listen_info[i].protocol_mask & 960 NFA_PROTOCOL_MASK_ISO_DEP)) { 961 /* Don't send NFA_DEACTIVATED_EVT if NFA_ACTIVATED_EVT wasn't sent */ 962 if (!(p_cb->listen_info[i].flags & 963 NFA_CE_LISTEN_INFO_T4T_ACTIVATE_PND)) { 964 if (i == NFA_CE_LISTEN_INFO_IDX_NDEF) { 965 conn_evt.deactivated.type = deact_type; 966 (*p_cb->p_active_conn_cback)(NFA_DEACTIVATED_EVT, &conn_evt); 967 } else { 968 conn_evt.ce_deactivated.handle = 969 NFA_HANDLE_GROUP_CE | ((tNFA_HANDLE)i); 970 conn_evt.ce_deactivated.type = deact_type; 971 (*p_cb->p_active_conn_cback)(NFA_CE_DEACTIVATED_EVT, &conn_evt); 972 } 973 } 974 } else if ((p_cb->activation_params.protocol == NFA_PROTOCOL_T3T) && 975 (p_cb->listen_info[i].protocol_mask & NFA_PROTOCOL_MASK_T3T)) { 976 if (i == NFA_CE_LISTEN_INFO_IDX_NDEF) { 977 conn_evt.deactivated.type = deact_type; 978 (*p_cb->p_active_conn_cback)(NFA_DEACTIVATED_EVT, &conn_evt); 979 } else { 980 conn_evt.ce_deactivated.handle = 981 NFA_HANDLE_GROUP_CE | ((tNFA_HANDLE)i); 982 conn_evt.ce_deactivated.type = deact_type; 983 (*p_cb->p_active_conn_cback)(NFA_CE_DEACTIVATED_EVT, &conn_evt); 984 } 985 } 986 } 987 } 988 989 /* Check if app initiated the deactivation (due to API deregister). If so, 990 * remove entry from listen_info table. */ 991 if (p_cb->flags & NFA_CE_FLAGS_APP_INIT_DEACTIVATION) { 992 p_cb->flags &= ~NFA_CE_FLAGS_APP_INIT_DEACTIVATION; 993 nfa_ce_remove_listen_info_entry(p_cb->idx_cur_active, true); 994 } 995 996 p_cb->p_active_conn_cback = NULL; 997 p_cb->idx_cur_active = NFA_CE_LISTEN_INFO_IDX_INVALID; 998 999 /* Restart listening (if any listen_info entries are still active) */ 1000 nfa_ce_restart_listen_check(); 1001 1002 return true; 1003 } 1004 1005 /******************************************************************************* 1006 ** 1007 ** Function nfa_ce_disable_local_tag 1008 ** 1009 ** Description Disable local NDEF tag 1010 ** - clean up control block 1011 ** - remove NDEF discovery configuration 1012 ** 1013 ** Returns Nothing 1014 ** 1015 *******************************************************************************/ 1016 void nfa_ce_disable_local_tag(void) { 1017 tNFA_CE_CB* p_cb = &nfa_ce_cb; 1018 tNFA_CONN_EVT_DATA evt_data; 1019 1020 NFA_TRACE_DEBUG0("Disabling local NDEF tag"); 1021 1022 /* If local NDEF tag is in use, then disable it */ 1023 if (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags & 1024 NFA_CE_LISTEN_INFO_IN_USE) { 1025 /* NDEF Tag is in not idle state */ 1026 if ((p_cb->flags & NFA_CE_FLAGS_LISTEN_ACTIVE_SLEEP) && 1027 (p_cb->idx_cur_active == NFA_CE_LISTEN_INFO_IDX_NDEF)) { 1028 /* wait for deactivation */ 1029 p_cb->flags |= NFA_CE_FLAGS_APP_INIT_DEACTIVATION; 1030 nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_IDLE); 1031 } else { 1032 /* Notify DM to stop listening for ndef */ 1033 if (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle != 1034 NFA_HANDLE_INVALID) { 1035 nfa_dm_delete_rf_discover( 1036 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle); 1037 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle = 1038 NFA_HANDLE_INVALID; 1039 } 1040 nfa_ce_remove_listen_info_entry(NFA_CE_LISTEN_INFO_IDX_NDEF, true); 1041 } 1042 } else { 1043 /* Notify application */ 1044 evt_data.status = NFA_STATUS_OK; 1045 nfa_dm_conn_cback_event_notify(NFA_CE_LOCAL_TAG_CONFIGURED_EVT, &evt_data); 1046 } 1047 } 1048 1049 /******************************************************************************* 1050 ** 1051 ** Function nfa_ce_api_cfg_local_tag 1052 ** 1053 ** Description Configure local NDEF tag 1054 ** - store ndef attributes in to control block 1055 ** - update discovery configuration 1056 ** 1057 ** Returns TRUE (message buffer to be freed by caller) 1058 ** 1059 *******************************************************************************/ 1060 bool nfa_ce_api_cfg_local_tag(tNFA_CE_MSG* p_ce_msg) { 1061 tNFA_CE_CB* p_cb = &nfa_ce_cb; 1062 tNFA_CONN_EVT_DATA conn_evt; 1063 1064 /* Check if disabling local tag */ 1065 if (p_ce_msg->local_tag.protocol_mask == 0) { 1066 nfa_ce_disable_local_tag(); 1067 return true; 1068 } 1069 1070 NFA_TRACE_DEBUG5( 1071 "Configuring local NDEF tag: protocol_mask=%01x cur_size=%i, " 1072 "max_size=%i, readonly=%i", 1073 p_ce_msg->local_tag.protocol_mask, p_ce_msg->local_tag.ndef_cur_size, 1074 p_ce_msg->local_tag.ndef_max_size, p_ce_msg->local_tag.read_only, 1075 p_ce_msg->local_tag.uid_len); 1076 1077 /* If local tag was already set, then check if NFA_CeConfigureLocalTag called 1078 * to change protocol mask */ 1079 if ((p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags & 1080 NFA_CE_LISTEN_INFO_IN_USE) && 1081 (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle != 1082 NFA_HANDLE_INVALID) && 1083 ((p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].protocol_mask & 1084 (NFA_PROTOCOL_MASK_T3T | NFA_PROTOCOL_MASK_ISO_DEP)) != 1085 (p_ce_msg->local_tag.protocol_mask & 1086 (NFA_PROTOCOL_MASK_T3T | NFA_PROTOCOL_MASK_ISO_DEP)))) { 1087 /* Listening for different tag protocols. Stop discovery */ 1088 nfa_dm_delete_rf_discover( 1089 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle); 1090 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].rf_disc_handle = 1091 NFA_HANDLE_INVALID; 1092 1093 /* clear NDEF contents */ 1094 CE_T3tSetLocalNDEFMsg(true, 0, 0, NULL, NULL); 1095 CE_T4tSetLocalNDEFMsg(true, 0, 0, NULL, NULL); 1096 } 1097 1098 /* Store NDEF info to control block */ 1099 p_cb->p_ndef_data = p_ce_msg->local_tag.p_ndef_data; 1100 p_cb->ndef_cur_size = p_ce_msg->local_tag.ndef_cur_size; 1101 p_cb->ndef_max_size = p_ce_msg->local_tag.ndef_max_size; 1102 1103 /* Fill in LISTEN_INFO entry for NDEF */ 1104 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags = 1105 NFA_CE_LISTEN_INFO_IN_USE; 1106 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].protocol_mask = 1107 p_ce_msg->local_tag.protocol_mask; 1108 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].p_conn_cback = 1109 nfa_dm_conn_cback_event_notify; 1110 if (p_ce_msg->local_tag.read_only) 1111 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].flags |= 1112 NFC_CE_LISTEN_INFO_READONLY_NDEF; 1113 p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].t3t_system_code = 1114 T3T_SYSTEM_CODE_NDEF; 1115 1116 /* Set NDEF contents */ 1117 conn_evt.status = NFA_STATUS_FAILED; 1118 1119 if (p_cb->listen_info[NFA_CE_LISTEN_INFO_IDX_NDEF].protocol_mask & 1120 (NFA_PROTOCOL_MASK_T3T | NFA_PROTOCOL_MASK_ISO_DEP)) { 1121 /* Ok to set contents now */ 1122 if (nfa_ce_set_content() != NFA_STATUS_OK) { 1123 NFA_TRACE_ERROR0("nfa_ce_api_cfg_local_tag: could not set contents"); 1124 nfa_dm_conn_cback_event_notify(NFA_CE_LOCAL_TAG_CONFIGURED_EVT, 1125 &conn_evt); 1126 return true; 1127 } 1128 1129 /* Start listening and notify app of status */ 1130 conn_evt.status = nfa_ce_start_listening(); 1131 nfa_dm_conn_cback_event_notify(NFA_CE_LOCAL_TAG_CONFIGURED_EVT, &conn_evt); 1132 } 1133 1134 return true; 1135 } 1136 1137 /******************************************************************************* 1138 ** 1139 ** Function nfa_ce_api_reg_listen 1140 ** 1141 ** Description Register listen params for Felica system code, T4T AID, 1142 ** or UICC 1143 ** 1144 ** Returns TRUE (message buffer to be freed by caller) 1145 ** 1146 *******************************************************************************/ 1147 bool nfa_ce_api_reg_listen(tNFA_CE_MSG* p_ce_msg) { 1148 tNFA_CE_CB* p_cb = &nfa_ce_cb; 1149 tNFA_CONN_EVT_DATA conn_evt; 1150 uint8_t i; 1151 uint8_t listen_info_idx = NFA_CE_LISTEN_INFO_IDX_INVALID; 1152 1153 NFA_TRACE_DEBUG1("Registering UICC/Felica/Type-4 tag listener. Type=%i", 1154 p_ce_msg->reg_listen.listen_type); 1155 1156 /* Look for available entry in listen_info table */ 1157 /* - If registering UICC listen, make sure there isn't another entry for the 1158 * ee_handle */ 1159 /* - Skip over entry 0 (reserved for local NDEF tag) */ 1160 for (i = 1; i < NFA_CE_LISTEN_INFO_MAX; i++) { 1161 if ((p_ce_msg->reg_listen.listen_type == NFA_CE_REG_TYPE_UICC) && 1162 (p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_IN_USE) && 1163 (p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_UICC) && 1164 (p_cb->listen_info[i].ee_handle == p_ce_msg->reg_listen.ee_handle)) { 1165 NFA_TRACE_ERROR1("UICC (0x%x) listening already specified", 1166 p_ce_msg->reg_listen.ee_handle); 1167 conn_evt.status = NFA_STATUS_FAILED; 1168 nfa_dm_conn_cback_event_notify(NFA_CE_UICC_LISTEN_CONFIGURED_EVT, 1169 &conn_evt); 1170 return true; 1171 } 1172 /* If this is a free entry, and we haven't found one yet, remember it */ 1173 else if ((!(p_cb->listen_info[i].flags & NFA_CE_LISTEN_INFO_IN_USE)) && 1174 (listen_info_idx == NFA_CE_LISTEN_INFO_IDX_INVALID)) { 1175 listen_info_idx = i; 1176 } 1177 } 1178 1179 /* Add new entry to listen_info table */ 1180 if (listen_info_idx == NFA_CE_LISTEN_INFO_IDX_INVALID) { 1181 NFA_TRACE_ERROR1("Maximum listen callbacks exceeded (%i)", 1182 NFA_CE_LISTEN_INFO_MAX); 1183 1184 if (p_ce_msg->reg_listen.listen_type == NFA_CE_REG_TYPE_UICC) { 1185 conn_evt.status = NFA_STATUS_FAILED; 1186 nfa_dm_conn_cback_event_notify(NFA_CE_UICC_LISTEN_CONFIGURED_EVT, 1187 &conn_evt); 1188 } else { 1189 /* Notify application */ 1190 conn_evt.ce_registered.handle = NFA_HANDLE_INVALID; 1191 conn_evt.ce_registered.status = NFA_STATUS_FAILED; 1192 (*p_ce_msg->reg_listen.p_conn_cback)(NFA_CE_REGISTERED_EVT, &conn_evt); 1193 } 1194 return true; 1195 } else { 1196 NFA_TRACE_DEBUG1("NFA_CE: adding listen_info entry %i", listen_info_idx); 1197 1198 /* Store common parameters */ 1199 /* Mark entry as 'in-use', and NFA_CE_LISTEN_INFO_START_NTF_PND */ 1200 /* (LISTEN_START_EVT will be notified when discovery successfully starts */ 1201 p_cb->listen_info[listen_info_idx].flags = 1202 NFA_CE_LISTEN_INFO_IN_USE | NFA_CE_LISTEN_INFO_START_NTF_PND; 1203 p_cb->listen_info[listen_info_idx].rf_disc_handle = NFA_HANDLE_INVALID; 1204 p_cb->listen_info[listen_info_idx].protocol_mask = 0; 1205 1206 /* Store type-specific parameters */ 1207 switch (p_ce_msg->reg_listen.listen_type) { 1208 case NFA_CE_REG_TYPE_ISO_DEP: 1209 p_cb->listen_info[listen_info_idx].protocol_mask = 1210 NFA_PROTOCOL_MASK_ISO_DEP; 1211 p_cb->listen_info[listen_info_idx].flags |= NFA_CE_LISTEN_INFO_T4T_AID; 1212 p_cb->listen_info[listen_info_idx].p_conn_cback = 1213 p_ce_msg->reg_listen.p_conn_cback; 1214 1215 /* Register this AID with CE_T4T */ 1216 p_cb->listen_info[listen_info_idx].t4t_aid_handle = CE_T4tRegisterAID( 1217 p_ce_msg->reg_listen.aid_len, p_ce_msg->reg_listen.aid, 1218 nfa_ce_handle_t4t_aid_evt); 1219 if (p_cb->listen_info[listen_info_idx].t4t_aid_handle == 1220 CE_T4T_AID_HANDLE_INVALID) { 1221 NFA_TRACE_ERROR0("Unable to register AID"); 1222 p_cb->listen_info[listen_info_idx].flags = 0; 1223 1224 /* Notify application */ 1225 conn_evt.ce_registered.handle = NFA_HANDLE_INVALID; 1226 conn_evt.ce_registered.status = NFA_STATUS_FAILED; 1227 (*p_ce_msg->reg_listen.p_conn_cback)(NFA_CE_REGISTERED_EVT, 1228 &conn_evt); 1229 1230 return true; 1231 } 1232 if (p_cb->listen_info[listen_info_idx].t4t_aid_handle == 1233 CE_T4T_WILDCARD_AID_HANDLE) 1234 nfa_ce_cb.idx_wild_card = listen_info_idx; 1235 break; 1236 1237 case NFA_CE_REG_TYPE_FELICA: 1238 p_cb->listen_info[listen_info_idx].protocol_mask = 1239 NFA_PROTOCOL_MASK_T3T; 1240 p_cb->listen_info[listen_info_idx].flags |= NFA_CE_LISTEN_INFO_FELICA; 1241 p_cb->listen_info[listen_info_idx].p_conn_cback = 1242 p_ce_msg->reg_listen.p_conn_cback; 1243 1244 /* Store system code and nfcid2 */ 1245 p_cb->listen_info[listen_info_idx].t3t_system_code = 1246 p_ce_msg->reg_listen.system_code; 1247 memcpy(p_cb->listen_info[listen_info_idx].t3t_nfcid2, 1248 p_ce_msg->reg_listen.nfcid2, NCI_RF_F_UID_LEN); 1249 break; 1250 1251 #if (NFC_NFCEE_INCLUDED == TRUE) 1252 case NFA_CE_REG_TYPE_UICC: 1253 p_cb->listen_info[listen_info_idx].flags |= NFA_CE_LISTEN_INFO_UICC; 1254 p_cb->listen_info[listen_info_idx].p_conn_cback = 1255 &nfa_dm_conn_cback_event_notify; 1256 1257 /* Store EE handle and Tech */ 1258 p_cb->listen_info[listen_info_idx].ee_handle = 1259 p_ce_msg->reg_listen.ee_handle; 1260 p_cb->listen_info[listen_info_idx].tech_mask = 1261 p_ce_msg->reg_listen.tech_mask; 1262 break; 1263 #endif 1264 } 1265 } 1266 1267 /* Start listening */ 1268 conn_evt.status = nfa_ce_start_listening(); 1269 if (conn_evt.status != NFA_STATUS_OK) { 1270 NFA_TRACE_ERROR0( 1271 "nfa_ce_api_reg_listen: unable to register new listen params with DM"); 1272 p_cb->listen_info[listen_info_idx].flags = 0; 1273 } 1274 1275 /* Nofitify app of status */ 1276 if (p_ce_msg->reg_listen.listen_type == NFA_CE_REG_TYPE_UICC) { 1277 (*p_cb->listen_info[listen_info_idx].p_conn_cback)( 1278 NFA_CE_UICC_LISTEN_CONFIGURED_EVT, &conn_evt); 1279 } else { 1280 conn_evt.ce_registered.handle = NFA_HANDLE_GROUP_CE | listen_info_idx; 1281 NFA_TRACE_DEBUG1("nfa_ce_api_reg_listen: registered handle 0x%04X", 1282 conn_evt.ce_registered.handle); 1283 (*p_cb->listen_info[listen_info_idx].p_conn_cback)(NFA_CE_REGISTERED_EVT, 1284 &conn_evt); 1285 } 1286 1287 return true; 1288 } 1289 1290 /******************************************************************************* 1291 ** 1292 ** Function nfa_ce_api_dereg_listen 1293 ** 1294 ** Description Deregister listen params 1295 ** 1296 ** Returns TRUE (message buffer to be freed by caller) 1297 ** 1298 *******************************************************************************/ 1299 bool nfa_ce_api_dereg_listen(tNFA_CE_MSG* p_ce_msg) { 1300 tNFA_CE_CB* p_cb = &nfa_ce_cb; 1301 uint8_t listen_info_idx; 1302 tNFA_CONN_EVT_DATA conn_evt; 1303 1304 #if (NFC_NFCEE_INCLUDED == TRUE) 1305 /* Check if deregistering UICC , or virtual secure element listen */ 1306 if (p_ce_msg->dereg_listen.listen_info == NFA_CE_LISTEN_INFO_UICC) { 1307 /* Deregistering UICC listen. Look for listen_info for this UICC ee handle 1308 */ 1309 for (listen_info_idx = 0; listen_info_idx < NFA_CE_LISTEN_INFO_MAX; 1310 listen_info_idx++) { 1311 if ((p_cb->listen_info[listen_info_idx].flags & 1312 NFA_CE_LISTEN_INFO_IN_USE) && 1313 (p_cb->listen_info[listen_info_idx].flags & 1314 NFA_CE_LISTEN_INFO_UICC) && 1315 (p_cb->listen_info[listen_info_idx].ee_handle == 1316 p_ce_msg->dereg_listen.handle)) { 1317 /* UICC is in not idle state */ 1318 if ((p_cb->flags & NFA_CE_FLAGS_LISTEN_ACTIVE_SLEEP) && 1319 (p_cb->idx_cur_active == listen_info_idx)) { 1320 /* wait for deactivation */ 1321 p_cb->flags |= NFA_CE_FLAGS_APP_INIT_DEACTIVATION; 1322 nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_IDLE); 1323 } else { 1324 /* Stop listening */ 1325 if (p_cb->listen_info[listen_info_idx].rf_disc_handle != 1326 NFA_HANDLE_INVALID) { 1327 nfa_dm_delete_rf_discover( 1328 p_cb->listen_info[listen_info_idx].rf_disc_handle); 1329 p_cb->listen_info[listen_info_idx].rf_disc_handle = 1330 NFA_HANDLE_INVALID; 1331 } 1332 1333 /* Remove entry and notify application */ 1334 nfa_ce_remove_listen_info_entry(listen_info_idx, true); 1335 } 1336 break; 1337 } 1338 } 1339 1340 if (listen_info_idx == NFA_CE_LISTEN_INFO_MAX) { 1341 NFA_TRACE_ERROR0( 1342 "nfa_ce_api_dereg_listen (): cannot find listen_info for UICC"); 1343 conn_evt.status = NFA_STATUS_INVALID_PARAM; 1344 nfa_dm_conn_cback_event_notify(NFA_CE_UICC_LISTEN_CONFIGURED_EVT, 1345 &conn_evt); 1346 } 1347 } else 1348 #endif 1349 { 1350 /* Deregistering virtual secure element listen */ 1351 listen_info_idx = p_ce_msg->dereg_listen.handle & NFA_HANDLE_MASK; 1352 if (nfa_ce_cb.idx_wild_card == listen_info_idx) { 1353 nfa_ce_cb.idx_wild_card = NFA_CE_LISTEN_INFO_IDX_INVALID; 1354 } 1355 1356 if ((listen_info_idx < NFA_CE_LISTEN_INFO_MAX) && 1357 (p_cb->listen_info[listen_info_idx].flags & 1358 NFA_CE_LISTEN_INFO_IN_USE)) { 1359 /* virtual secure element is in not idle state */ 1360 if ((p_cb->flags & NFA_CE_FLAGS_LISTEN_ACTIVE_SLEEP) && 1361 (p_cb->idx_cur_active == listen_info_idx)) { 1362 /* wait for deactivation */ 1363 p_cb->flags |= NFA_CE_FLAGS_APP_INIT_DEACTIVATION; 1364 nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_IDLE); 1365 } else { 1366 /* Stop listening */ 1367 if (p_cb->listen_info[listen_info_idx].rf_disc_handle != 1368 NFA_HANDLE_INVALID) { 1369 nfa_dm_delete_rf_discover( 1370 p_cb->listen_info[listen_info_idx].rf_disc_handle); 1371 p_cb->listen_info[listen_info_idx].rf_disc_handle = 1372 NFA_HANDLE_INVALID; 1373 } 1374 1375 /* Remove entry and notify application */ 1376 nfa_ce_remove_listen_info_entry(listen_info_idx, true); 1377 } 1378 } else { 1379 NFA_TRACE_ERROR0( 1380 "nfa_ce_api_dereg_listen (): cannot find listen_info for " 1381 "Felica/T4tAID"); 1382 conn_evt.status = NFA_STATUS_INVALID_PARAM; 1383 nfa_dm_conn_cback_event_notify(NFA_CE_DEREGISTERED_EVT, &conn_evt); 1384 } 1385 } 1386 1387 return true; 1388 } 1389 1390 /******************************************************************************* 1391 ** 1392 ** Function nfa_ce_api_cfg_isodep_tech 1393 ** 1394 ** Description Configure the technologies (NFC-A and/or NFC-B) to listen 1395 ** for ISO-DEP 1396 ** 1397 ** Returns TRUE (message buffer to be freed by caller) 1398 ** 1399 *******************************************************************************/ 1400 bool nfa_ce_api_cfg_isodep_tech(tNFA_CE_MSG* p_ce_msg) { 1401 nfa_ce_cb.isodep_disc_mask = 0; 1402 if (p_ce_msg->hdr.layer_specific & NFA_TECHNOLOGY_MASK_A) 1403 nfa_ce_cb.isodep_disc_mask = NFA_DM_DISC_MASK_LA_ISO_DEP; 1404 1405 if (p_ce_msg->hdr.layer_specific & NFA_TECHNOLOGY_MASK_B) 1406 nfa_ce_cb.isodep_disc_mask |= NFA_DM_DISC_MASK_LB_ISO_DEP; 1407 return true; 1408 } 1409