• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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