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