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