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