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 *******************************************************************************/
nfa_ce_handle_t3t_evt(tCE_EVENT event,tCE_DATA * p_ce_data)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 *******************************************************************************/
nfa_ce_handle_t4t_evt(tCE_EVENT event,tCE_DATA * p_ce_data)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 *******************************************************************************/
nfa_ce_handle_t4t_aid_evt(tCE_EVENT event,tCE_DATA * p_ce_data)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 *******************************************************************************/
nfa_ce_discovery_cback(tNFA_DM_RF_DISC_EVT event,tNFC_DISCOVER * p_data)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 *******************************************************************************/
nfc_ce_t3t_set_listen_params(void)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 *******************************************************************************/
nfa_ce_t3t_generate_rand_nfcid(uint8_t nfcid2[NCI_RF_F_UID_LEN])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 *******************************************************************************/
nfa_ce_start_listening(void)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 *******************************************************************************/
nfa_ce_restart_listen_check(void)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 *******************************************************************************/
nfa_ce_remove_listen_info_entry(uint8_t listen_info_idx,bool notify_app)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 *******************************************************************************/
nfa_ce_free_scratch_buf(void)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 *******************************************************************************/
nfa_ce_realloc_scratch_buffer(void)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 *******************************************************************************/
nfa_ce_set_content(void)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 *******************************************************************************/
nfa_ce_activate_ntf(tNFA_CE_MSG * p_ce_msg)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 *******************************************************************************/
nfa_ce_deactivate_ntf(tNFA_CE_MSG * p_ce_msg)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 *******************************************************************************/
nfa_ce_disable_local_tag(void)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 *******************************************************************************/
nfa_ce_api_cfg_local_tag(tNFA_CE_MSG * p_ce_msg)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 *******************************************************************************/
nfa_ce_api_reg_listen(tNFA_CE_MSG * p_ce_msg)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 *******************************************************************************/
nfa_ce_api_dereg_listen(tNFA_CE_MSG * p_ce_msg)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 *******************************************************************************/
nfa_ce_api_cfg_isodep_tech(tNFA_CE_MSG * p_ce_msg)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