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