Home | History | Annotate | Download | only in ee
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2010-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 for NFA-EE
     22  *
     23  ******************************************************************************/
     24 #include <string.h>
     25 
     26 #include <android-base/stringprintf.h>
     27 #include <base/logging.h>
     28 
     29 #include "nfa_api.h"
     30 #include "nfa_dm_int.h"
     31 #include "nfa_ee_int.h"
     32 #include "nfa_hci_int.h"
     33 
     34 using android::base::StringPrintf;
     35 
     36 extern bool nfc_debug_enabled;
     37 
     38 /* the de-bounce timer:
     39  * The NFA-EE API functions are called to set the routing and VS configuration.
     40  * When this timer expires, the configuration is sent to NFCC all at once.
     41  * This is the timeout value for the de-bounce timer. */
     42 #ifndef NFA_EE_ROUT_TIMEOUT_VAL
     43 #define NFA_EE_ROUT_TIMEOUT_VAL 1000
     44 #endif
     45 
     46 #define NFA_EE_ROUT_BUF_SIZE 540
     47 #define NFA_EE_ROUT_MAX_TLV_SIZE 0xFD
     48 
     49 /* the following 2 tables convert the technology mask in API and control block
     50  * to the command for NFCC */
     51 #define NFA_EE_NUM_TECH 3
     52 const uint8_t nfa_ee_tech_mask_list[NFA_EE_NUM_TECH] = {
     53     NFA_TECHNOLOGY_MASK_A, NFA_TECHNOLOGY_MASK_B, NFA_TECHNOLOGY_MASK_F};
     54 
     55 const uint8_t nfa_ee_tech_list[NFA_EE_NUM_TECH] = {
     56     NFC_RF_TECHNOLOGY_A, NFC_RF_TECHNOLOGY_B, NFC_RF_TECHNOLOGY_F};
     57 
     58 /* the following 2 tables convert the protocol mask in API and control block to
     59  * the command for NFCC */
     60 #define NFA_EE_NUM_PROTO 5
     61 
     62 static void add_route_tech_proto_tlv(uint8_t** pp, uint8_t tlv_type,
     63                                      uint8_t nfcee_id, uint8_t pwr_cfg,
     64                                      uint8_t tech_proto) {
     65   *(*pp)++ = tlv_type;
     66   *(*pp)++ = 3;
     67   *(*pp)++ = nfcee_id;
     68   *(*pp)++ = pwr_cfg;
     69   *(*pp)++ = tech_proto;
     70 }
     71 
     72 static void add_route_aid_tlv(uint8_t** pp, uint8_t* pa, uint8_t nfcee_id,
     73                               uint8_t pwr_cfg, uint8_t tag) {
     74   pa++;                /* EMV tag */
     75   uint8_t len = *pa++; /* aid_len */
     76   *(*pp)++ = tag;
     77   *(*pp)++ = len + 2;
     78   *(*pp)++ = nfcee_id;
     79   *(*pp)++ = pwr_cfg;
     80   /* copy the AID */
     81   memcpy(*pp, pa, len);
     82   *pp += len;
     83 }
     84 
     85 static void add_route_sys_code_tlv(uint8_t** p_buff, uint8_t* p_sys_code_cfg,
     86                                    uint8_t sys_code_rt_loc,
     87                                    uint8_t sys_code_pwr_cfg) {
     88   *(*p_buff)++ = NFC_ROUTE_TAG_SYSCODE | nfa_ee_cb.route_block_control;
     89   *(*p_buff)++ = NFA_EE_SYSTEM_CODE_LEN + 2;
     90   *(*p_buff)++ = sys_code_rt_loc;
     91   *(*p_buff)++ = sys_code_pwr_cfg;
     92   /* copy the system code */
     93   memcpy(*p_buff, p_sys_code_cfg, NFA_EE_SYSTEM_CODE_LEN);
     94   *p_buff += NFA_EE_SYSTEM_CODE_LEN;
     95 }
     96 
     97 const uint8_t nfa_ee_proto_mask_list[NFA_EE_NUM_PROTO] = {
     98     NFA_PROTOCOL_MASK_T1T, NFA_PROTOCOL_MASK_T2T, NFA_PROTOCOL_MASK_T3T,
     99     NFA_PROTOCOL_MASK_ISO_DEP, NFA_PROTOCOL_MASK_NFC_DEP};
    100 
    101 const uint8_t nfa_ee_proto_list[NFA_EE_NUM_PROTO] = {
    102     NFC_PROTOCOL_T1T, NFC_PROTOCOL_T2T, NFC_PROTOCOL_T3T, NFC_PROTOCOL_ISO_DEP,
    103     NFC_PROTOCOL_NFC_DEP};
    104 
    105 static void nfa_ee_report_discover_req_evt(void);
    106 static void nfa_ee_build_discover_req_evt(tNFA_EE_DISCOVER_REQ* p_evt_data);
    107 void nfa_ee_check_set_routing(uint16_t new_size, int* p_max_len, uint8_t* p,
    108                               int* p_cur_offset);
    109 /*******************************************************************************
    110 **
    111 ** Function         nfa_ee_trace_aid
    112 **
    113 ** Description      trace AID
    114 **
    115 ** Returns          void
    116 **
    117 *******************************************************************************/
    118 static void nfa_ee_trace_aid(std::string p_str, uint8_t id, uint8_t aid_len,
    119                              uint8_t* p) {
    120   int len = aid_len;
    121   int xx, yy = 0;
    122   char buff[100];
    123 
    124   buff[0] = 0;
    125   if (aid_len > NFA_MAX_AID_LEN) {
    126     LOG(ERROR) << StringPrintf("aid_len: %d exceeds max(%d)", aid_len,
    127                                NFA_MAX_AID_LEN);
    128     len = NFA_MAX_AID_LEN;
    129   }
    130   for (xx = 0; xx < len; xx++) {
    131     yy += sprintf(&buff[yy], "%02x ", *p);
    132     p++;
    133   }
    134   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    135       "%s id:0x%x len=%d aid:%s", p_str.c_str(), id, aid_len, buff);
    136 }
    137 
    138 /*******************************************************************************
    139 **
    140 ** Function         nfa_ee_update_route_size
    141 **
    142 ** Description      Update the size required for technology and protocol routing
    143 **                  of the given NFCEE ID.
    144 **
    145 ** Returns          void
    146 **
    147 *******************************************************************************/
    148 static void nfa_ee_update_route_size(tNFA_EE_ECB* p_cb) {
    149   int xx;
    150   uint8_t power_cfg = 0;
    151 
    152   p_cb->size_mask = 0;
    153   /* add the Technology based routing */
    154   for (xx = 0; xx < NFA_EE_NUM_TECH; xx++) {
    155     power_cfg = 0;
    156     if (p_cb->tech_switch_on & nfa_ee_tech_mask_list[xx])
    157       power_cfg |= NCI_ROUTE_PWR_STATE_ON;
    158     if (p_cb->tech_switch_off & nfa_ee_tech_mask_list[xx])
    159       power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
    160     if (p_cb->tech_battery_off & nfa_ee_tech_mask_list[xx])
    161       power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
    162     if ((power_cfg & NCI_ROUTE_PWR_STATE_ON) &&
    163         (NFC_GetNCIVersion() == NCI_VERSION_2_0)) {
    164       if (p_cb->tech_screen_lock & nfa_ee_tech_mask_list[xx])
    165         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_ON_LOCK();
    166       if (p_cb->tech_screen_off & nfa_ee_tech_mask_list[xx])
    167         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_UNLOCK();
    168       if (p_cb->tech_screen_off_lock & nfa_ee_tech_mask_list[xx])
    169         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_LOCK();
    170     }
    171     if (power_cfg) {
    172       /* 5 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) + 1 (technology) */
    173       p_cb->size_mask += 5;
    174     }
    175   }
    176 
    177   /* add the Protocol based routing */
    178   for (xx = 0; xx < NFA_EE_NUM_PROTO; xx++) {
    179     power_cfg = 0;
    180     if (p_cb->proto_switch_on & nfa_ee_proto_mask_list[xx])
    181       power_cfg |= NCI_ROUTE_PWR_STATE_ON;
    182     if (p_cb->proto_switch_off & nfa_ee_proto_mask_list[xx])
    183       power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
    184     if (p_cb->proto_battery_off & nfa_ee_proto_mask_list[xx])
    185       power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
    186     if ((power_cfg & NCI_ROUTE_PWR_STATE_ON) &&
    187         (NFC_GetNCIVersion() == NCI_VERSION_2_0)) {
    188       if (p_cb->proto_screen_lock & nfa_ee_proto_mask_list[xx])
    189         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_ON_LOCK();
    190       if (p_cb->proto_screen_off & nfa_ee_proto_mask_list[xx])
    191         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_UNLOCK();
    192       if (p_cb->proto_screen_off_lock & nfa_ee_proto_mask_list[xx])
    193         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_LOCK();
    194     }
    195     if (power_cfg) {
    196       /* 5 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) + 1 (protocol) */
    197       p_cb->size_mask += 5;
    198     }
    199   }
    200   DLOG_IF(INFO, nfc_debug_enabled)
    201       << StringPrintf("nfa_ee_update_route_size nfcee_id:0x%x size_mask:%d",
    202                       p_cb->nfcee_id, p_cb->size_mask);
    203 }
    204 
    205 /*******************************************************************************
    206 **
    207 ** Function         nfa_ee_update_route_aid_size
    208 **
    209 ** Description      Update the size required for AID routing
    210 **                  of the given NFCEE ID.
    211 **
    212 ** Returns          void
    213 **
    214 *******************************************************************************/
    215 static void nfa_ee_update_route_aid_size(tNFA_EE_ECB* p_cb) {
    216   uint8_t *pa, len;
    217   int start_offset;
    218   int xx;
    219 
    220   p_cb->size_aid = 0;
    221   if (p_cb->aid_entries) {
    222     start_offset = 0;
    223     for (xx = 0; xx < p_cb->aid_entries; xx++) {
    224       /* add one AID entry */
    225       if (p_cb->aid_rt_info[xx] & NFA_EE_AE_ROUTE) {
    226         pa = &p_cb->aid_cfg[start_offset];
    227         pa++;        /* EMV tag */
    228         len = *pa++; /* aid_len */
    229         /* 4 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) */
    230         p_cb->size_aid += 4;
    231         p_cb->size_aid += len;
    232       }
    233       start_offset += p_cb->aid_len[xx];
    234     }
    235   }
    236   DLOG_IF(INFO, nfc_debug_enabled)
    237       << StringPrintf("nfa_ee_update_route_aid_size nfcee_id:0x%x size_aid:%d",
    238                       p_cb->nfcee_id, p_cb->size_aid);
    239 }
    240 
    241 /*******************************************************************************
    242 **
    243 ** Function         nfa_ee_update_route_sys_code_size
    244 **
    245 ** Description      Update the size required for system code routing
    246 **                  of the given NFCEE ID.
    247 **
    248 ** Returns          void
    249 **
    250 *******************************************************************************/
    251 static void nfa_ee_update_route_sys_code_size(tNFA_EE_ECB* p_cb) {
    252   p_cb->size_sys_code = 0;
    253   if (p_cb->sys_code_cfg_entries) {
    254     for (uint8_t xx = 0; xx < p_cb->sys_code_cfg_entries; xx++) {
    255       if (p_cb->sys_code_rt_loc_vs_info[xx] & NFA_EE_AE_ROUTE) {
    256         /* 4 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) */
    257         p_cb->size_sys_code += 4;
    258         p_cb->size_sys_code += NFA_EE_SYSTEM_CODE_LEN;
    259       }
    260     }
    261   }
    262   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    263       "nfa_ee_update_route_sys_code_size nfcee_id:0x%x size_sys_code:%d",
    264       p_cb->nfcee_id, p_cb->size_sys_code);
    265 }
    266 
    267 /*******************************************************************************
    268 **
    269 ** Function         nfa_ee_total_lmrt_size
    270 **
    271 ** Description      the total listen mode routing table size
    272 **
    273 ** Returns          uint16_t
    274 **
    275 *******************************************************************************/
    276 static uint16_t nfa_ee_total_lmrt_size(void) {
    277   int xx;
    278   uint16_t lmrt_size = 0;
    279   tNFA_EE_ECB* p_cb;
    280 
    281   p_cb = &nfa_ee_cb.ecb[NFA_EE_CB_4_DH];
    282   lmrt_size += p_cb->size_mask;
    283   lmrt_size += p_cb->size_aid;
    284   lmrt_size += p_cb->size_sys_code;
    285   p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
    286   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb--) {
    287     if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE) {
    288       lmrt_size += p_cb->size_mask;
    289       lmrt_size += p_cb->size_aid;
    290       lmrt_size += p_cb->size_sys_code;
    291     }
    292   }
    293   DLOG_IF(INFO, nfc_debug_enabled)
    294       << StringPrintf("nfa_ee_total_lmrt_size size:%d", lmrt_size);
    295   return lmrt_size;
    296 }
    297 
    298 static void nfa_ee_add_tech_route_to_ecb(tNFA_EE_ECB* p_cb, uint8_t* pp,
    299                                          uint8_t* p, uint8_t* ps,
    300                                          int* p_cur_offset) {
    301   uint8_t num_tlv = *ps;
    302 
    303   /* add the Technology based routing */
    304   for (int xx = 0; xx < NFA_EE_NUM_TECH; xx++) {
    305     uint8_t power_cfg = 0;
    306     if (p_cb->tech_switch_on & nfa_ee_tech_mask_list[xx])
    307       power_cfg |= NCI_ROUTE_PWR_STATE_ON;
    308     if (p_cb->tech_switch_off & nfa_ee_tech_mask_list[xx])
    309       power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
    310     if (p_cb->tech_battery_off & nfa_ee_tech_mask_list[xx])
    311       power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
    312     if ((power_cfg & NCI_ROUTE_PWR_STATE_ON) &&
    313         (NFC_GetNCIVersion() == NCI_VERSION_2_0)) {
    314       if (p_cb->tech_screen_lock & nfa_ee_tech_mask_list[xx])
    315         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_ON_LOCK();
    316       if (p_cb->tech_screen_off & nfa_ee_tech_mask_list[xx])
    317         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_UNLOCK();
    318       if (p_cb->tech_screen_off_lock & nfa_ee_tech_mask_list[xx])
    319         power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_LOCK();
    320     }
    321     if (power_cfg) {
    322       add_route_tech_proto_tlv(&pp, NFC_ROUTE_TAG_TECH, p_cb->nfcee_id,
    323                                power_cfg, nfa_ee_tech_list[xx]);
    324       num_tlv++;
    325       if (power_cfg != NCI_ROUTE_PWR_STATE_ON)
    326         nfa_ee_cb.ee_cfged |= NFA_EE_CFGED_OFF_ROUTING;
    327     }
    328   }
    329 
    330   /* update the num_tlv and current offset */
    331   uint8_t entry_size = (uint8_t)(pp - p);
    332   *p_cur_offset += entry_size;
    333   *ps = num_tlv;
    334 }
    335 
    336 static void nfa_ee_add_proto_route_to_ecb(tNFA_EE_ECB* p_cb, uint8_t* pp,
    337                                           uint8_t* p, uint8_t* ps,
    338                                           int* p_cur_offset) {
    339   uint8_t num_tlv = *ps;
    340 
    341   /* add the Protocol based routing */
    342   for (int xx = 0; xx < NFA_EE_NUM_PROTO; xx++) {
    343     uint8_t power_cfg = 0, proto_tag = 0;
    344     if (p_cb->proto_switch_on & nfa_ee_proto_mask_list[xx])
    345       power_cfg |= NCI_ROUTE_PWR_STATE_ON;
    346     if (p_cb->proto_switch_off & nfa_ee_proto_mask_list[xx])
    347       power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
    348     if (p_cb->proto_battery_off & nfa_ee_proto_mask_list[xx])
    349       power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
    350     if (power_cfg) {
    351       /* Applying Route Block for ISO DEP Protocol, so that AIDs
    352        * which are not in the routing table can also be blocked */
    353       if (nfa_ee_proto_mask_list[xx] == NFA_PROTOCOL_MASK_ISO_DEP) {
    354         proto_tag = NFC_ROUTE_TAG_PROTO | nfa_ee_cb.route_block_control;
    355 
    356         /* Enable screen on lock power state for ISO-DEP protocol to
    357            enable HCE screen lock */
    358         if ((power_cfg & NCI_ROUTE_PWR_STATE_ON) &&
    359             (NFC_GetNCIVersion() == NCI_VERSION_2_0)) {
    360           if (p_cb->proto_screen_lock & nfa_ee_proto_mask_list[xx])
    361             power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_ON_LOCK();
    362           if (p_cb->proto_screen_off & nfa_ee_proto_mask_list[xx])
    363             power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_UNLOCK();
    364           if (p_cb->proto_screen_off_lock & nfa_ee_proto_mask_list[xx])
    365             power_cfg |= NCI_ROUTE_PWR_STATE_SCREEN_OFF_LOCK();
    366         }
    367       } else {
    368         proto_tag = NFC_ROUTE_TAG_PROTO;
    369       }
    370 
    371       add_route_tech_proto_tlv(&pp, proto_tag, p_cb->nfcee_id, power_cfg,
    372                                nfa_ee_proto_list[xx]);
    373       num_tlv++;
    374       if (power_cfg != NCI_ROUTE_PWR_STATE_ON)
    375         nfa_ee_cb.ee_cfged |= NFA_EE_CFGED_OFF_ROUTING;
    376     }
    377   }
    378 
    379   /* add NFC-DEP routing to HOST */
    380   if (p_cb->nfcee_id == NFC_DH_ID) {
    381     add_route_tech_proto_tlv(&pp, NFC_ROUTE_TAG_PROTO, NFC_DH_ID,
    382                              NCI_ROUTE_PWR_STATE_ON, NFC_PROTOCOL_NFC_DEP);
    383 
    384     num_tlv++;
    385     DLOG_IF(INFO, nfc_debug_enabled)
    386         << StringPrintf("%s - NFC DEP added for DH!!!", __func__);
    387   }
    388   /* update the num_tlv and current offset */
    389   uint8_t entry_size = (uint8_t)(pp - p);
    390   *p_cur_offset += entry_size;
    391   *ps = num_tlv;
    392 }
    393 
    394 static void nfa_ee_add_aid_route_to_ecb(tNFA_EE_ECB* p_cb, uint8_t* pp,
    395                                         uint8_t* p, uint8_t* ps,
    396                                         int* p_cur_offset, int* p_max_len) {
    397   uint8_t num_tlv = *ps;
    398 
    399   /* add the AID routing */
    400   if (p_cb->aid_entries) {
    401     int start_offset = 0;
    402     for (int xx = 0; xx < p_cb->aid_entries; xx++) {
    403       /* remember the beginning of this AID routing entry, just in case we
    404        * need to put it in next command */
    405       uint8_t route_qual = 0;
    406       uint8_t* p_start = pp;
    407       /* add one AID entry */
    408       if (p_cb->aid_rt_info[xx] & NFA_EE_AE_ROUTE) {
    409         num_tlv++;
    410         uint8_t* pa = &p_cb->aid_cfg[start_offset];
    411 
    412         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    413             "%s -  p_cb->aid_info%x", __func__, p_cb->aid_info[xx]);
    414         if (p_cb->aid_info[xx] & NCI_ROUTE_QUAL_LONG_SELECT) {
    415           DLOG_IF(INFO, nfc_debug_enabled)
    416               << StringPrintf("%s - %x", __func__,
    417                               p_cb->aid_info[xx] & NCI_ROUTE_QUAL_LONG_SELECT);
    418           route_qual |= NCI_ROUTE_QUAL_LONG_SELECT;
    419         }
    420         if (p_cb->aid_info[xx] & NCI_ROUTE_QUAL_SHORT_SELECT) {
    421           DLOG_IF(INFO, nfc_debug_enabled)
    422               << StringPrintf("%s - %x", __func__,
    423                               p_cb->aid_info[xx] & NCI_ROUTE_QUAL_SHORT_SELECT);
    424           route_qual |= NCI_ROUTE_QUAL_SHORT_SELECT;
    425         }
    426 
    427         uint8_t tag =
    428             NFC_ROUTE_TAG_AID | nfa_ee_cb.route_block_control | route_qual;
    429 
    430         add_route_aid_tlv(&pp, pa, p_cb->nfcee_id, p_cb->aid_pwr_cfg[xx], tag);
    431       }
    432       start_offset += p_cb->aid_len[xx];
    433       uint8_t new_size = (uint8_t)(pp - p_start);
    434       nfa_ee_check_set_routing(new_size, p_max_len, ps, p_cur_offset);
    435       if (*ps == 0) {
    436         /* just sent routing command, update local */
    437         *ps = 1;
    438         num_tlv = *ps;
    439         *p_cur_offset = new_size;
    440         pp = ps + 1;
    441         p = pp;
    442         memcpy(p, p_start, new_size);
    443         pp += new_size;
    444       } else {
    445         /* add the new entry */
    446         *ps = num_tlv;
    447         *p_cur_offset += new_size;
    448       }
    449     }
    450   } else {
    451     DLOG_IF(INFO, nfc_debug_enabled)
    452         << StringPrintf("%s - No AID entries available", __func__);
    453   }
    454 }
    455 
    456 static void nfa_ee_add_sys_code_route_to_ecb(tNFA_EE_ECB* p_cb, uint8_t* pp,
    457                                              uint8_t* p, uint8_t* p_buff,
    458                                              int* p_cur_offset,
    459                                              int* p_max_len) {
    460   uint8_t num_tlv = *p_buff;
    461 
    462   /* add the SC routing */
    463   if (p_cb->sys_code_cfg_entries) {
    464     int start_offset = 0;
    465     for (int xx = 0; xx < p_cb->sys_code_cfg_entries; xx++) {
    466       /* remember the beginning of this SC routing entry, just in case we
    467        * need to put it in next command */
    468       uint8_t* p_start = pp;
    469       /* add one SC entry */
    470       if (p_cb->sys_code_rt_loc_vs_info[xx] & NFA_EE_AE_ROUTE) {
    471         uint8_t* p_sys_code_cfg = &p_cb->sys_code_cfg[start_offset];
    472         if (nfa_ee_is_active(p_cb->sys_code_rt_loc[xx] | NFA_HANDLE_GROUP_EE)) {
    473           add_route_sys_code_tlv(&pp, p_sys_code_cfg, p_cb->sys_code_rt_loc[xx],
    474                                  p_cb->sys_code_pwr_cfg[xx]);
    475           p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_ROUTING;
    476           num_tlv++;
    477         } else {
    478           DLOG_IF(INFO, nfc_debug_enabled)
    479               << StringPrintf("%s -  ignoring route loc%x", __func__,
    480                               p_cb->sys_code_rt_loc[xx]);
    481         }
    482       }
    483       start_offset += NFA_EE_SYSTEM_CODE_LEN;
    484       uint8_t new_size = (uint8_t)(pp - p_start);
    485       nfa_ee_check_set_routing(new_size, p_max_len, p_buff, p_cur_offset);
    486       if (*p_buff == 0 && (num_tlv > 0x00)) {
    487         /* just sent routing command, update local */
    488         *p_buff = 1;
    489         num_tlv = *p_buff;
    490         *p_cur_offset = new_size;
    491         pp = p_buff + 1;
    492         p = pp;
    493         memcpy(p, p_start, new_size);
    494         pp += new_size;
    495       } else {
    496         /* add the new entry */
    497         *p_buff = num_tlv;
    498         *p_cur_offset += new_size;
    499       }
    500     }
    501     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    502         "nfa_ee_route_add_one_ecb_by_route_order --num_tlv:- %d", num_tlv);
    503   } else {
    504     DLOG_IF(INFO, nfc_debug_enabled)
    505         << StringPrintf("%s - No SC entries available", __func__);
    506   }
    507 }
    508 
    509 /*******************************************************************************
    510 **
    511 ** Function         nfa_ee_conn_cback
    512 **
    513 ** Description      process connection callback event from stack
    514 **
    515 ** Returns          void
    516 **
    517 *******************************************************************************/
    518 static void nfa_ee_conn_cback(uint8_t conn_id, tNFC_CONN_EVT event,
    519                               tNFC_CONN* p_data) {
    520   tNFA_EE_NCI_CONN cbk;
    521 
    522   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    523       "nfa_ee_conn_cback: conn_id: %d, event=0x%02x", conn_id, event);
    524 
    525   cbk.hdr.event = NFA_EE_NCI_CONN_EVT;
    526   if (event == NFC_DATA_CEVT) {
    527     /* Treat data event specially to avoid potential memory leak */
    528     cbk.hdr.event = NFA_EE_NCI_DATA_EVT;
    529   }
    530   cbk.conn_id = conn_id;
    531   cbk.event = event;
    532   cbk.p_data = p_data;
    533   tNFA_EE_MSG nfa_ee_msg;
    534   nfa_ee_msg.conn = cbk;
    535 
    536   nfa_ee_evt_hdlr(&nfa_ee_msg.hdr);
    537 }
    538 
    539 /*******************************************************************************
    540 **
    541 ** Function         nfa_ee_find_total_aid_len
    542 **
    543 ** Description      Find the total len in aid_cfg from start_entry to the last
    544 **
    545 ** Returns          void
    546 **
    547 *******************************************************************************/
    548 int nfa_ee_find_total_aid_len(tNFA_EE_ECB* p_cb, int start_entry) {
    549   int len = 0, xx;
    550 
    551   if (p_cb->aid_entries > start_entry) {
    552     for (xx = start_entry; xx < p_cb->aid_entries; xx++) {
    553       len += p_cb->aid_len[xx];
    554     }
    555   }
    556   return len;
    557 }
    558 
    559 /*******************************************************************************
    560 **
    561 ** Function         nfa_ee_find_total_sys_code_len
    562 **
    563 ** Description      Find the total len in sys_code_cfg from start_entry to the
    564 **                  last in the given ecb.
    565 **
    566 ** Returns          void
    567 **
    568 *******************************************************************************/
    569 int nfa_ee_find_total_sys_code_len(tNFA_EE_ECB* p_cb, int start_entry) {
    570   int len = 0;
    571   if (p_cb->sys_code_cfg_entries > start_entry) {
    572     for (int xx = start_entry; xx < p_cb->sys_code_cfg_entries; xx++) {
    573       len += NFA_EE_SYSTEM_CODE_LEN;
    574     }
    575   }
    576   return len;
    577 }
    578 
    579 /*******************************************************************************
    580 **
    581 ** Function         nfa_all_ee_find_total_sys_code_len
    582 **
    583 ** Description      Find the total len in sys_code_cfg from start_entry to the
    584 **                  last for all EE and DH.
    585 **
    586 ** Returns          total length
    587 **
    588 *******************************************************************************/
    589 int nfa_all_ee_find_total_sys_code_len() {
    590   int total_len = 0;
    591   for (int32_t xx = 0; xx < NFA_EE_NUM_ECBS; xx++) {
    592     tNFA_EE_ECB* p_cb = &nfa_ee_cb.ecb[xx];
    593     total_len += nfa_ee_find_total_sys_code_len(p_cb, 0);
    594   }
    595   return total_len;
    596 }
    597 
    598 /*******************************************************************************
    599 **
    600 ** Function         nfa_ee_find_aid_offset
    601 **
    602 ** Description      Given the AID, find the associated tNFA_EE_ECB and the
    603 **                  offset in aid_cfg[]. *p_entry is the index.
    604 **
    605 ** Returns          void
    606 **
    607 *******************************************************************************/
    608 tNFA_EE_ECB* nfa_ee_find_aid_offset(uint8_t aid_len, uint8_t* p_aid,
    609                                     int* p_offset, int* p_entry) {
    610   int xx, yy, aid_len_offset, offset;
    611   tNFA_EE_ECB *p_ret = NULL, *p_ecb;
    612 
    613   p_ecb = &nfa_ee_cb.ecb[NFA_EE_CB_4_DH];
    614   aid_len_offset = 1; /* skip the tag */
    615   for (yy = 0; yy < nfa_ee_cb.cur_ee; yy++, p_ecb++) {
    616     if (p_ecb->aid_entries) {
    617       offset = 0;
    618       for (xx = 0; xx < p_ecb->aid_entries; xx++) {
    619         if ((p_ecb->aid_cfg[offset + aid_len_offset] == aid_len) &&
    620             (memcmp(&p_ecb->aid_cfg[offset + aid_len_offset + 1], p_aid,
    621                     aid_len) == 0)) {
    622           p_ret = p_ecb;
    623           if (p_offset) *p_offset = offset;
    624           if (p_entry) *p_entry = xx;
    625           break;
    626         }
    627         offset += p_ecb->aid_len[xx];
    628       }
    629 
    630       if (p_ret) {
    631         /* found the entry already */
    632         break;
    633       }
    634     }
    635     p_ecb = &nfa_ee_cb.ecb[yy];
    636   }
    637 
    638   return p_ret;
    639 }
    640 
    641 /*******************************************************************************
    642  **
    643  ** Function         nfa_ee_find_sys_code_offset
    644  **
    645  ** Description      Given the System Code, find the associated tNFA_EE_ECB and
    646  *the
    647  **                  offset in sys_code_cfg[]. *p_entry is the index.
    648  **
    649  ** Returns          void
    650  **
    651  *******************************************************************************/
    652 tNFA_EE_ECB* nfa_ee_find_sys_code_offset(uint16_t sys_code, int* p_offset,
    653                                          int* p_entry) {
    654   tNFA_EE_ECB* p_ret = NULL;
    655 
    656   for (uint8_t xx = 0; xx < NFA_EE_NUM_ECBS; xx++) {
    657     tNFA_EE_ECB* p_ecb = &nfa_ee_cb.ecb[xx];
    658     uint8_t mask = nfa_ee_ecb_to_mask(p_ecb);
    659     if ((nfa_ee_cb.ee_cfged & mask) == 0 || p_ecb->sys_code_cfg_entries == 0) {
    660       continue; /*try next ecb*/
    661     }
    662     if (p_ecb->sys_code_cfg_entries) {
    663       uint8_t offset = 0;
    664       for (uint8_t yy = 0; yy < p_ecb->sys_code_cfg_entries; yy++) {
    665         if ((memcmp(&p_ecb->sys_code_cfg[offset], &sys_code,
    666                     NFA_EE_SYSTEM_CODE_LEN) == 0)) {
    667           p_ret = p_ecb;
    668           if (p_offset) *p_offset = offset;
    669           if (p_entry) *p_entry = yy;
    670           break;
    671         }
    672         offset += NFA_EE_SYSTEM_CODE_LEN;
    673       }
    674 
    675       if (p_ret) {
    676         /* found the entry already */
    677         return p_ret;
    678       }
    679     }
    680   }
    681   return p_ret;
    682 }
    683 
    684 /*******************************************************************************
    685 **
    686 ** Function         nfa_ee_report_event
    687 **
    688 ** Description      report the given event to the callback
    689 **
    690 ** Returns          void
    691 **
    692 *******************************************************************************/
    693 void nfa_ee_report_event(tNFA_EE_CBACK* p_cback, tNFA_EE_EVT event,
    694                          tNFA_EE_CBACK_DATA* p_data) {
    695   int xx;
    696 
    697   /* use the given callback, if not NULL */
    698   if (p_cback) {
    699     (*p_cback)(event, p_data);
    700     return;
    701   }
    702   /* if the given is NULL, report to all registered ones */
    703   for (xx = 0; xx < NFA_EE_MAX_CBACKS; xx++) {
    704     if (nfa_ee_cb.p_ee_cback[xx] != NULL) {
    705       (*nfa_ee_cb.p_ee_cback[xx])(event, p_data);
    706     }
    707   }
    708 }
    709 /*******************************************************************************
    710 **
    711 ** Function         nfa_ee_start_timer
    712 **
    713 ** Description      start the de-bounce timer
    714 **
    715 ** Returns          void
    716 **
    717 *******************************************************************************/
    718 void nfa_ee_start_timer(void) {
    719   if (nfa_dm_is_active())
    720     nfa_sys_start_timer(&nfa_ee_cb.timer, NFA_EE_ROUT_TIMEOUT_EVT,
    721                         NFA_EE_ROUT_TIMEOUT_VAL);
    722 }
    723 
    724 /*******************************************************************************
    725 **
    726 ** Function         nfa_ee_api_discover
    727 **
    728 ** Description      process discover command from user
    729 **
    730 ** Returns          void
    731 **
    732 *******************************************************************************/
    733 void nfa_ee_api_discover(tNFA_EE_MSG* p_data) {
    734   tNFA_EE_CBACK* p_cback = p_data->ee_discover.p_cback;
    735   tNFA_EE_CBACK_DATA evt_data = {0};
    736 
    737   DLOG_IF(INFO, nfc_debug_enabled)
    738       << StringPrintf("in_use:%d", nfa_ee_cb.discv_timer.in_use);
    739   if (nfa_ee_cb.discv_timer.in_use) {
    740     nfa_sys_stop_timer(&nfa_ee_cb.discv_timer);
    741     if (NFA_GetNCIVersion() != NCI_VERSION_2_0) NFC_NfceeDiscover(false);
    742   }
    743   if (nfa_ee_cb.p_ee_disc_cback == NULL &&
    744       NFC_NfceeDiscover(true) == NFC_STATUS_OK) {
    745     nfa_ee_cb.p_ee_disc_cback = p_cback;
    746   } else {
    747     evt_data.status = NFA_STATUS_FAILED;
    748     nfa_ee_report_event(p_cback, NFA_EE_DISCOVER_EVT, &evt_data);
    749   }
    750 }
    751 
    752 /*******************************************************************************
    753 **
    754 ** Function         nfa_ee_api_register
    755 **
    756 ** Description      process register command from user
    757 **
    758 ** Returns          void
    759 **
    760 *******************************************************************************/
    761 void nfa_ee_api_register(tNFA_EE_MSG* p_data) {
    762   int xx;
    763   tNFA_EE_CBACK* p_cback = p_data->ee_register.p_cback;
    764   tNFA_EE_CBACK_DATA evt_data = {0};
    765   bool found = false;
    766 
    767   evt_data.ee_register = NFA_STATUS_FAILED;
    768   /* loop through all entries to see if there's a matching callback */
    769   for (xx = 0; xx < NFA_EE_MAX_CBACKS; xx++) {
    770     if (nfa_ee_cb.p_ee_cback[xx] == p_cback) {
    771       evt_data.ee_register = NFA_STATUS_OK;
    772       found = true;
    773       break;
    774     }
    775   }
    776 
    777   /* If no matching callback, allocated an entry */
    778   if (!found) {
    779     for (xx = 0; xx < NFA_EE_MAX_CBACKS; xx++) {
    780       if (nfa_ee_cb.p_ee_cback[xx] == NULL) {
    781         nfa_ee_cb.p_ee_cback[xx] = p_cback;
    782         evt_data.ee_register = NFA_STATUS_OK;
    783         break;
    784       }
    785     }
    786   }
    787   /* This callback is verified (not NULL) in NFA_EeRegister() */
    788   (*p_cback)(NFA_EE_REGISTER_EVT, &evt_data);
    789 
    790   /* report NFCEE Discovery Request collected during booting up */
    791   nfa_ee_build_discover_req_evt(&evt_data.discover_req);
    792   (*p_cback)(NFA_EE_DISCOVER_REQ_EVT, &evt_data);
    793 }
    794 
    795 /*******************************************************************************
    796 **
    797 ** Function         nfa_ee_api_deregister
    798 **
    799 ** Description      process de-register command from user
    800 **
    801 ** Returns          void
    802 **
    803 *******************************************************************************/
    804 void nfa_ee_api_deregister(tNFA_EE_MSG* p_data) {
    805   tNFA_EE_CBACK* p_cback = NULL;
    806   int index = p_data->deregister.index;
    807   tNFA_EE_CBACK_DATA evt_data = {0};
    808 
    809   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("nfa_ee_api_deregister");
    810   p_cback = nfa_ee_cb.p_ee_cback[index];
    811   nfa_ee_cb.p_ee_cback[index] = NULL;
    812   if (p_cback) (*p_cback)(NFA_EE_DEREGISTER_EVT, &evt_data);
    813 }
    814 
    815 /*******************************************************************************
    816 **
    817 ** Function         nfa_ee_api_mode_set
    818 **
    819 ** Description      process mode set command from user
    820 **
    821 ** Returns          void
    822 **
    823 *******************************************************************************/
    824 void nfa_ee_api_mode_set(tNFA_EE_MSG* p_data) {
    825   tNFA_EE_ECB* p_cb = p_data->cfg_hdr.p_cb;
    826   tNFA_EE_MODE_SET mode_set;
    827   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    828       "handle:0x%02x mode:%d", p_cb->nfcee_id, p_data->mode_set.mode);
    829   mode_set.status = NFC_NfceeModeSet(p_cb->nfcee_id, p_data->mode_set.mode);
    830   if (mode_set.status != NFC_STATUS_OK) {
    831     /* the api is rejected at NFC layer, report the failure status right away */
    832     mode_set.ee_handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
    833     mode_set.ee_status = p_data->mode_set.mode;
    834     tNFA_EE_CBACK_DATA nfa_ee_cback_data;
    835     nfa_ee_cback_data.mode_set = mode_set;
    836     nfa_ee_report_event(NULL, NFA_EE_MODE_SET_EVT, &nfa_ee_cback_data);
    837     return;
    838   }
    839   /* set the NFA_EE_STATUS_PENDING bit to indicate the status is not exactly
    840    * active */
    841   if (p_data->mode_set.mode == NFC_MODE_ACTIVATE)
    842     p_cb->ee_status = NFA_EE_STATUS_PENDING | NFA_EE_STATUS_ACTIVE;
    843   else {
    844     p_cb->ee_status = NFA_EE_STATUS_INACTIVE;
    845     /* DH should release the NCI connection before deactivate the NFCEE */
    846     if (p_cb->conn_st == NFA_EE_CONN_ST_CONN) {
    847       p_cb->conn_st = NFA_EE_CONN_ST_DISC;
    848       NFC_ConnClose(p_cb->conn_id);
    849     }
    850   }
    851   /* report the NFA_EE_MODE_SET_EVT status on the response from NFCC */
    852 }
    853 
    854 /*******************************************************************************
    855 **
    856 ** Function         nfa_ee_api_set_tech_cfg
    857 **
    858 ** Description      process set technology routing configuration from user
    859 **                  start a 1 second timer. When the timer expires,
    860 **                  the configuration collected in control block is sent to NFCC
    861 **
    862 ** Returns          void
    863 **
    864 *******************************************************************************/
    865 void nfa_ee_api_set_tech_cfg(tNFA_EE_MSG* p_data) {
    866   tNFA_EE_ECB* p_cb = p_data->cfg_hdr.p_cb;
    867   tNFA_EE_CBACK_DATA evt_data = {0};
    868   tNFA_TECHNOLOGY_MASK old_tech_switch_on = p_cb->tech_switch_on;
    869   tNFA_TECHNOLOGY_MASK old_tech_switch_off = p_cb->tech_switch_off;
    870   tNFA_TECHNOLOGY_MASK old_tech_battery_off = p_cb->tech_battery_off;
    871   tNFA_TECHNOLOGY_MASK old_tech_screen_lock = p_cb->tech_screen_lock;
    872   tNFA_TECHNOLOGY_MASK old_tech_screen_off = p_cb->tech_screen_off;
    873   tNFA_TECHNOLOGY_MASK old_tech_screen_off_lock = p_cb->tech_screen_off_lock;
    874   uint8_t old_size_mask = p_cb->size_mask;
    875 
    876   if ((p_cb->tech_switch_on == p_data->set_tech.technologies_switch_on) &&
    877       (p_cb->tech_switch_off == p_data->set_tech.technologies_switch_off) &&
    878       (p_cb->tech_battery_off == p_data->set_tech.technologies_battery_off) &&
    879       (p_cb->tech_screen_lock == p_data->set_tech.technologies_screen_lock) &&
    880       (p_cb->tech_screen_off == p_data->set_tech.technologies_screen_off) &&
    881       (p_cb->tech_screen_off_lock ==
    882        p_data->set_tech.technologies_screen_off_lock)) {
    883     /* nothing to change */
    884     evt_data.status = NFA_STATUS_OK;
    885     nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_SET_TECH_CFG_EVT, &evt_data);
    886     return;
    887   }
    888 
    889   p_cb->tech_switch_on |= p_data->set_tech.technologies_switch_on;
    890   p_cb->tech_switch_off |= p_data->set_tech.technologies_switch_off;
    891   p_cb->tech_battery_off |= p_data->set_tech.technologies_battery_off;
    892   p_cb->tech_screen_lock |= p_data->set_tech.technologies_screen_lock;
    893   p_cb->tech_screen_off |= p_data->set_tech.technologies_screen_off;
    894   p_cb->tech_screen_off_lock |= p_data->set_tech.technologies_screen_off_lock;
    895   nfa_ee_update_route_size(p_cb);
    896   if (nfa_ee_total_lmrt_size() > NFC_GetLmrtSize()) {
    897     LOG(ERROR) << StringPrintf("nfa_ee_api_set_tech_cfg Exceed LMRT size");
    898     evt_data.status = NFA_STATUS_BUFFER_FULL;
    899     p_cb->tech_switch_on = old_tech_switch_on;
    900     p_cb->tech_switch_off = old_tech_switch_off;
    901     p_cb->tech_battery_off = old_tech_battery_off;
    902     p_cb->tech_screen_lock = old_tech_screen_lock;
    903     p_cb->tech_screen_off = old_tech_screen_off;
    904     p_cb->tech_screen_off_lock = old_tech_screen_off_lock;
    905     p_cb->size_mask = old_size_mask;
    906   } else {
    907     p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_TECH;
    908     if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off |
    909         p_cb->tech_screen_lock | p_cb->tech_screen_off |
    910         p_cb->tech_screen_off_lock) {
    911       /* if any technology in any power mode is configured, mark this entry as
    912        * configured */
    913       nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
    914     }
    915     nfa_ee_start_timer();
    916   }
    917   nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_SET_TECH_CFG_EVT, &evt_data);
    918 }
    919 
    920 /*******************************************************************************
    921 **
    922 ** Function         nfa_ee_api_set_proto_cfg
    923 **
    924 ** Description      process set protocol routing configuration from user
    925 **                  start a 1 second timer. When the timer expires,
    926 **                  the configuration collected in control block is sent to NFCC
    927 **
    928 ** Returns          void
    929 **
    930 *******************************************************************************/
    931 void nfa_ee_api_set_proto_cfg(tNFA_EE_MSG* p_data) {
    932   tNFA_EE_ECB* p_cb = p_data->cfg_hdr.p_cb;
    933   tNFA_EE_CBACK_DATA evt_data = {0};
    934   tNFA_PROTOCOL_MASK old_proto_switch_on = p_cb->proto_switch_on;
    935   tNFA_PROTOCOL_MASK old_proto_switch_off = p_cb->proto_switch_off;
    936   tNFA_PROTOCOL_MASK old_proto_battery_off = p_cb->proto_battery_off;
    937   tNFA_PROTOCOL_MASK old_proto_screen_lock = p_cb->proto_screen_lock;
    938   tNFA_PROTOCOL_MASK old_proto_screen_off = p_cb->proto_screen_off;
    939   tNFA_PROTOCOL_MASK old_proto_screen_off_lock = p_cb->proto_screen_off_lock;
    940   uint8_t old_size_mask = p_cb->size_mask;
    941 
    942   if ((p_cb->proto_switch_on == p_data->set_proto.protocols_switch_on) &&
    943       (p_cb->proto_switch_off == p_data->set_proto.protocols_switch_off) &&
    944       (p_cb->proto_battery_off == p_data->set_proto.protocols_battery_off) &&
    945       (p_cb->proto_screen_lock == p_data->set_proto.protocols_screen_lock) &&
    946       (p_cb->proto_screen_off == p_data->set_proto.protocols_screen_off) &&
    947       (p_cb->proto_screen_off_lock ==
    948        p_data->set_proto.protocols_screen_off_lock)) {
    949     /* nothing to change */
    950     evt_data.status = NFA_STATUS_OK;
    951     nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_SET_PROTO_CFG_EVT, &evt_data);
    952     return;
    953   }
    954 
    955   p_cb->proto_switch_on |= p_data->set_proto.protocols_switch_on;
    956   p_cb->proto_switch_off |= p_data->set_proto.protocols_switch_off;
    957   p_cb->proto_battery_off |= p_data->set_proto.protocols_battery_off;
    958   p_cb->proto_screen_lock |= p_data->set_proto.protocols_screen_lock;
    959   p_cb->proto_screen_off |= p_data->set_proto.protocols_screen_off;
    960   p_cb->proto_screen_off_lock |= p_data->set_proto.protocols_screen_off_lock;
    961   nfa_ee_update_route_size(p_cb);
    962   if (nfa_ee_total_lmrt_size() > NFC_GetLmrtSize()) {
    963     LOG(ERROR) << StringPrintf("nfa_ee_api_set_proto_cfg Exceed LMRT size");
    964     evt_data.status = NFA_STATUS_BUFFER_FULL;
    965     p_cb->proto_switch_on = old_proto_switch_on;
    966     p_cb->proto_switch_off = old_proto_switch_off;
    967     p_cb->proto_battery_off = old_proto_battery_off;
    968     p_cb->proto_screen_lock = old_proto_screen_lock;
    969     p_cb->proto_screen_off = old_proto_screen_off;
    970     p_cb->proto_screen_off_lock = old_proto_screen_off_lock;
    971     p_cb->size_mask = old_size_mask;
    972   } else {
    973     p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_PROTO;
    974     if (p_cb->proto_switch_on | p_cb->proto_switch_off |
    975         p_cb->proto_battery_off | p_cb->proto_screen_lock |
    976         p_cb->proto_screen_off | p_cb->proto_screen_off_lock) {
    977       /* if any protocol in any power mode is configured, mark this entry as
    978        * configured */
    979       nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
    980     }
    981     nfa_ee_start_timer();
    982   }
    983   nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_SET_PROTO_CFG_EVT, &evt_data);
    984 }
    985 
    986 /*******************************************************************************
    987 **
    988 ** Function         nfa_ee_api_add_aid
    989 **
    990 ** Description      process add an AID routing configuration from user
    991 **                  start a 1 second timer. When the timer expires,
    992 **                  the configuration collected in control block is sent to NFCC
    993 **
    994 ** Returns          void
    995 **
    996 *******************************************************************************/
    997 void nfa_ee_api_add_aid(tNFA_EE_MSG* p_data) {
    998   tNFA_EE_API_ADD_AID* p_add = &p_data->add_aid;
    999   tNFA_EE_ECB* p_cb = p_data->cfg_hdr.p_cb;
   1000   tNFA_EE_ECB* p_chk_cb;
   1001   uint8_t *p, *p_start;
   1002   int len, len_needed;
   1003   tNFA_EE_CBACK_DATA evt_data = {0};
   1004   int offset = 0, entry = 0;
   1005   uint16_t new_size;
   1006 
   1007   nfa_ee_trace_aid("nfa_ee_api_add_aid", p_cb->nfcee_id, p_add->aid_len,
   1008                    p_add->p_aid);
   1009   p_chk_cb =
   1010       nfa_ee_find_aid_offset(p_add->aid_len, p_add->p_aid, &offset, &entry);
   1011   if (p_chk_cb) {
   1012     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1013         "nfa_ee_api_add_aid The AID entry is already in the database");
   1014     if (p_chk_cb == p_cb) {
   1015       p_cb->aid_rt_info[entry] |= NFA_EE_AE_ROUTE;
   1016       p_cb->aid_info[entry] = p_add->aidInfo;
   1017       new_size = nfa_ee_total_lmrt_size();
   1018       if (new_size > NFC_GetLmrtSize()) {
   1019         LOG(ERROR) << StringPrintf("Exceed LMRT size:%d (add ROUTE)", new_size);
   1020         evt_data.status = NFA_STATUS_BUFFER_FULL;
   1021         p_cb->aid_rt_info[entry] &= ~NFA_EE_AE_ROUTE;
   1022       } else {
   1023         p_cb->aid_pwr_cfg[entry] = p_add->power_state;
   1024       }
   1025     } else {
   1026       LOG(ERROR) << StringPrintf(
   1027           "The AID entry is already in the database for different NFCEE "
   1028           "ID:0x%02x",
   1029           p_chk_cb->nfcee_id);
   1030       evt_data.status = NFA_STATUS_SEMANTIC_ERROR;
   1031     }
   1032   } else {
   1033     /* Find the total length so far */
   1034     len = nfa_ee_find_total_aid_len(p_cb, 0);
   1035 
   1036     /* make sure the control block has enough room to hold this entry */
   1037     len_needed = p_add->aid_len + 2; /* tag/len */
   1038 
   1039     if ((len_needed + len) > NFA_EE_MAX_AID_CFG_LEN) {
   1040       LOG(ERROR) << StringPrintf(
   1041           "Exceed capacity: (len_needed:%d + len:%d) > "
   1042           "NFA_EE_MAX_AID_CFG_LEN:%d",
   1043           len_needed, len, NFA_EE_MAX_AID_CFG_LEN);
   1044       evt_data.status = NFA_STATUS_BUFFER_FULL;
   1045     } else if (p_cb->aid_entries < NFA_EE_MAX_AID_ENTRIES) {
   1046       /* 4 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) */
   1047       new_size = nfa_ee_total_lmrt_size() + 4 + p_add->aid_len;
   1048       if (new_size > NFC_GetLmrtSize()) {
   1049         LOG(ERROR) << StringPrintf("Exceed LMRT size:%d", new_size);
   1050         evt_data.status = NFA_STATUS_BUFFER_FULL;
   1051       } else {
   1052         /* add AID */
   1053         p_cb->aid_pwr_cfg[p_cb->aid_entries] = p_add->power_state;
   1054         p_cb->aid_info[p_cb->aid_entries] = p_add->aidInfo;
   1055         p_cb->aid_rt_info[p_cb->aid_entries] = NFA_EE_AE_ROUTE;
   1056         p = p_cb->aid_cfg + len;
   1057         p_start = p;
   1058         *p++ = NFA_EE_AID_CFG_TAG_NAME;
   1059         *p++ = p_add->aid_len;
   1060         memcpy(p, p_add->p_aid, p_add->aid_len);
   1061         p += p_add->aid_len;
   1062 
   1063         p_cb->aid_len[p_cb->aid_entries++] = (uint8_t)(p - p_start);
   1064       }
   1065     } else {
   1066       LOG(ERROR) << StringPrintf("Exceed NFA_EE_MAX_AID_ENTRIES:%d",
   1067                                  NFA_EE_MAX_AID_ENTRIES);
   1068       evt_data.status = NFA_STATUS_BUFFER_FULL;
   1069     }
   1070   }
   1071 
   1072   if (evt_data.status == NFA_STATUS_OK) {
   1073     /* mark AID changed */
   1074     p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_AID;
   1075     nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
   1076     nfa_ee_update_route_aid_size(p_cb);
   1077     nfa_ee_start_timer();
   1078   }
   1079   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1080       "status:%d ee_cfged:0x%02x ", evt_data.status, nfa_ee_cb.ee_cfged);
   1081   /* report the status of this operation */
   1082   nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_ADD_AID_EVT, &evt_data);
   1083 }
   1084 
   1085 /*******************************************************************************
   1086 **
   1087 ** Function         nfa_ee_api_remove_aid
   1088 **
   1089 ** Description      process remove an AID routing configuration from user
   1090 **                  start a 1 second timer. When the timer expires,
   1091 **                  the configuration collected in control block is sent to NFCC
   1092 **
   1093 ** Returns          void
   1094 **
   1095 *******************************************************************************/
   1096 void nfa_ee_api_remove_aid(tNFA_EE_MSG* p_data) {
   1097   tNFA_EE_ECB* p_cb;
   1098   tNFA_EE_CBACK_DATA evt_data = {0};
   1099   int offset = 0, entry = 0, len;
   1100   int rest_len;
   1101   tNFA_EE_CBACK* p_cback = NULL;
   1102 
   1103   nfa_ee_trace_aid("nfa_ee_api_remove_aid", 0, p_data->rm_aid.aid_len,
   1104                    p_data->rm_aid.p_aid);
   1105   p_cb = nfa_ee_find_aid_offset(p_data->rm_aid.aid_len, p_data->rm_aid.p_aid,
   1106                                 &offset, &entry);
   1107   if (p_cb && p_cb->aid_entries) {
   1108     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1109         "aid_rt_info[%d]: 0x%02x", entry, p_cb->aid_rt_info[entry]);
   1110     /* mark routing and VS changed */
   1111     if (p_cb->aid_rt_info[entry] & NFA_EE_AE_ROUTE)
   1112       p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_AID;
   1113 
   1114     if (p_cb->aid_rt_info[entry] & NFA_EE_AE_VS)
   1115       p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_VS;
   1116 
   1117     /* remove the aid */
   1118     if ((entry + 1) < p_cb->aid_entries) {
   1119       /* not the last entry, move the aid entries in control block */
   1120       /* Find the total len from the next entry to the last one */
   1121       rest_len = nfa_ee_find_total_aid_len(p_cb, entry + 1);
   1122 
   1123       len = p_cb->aid_len[entry];
   1124       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1125           "nfa_ee_api_remove_aid len:%d, rest_len:%d", len, rest_len);
   1126       GKI_shiftup(&p_cb->aid_cfg[offset], &p_cb->aid_cfg[offset + len],
   1127                   rest_len);
   1128       rest_len = p_cb->aid_entries - entry;
   1129       GKI_shiftup(&p_cb->aid_len[entry], &p_cb->aid_len[entry + 1], rest_len);
   1130       GKI_shiftup(&p_cb->aid_pwr_cfg[entry], &p_cb->aid_pwr_cfg[entry + 1],
   1131                   rest_len);
   1132       GKI_shiftup(&p_cb->aid_rt_info[entry], &p_cb->aid_rt_info[entry + 1],
   1133                   rest_len);
   1134     }
   1135     /* else the last entry, just reduce the aid_entries by 1 */
   1136     p_cb->aid_entries--;
   1137     nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
   1138     nfa_ee_update_route_aid_size(p_cb);
   1139     nfa_ee_start_timer();
   1140     /* report NFA_EE_REMOVE_AID_EVT to the callback associated the NFCEE */
   1141     p_cback = p_cb->p_ee_cback;
   1142   } else {
   1143     LOG(ERROR) << StringPrintf(
   1144         "nfa_ee_api_remove_aid The AID entry is not in the database");
   1145     evt_data.status = NFA_STATUS_INVALID_PARAM;
   1146   }
   1147   nfa_ee_report_event(p_cback, NFA_EE_REMOVE_AID_EVT, &evt_data);
   1148 }
   1149 
   1150 /*******************************************************************************
   1151  **
   1152  ** Function         nfa_ee_api_add_sys_code
   1153  **
   1154  ** Description      Adds System Code routing configuration from user. When the
   1155  **                  timer expires, the configuration collected in control block
   1156  **                  is sent to NFCC
   1157  **
   1158  ** Returns          void
   1159  **
   1160  *******************************************************************************/
   1161 void nfa_ee_api_add_sys_code(tNFA_EE_MSG* p_data) {
   1162   tNFA_EE_CBACK_DATA evt_data = {0};
   1163   tNFA_EE_API_ADD_SYSCODE* p_add = &p_data->add_syscode;
   1164   tNFA_EE_ECB* p_cb = p_data->cfg_hdr.p_cb;
   1165 
   1166   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1167       "%s id:0x%x SC:0x%X ", __func__, p_add->nfcee_id, p_add->syscode);
   1168 
   1169   int offset = 0, entry = 0;
   1170   tNFA_EE_ECB* p_chk_cb =
   1171       nfa_ee_find_sys_code_offset(p_add->syscode, &offset, &entry);
   1172 
   1173   if (p_chk_cb) {
   1174     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1175         "%s: The SC entry already registered "
   1176         "for this NFCEE id:0x%02x",
   1177         __func__, p_add->nfcee_id);
   1178 
   1179     if (p_chk_cb == p_cb) {
   1180       p_cb->sys_code_rt_loc_vs_info[entry] |= NFA_EE_AE_ROUTE;
   1181       uint16_t new_size = nfa_ee_total_lmrt_size();
   1182       if (new_size > NFC_GetLmrtSize()) {
   1183         LOG(ERROR) << StringPrintf("Exceeded LMRT size:%d (add SYSCODE)",
   1184                                    new_size);
   1185         evt_data.status = NFA_STATUS_BUFFER_FULL;
   1186         p_cb->sys_code_rt_loc_vs_info[entry] &= ~NFA_EE_AE_ROUTE;
   1187       } else {
   1188         p_cb->sys_code_pwr_cfg[entry] = p_add->power_state;
   1189       }
   1190     } else {
   1191       LOG(ERROR) << StringPrintf(
   1192           "%s: SystemCode entry already registered for different "
   1193           "NFCEE id:0x%02x",
   1194           __func__, p_chk_cb->nfcee_id);
   1195       evt_data.status = NFA_STATUS_REJECTED;
   1196     }
   1197   } else {
   1198     /* Find the total length so far in sys_code_cfg */
   1199     int total_sc_len = nfa_all_ee_find_total_sys_code_len();
   1200     /* make sure the control block has enough room to hold this entry */
   1201     if ((NFA_EE_SYSTEM_CODE_LEN + total_sc_len) >
   1202         NFA_EE_MAX_SYSTEM_CODE_CFG_LEN) {
   1203       LOG(ERROR) << StringPrintf(
   1204           "Exceeded capacity: (NFA_EE_SYSTEM_CODE_LEN:%d + total_sc_len:%d) > "
   1205           "NFA_EE_MAX_SYSTEM_CODE_CFG_LEN:%d",
   1206           NFA_EE_SYSTEM_CODE_LEN, total_sc_len, NFA_EE_MAX_SYSTEM_CODE_CFG_LEN);
   1207       evt_data.status = NFA_STATUS_BUFFER_FULL;
   1208     } else if (p_cb->sys_code_cfg_entries < NFA_EE_MAX_SYSTEM_CODE_ENTRIES) {
   1209       /* 6 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) + 2(system code)*/
   1210       uint16_t new_size =
   1211           nfa_ee_total_lmrt_size() + NFA_EE_SYSTEM_CODE_TLV_SIZE;
   1212       if (new_size > NFC_GetLmrtSize()) {
   1213         LOG(ERROR) << StringPrintf("Exceeded LMRT size:%d", new_size);
   1214         evt_data.status = NFA_STATUS_BUFFER_FULL;
   1215       } else {
   1216         /* add SC entry*/
   1217         uint32_t p_cb_sc_len = nfa_ee_find_total_sys_code_len(p_cb, 0);
   1218         p_cb->sys_code_pwr_cfg[p_cb->sys_code_cfg_entries] = p_add->power_state;
   1219         p_cb->sys_code_rt_loc[p_cb->sys_code_cfg_entries] = p_add->nfcee_id;
   1220         p_cb->sys_code_rt_loc_vs_info[p_cb->sys_code_cfg_entries] =
   1221             NFA_EE_AE_ROUTE;
   1222 
   1223         uint8_t* p = p_cb->sys_code_cfg + p_cb_sc_len;
   1224         memcpy(p, &p_add->syscode, NFA_EE_SYSTEM_CODE_LEN);
   1225         p += NFA_EE_SYSTEM_CODE_LEN;
   1226 
   1227         p_cb->sys_code_cfg_entries++;
   1228       }
   1229     } else {
   1230       LOG(ERROR) << StringPrintf("Exceeded NFA_EE_MAX_SYSTEM_CODE_ENTRIES:%d",
   1231                                  NFA_EE_MAX_SYSTEM_CODE_ENTRIES);
   1232       evt_data.status = NFA_STATUS_BUFFER_FULL;
   1233     }
   1234   }
   1235 
   1236   if (evt_data.status == NFA_STATUS_OK) {
   1237     /* mark SC changed */
   1238     p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_SYSCODE;
   1239     nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
   1240     nfa_ee_update_route_sys_code_size(p_cb);
   1241     nfa_ee_start_timer();
   1242   }
   1243   DLOG_IF(INFO, nfc_debug_enabled)
   1244       << StringPrintf("%s: status:%d ee_cfged:0x%02x ", __func__,
   1245                       evt_data.status, nfa_ee_cb.ee_cfged);
   1246 
   1247   /* report the status of this operation */
   1248   nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_ADD_SYSCODE_EVT, &evt_data);
   1249 }
   1250 
   1251 /*******************************************************************************
   1252 **
   1253 ** Function         nfa_ee_api_remove_sys_code
   1254 **
   1255 ** Description      process remove an System Code routing configuration from
   1256 **                  user start a 1 second timer. When the timer expires,
   1257 **                  the configuration collected in control block is sent to NFCC
   1258 **
   1259 ** Returns          void
   1260 **
   1261 *******************************************************************************/
   1262 void nfa_ee_api_remove_sys_code(tNFA_EE_MSG* p_data) {
   1263   tNFA_EE_CBACK_DATA evt_data = {0};
   1264   tNFA_EE_API_REMOVE_SYSCODE* p_remove = &p_data->rm_syscode;
   1265 
   1266   DLOG_IF(INFO, nfc_debug_enabled)
   1267       << StringPrintf("%s SC:0x%x", __func__, p_remove->syscode);
   1268 
   1269   int offset = 0, entry = 0;
   1270   tNFA_EE_ECB* p_cb =
   1271       nfa_ee_find_sys_code_offset(p_data->rm_syscode.syscode, &offset, &entry);
   1272 
   1273   if (p_cb && p_cb->sys_code_cfg_entries) {
   1274     DLOG_IF(INFO, nfc_debug_enabled)
   1275         << StringPrintf("sys_code_rt_loc_vs_info[%d]: 0x%02x", entry,
   1276                         p_cb->sys_code_rt_loc_vs_info[entry]);
   1277     /* mark routing and VS changed */
   1278     if (p_cb->sys_code_rt_loc_vs_info[entry] & NFA_EE_AE_ROUTE)
   1279       p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_SYSCODE;
   1280 
   1281     if (p_cb->sys_code_rt_loc_vs_info[entry] & NFA_EE_AE_VS)
   1282       p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_VS;
   1283 
   1284     /* remove the system code */
   1285     if ((entry + 1) < p_cb->sys_code_cfg_entries) {
   1286       /* not the last entry, move the SC entries in control block */
   1287       /* Find the total len from the next entry to the last one */
   1288       int total_len = nfa_ee_find_total_sys_code_len(p_cb, entry + 1);
   1289 
   1290       int rm_len = NFA_EE_SYSTEM_CODE_LEN;
   1291 
   1292       DLOG_IF(INFO, nfc_debug_enabled)
   1293           << StringPrintf("nfa_ee_api_remove_sys_code: rm_len:%d, total_len:%d",
   1294                           rm_len, total_len);
   1295 
   1296       GKI_shiftup(&p_cb->sys_code_cfg[offset],
   1297                   &p_cb->sys_code_cfg[offset + rm_len], total_len);
   1298 
   1299       total_len = p_cb->sys_code_cfg_entries - entry;
   1300 
   1301       GKI_shiftup(&p_cb->sys_code_pwr_cfg[entry],
   1302                   &p_cb->sys_code_pwr_cfg[entry + 1], total_len);
   1303 
   1304       GKI_shiftup(&p_cb->sys_code_rt_loc_vs_info[entry],
   1305                   &p_cb->sys_code_rt_loc_vs_info[entry + 1], total_len);
   1306 
   1307       GKI_shiftup(&p_cb->sys_code_rt_loc[entry],
   1308                   &p_cb->sys_code_rt_loc[entry + 1], total_len);
   1309     }
   1310     /* else the last entry, just reduce the aid_entries by 1 */
   1311     p_cb->sys_code_cfg_entries--;
   1312     nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
   1313     nfa_ee_update_route_sys_code_size(p_cb);
   1314     nfa_ee_start_timer();
   1315   } else {
   1316     LOG(ERROR) << StringPrintf(
   1317         "nfa_ee_api_remove_sys_code: The SC entry is not in the database");
   1318     evt_data.status = NFA_STATUS_INVALID_PARAM;
   1319   }
   1320   /* report the status of this operation */
   1321   nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_REMOVE_SYSCODE_EVT, &evt_data);
   1322 }
   1323 
   1324 /*******************************************************************************
   1325 **
   1326 ** Function         nfa_ee_api_lmrt_size
   1327 **
   1328 ** Description      Reports the remaining size in the Listen Mode Routing Table
   1329 **
   1330 ** Returns          void
   1331 **
   1332 *******************************************************************************/
   1333 void nfa_ee_api_lmrt_size(__attribute__((unused)) tNFA_EE_MSG* p_data) {
   1334   tNFA_EE_CBACK_DATA evt_data = {0};
   1335   uint16_t total_size = NFC_GetLmrtSize();
   1336 
   1337   evt_data.size = total_size - nfa_ee_total_lmrt_size();
   1338   DLOG_IF(INFO, nfc_debug_enabled)
   1339       << StringPrintf("nfa_ee_api_lmrt_size total size:%d remaining size:%d",
   1340                       total_size, evt_data.size);
   1341 
   1342   nfa_ee_report_event(NULL, NFA_EE_REMAINING_SIZE_EVT, &evt_data);
   1343 }
   1344 
   1345 /*******************************************************************************
   1346 **
   1347 ** Function         nfa_ee_api_update_now
   1348 **
   1349 ** Description      Initiates connection creation process to the given NFCEE
   1350 **
   1351 ** Returns          void
   1352 **
   1353 *******************************************************************************/
   1354 void nfa_ee_api_update_now(tNFA_EE_MSG* p_data) {
   1355   tNFA_EE_CBACK_DATA evt_data;
   1356 
   1357   if (nfa_ee_cb.ee_wait_evt & NFA_EE_WAIT_UPDATE_ALL) {
   1358     LOG(ERROR) << StringPrintf(
   1359         "nfa_ee_api_update_now still waiting for update complete "
   1360         "ee_wait_evt:0x%x wait_rsp:%d",
   1361         nfa_ee_cb.ee_wait_evt, nfa_ee_cb.wait_rsp);
   1362     evt_data.status = NFA_STATUS_SEMANTIC_ERROR;
   1363     nfa_ee_report_event(NULL, NFA_EE_UPDATED_EVT, &evt_data);
   1364     return;
   1365   }
   1366   nfa_sys_stop_timer(&nfa_ee_cb.timer);
   1367   nfa_ee_cb.ee_cfged |= NFA_EE_CFGED_UPDATE_NOW;
   1368   nfa_ee_rout_timeout(p_data);
   1369 }
   1370 
   1371 /*******************************************************************************
   1372 **
   1373 ** Function         nfa_ee_api_connect
   1374 **
   1375 ** Description      Initiates connection creation process to the given NFCEE
   1376 **
   1377 ** Returns          void
   1378 **
   1379 *******************************************************************************/
   1380 void nfa_ee_api_connect(tNFA_EE_MSG* p_data) {
   1381   tNFA_EE_ECB* p_cb = p_data->connect.p_cb;
   1382   int xx;
   1383   tNFA_EE_CBACK_DATA evt_data = {0};
   1384 
   1385   evt_data.connect.status = NFA_STATUS_FAILED;
   1386   if (p_cb->conn_st == NFA_EE_CONN_ST_NONE) {
   1387     for (xx = 0; xx < p_cb->num_interface; xx++) {
   1388       if (p_data->connect.ee_interface == p_cb->ee_interface[xx]) {
   1389         p_cb->p_ee_cback = p_data->connect.p_cback;
   1390         p_cb->conn_st = NFA_EE_CONN_ST_WAIT;
   1391         p_cb->use_interface = p_data->connect.ee_interface;
   1392         evt_data.connect.status =
   1393             NFC_ConnCreate(NCI_DEST_TYPE_NFCEE, p_data->connect.nfcee_id,
   1394                            p_data->connect.ee_interface, nfa_ee_conn_cback);
   1395         /* report the NFA_EE_CONNECT_EVT status on the response from NFCC */
   1396         break;
   1397       }
   1398     }
   1399   }
   1400 
   1401   if (evt_data.connect.status != NCI_STATUS_OK) {
   1402     evt_data.connect.ee_handle =
   1403         (tNFA_HANDLE)p_data->connect.nfcee_id | NFA_HANDLE_GROUP_EE;
   1404     evt_data.connect.status = NFA_STATUS_INVALID_PARAM;
   1405     evt_data.connect.ee_interface = p_data->connect.ee_interface;
   1406     nfa_ee_report_event(p_data->connect.p_cback, NFA_EE_CONNECT_EVT, &evt_data);
   1407   }
   1408 }
   1409 
   1410 /*******************************************************************************
   1411 **
   1412 ** Function         nfa_ee_api_send_data
   1413 **
   1414 ** Description      Send the given data packet to the given NFCEE
   1415 **
   1416 ** Returns          void
   1417 **
   1418 *******************************************************************************/
   1419 void nfa_ee_api_send_data(tNFA_EE_MSG* p_data) {
   1420   tNFA_EE_ECB* p_cb = p_data->send_data.p_cb;
   1421   NFC_HDR* p_pkt;
   1422   uint16_t size = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE +
   1423                   p_data->send_data.data_len + NFC_HDR_SIZE;
   1424   uint8_t* p;
   1425   tNFA_STATUS status = NFA_STATUS_FAILED;
   1426 
   1427   if (p_cb->conn_st == NFA_EE_CONN_ST_CONN) {
   1428     p_pkt = (NFC_HDR*)GKI_getbuf(size);
   1429     if (p_pkt) {
   1430       p_pkt->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
   1431       p_pkt->len = p_data->send_data.data_len;
   1432       p = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
   1433       memcpy(p, p_data->send_data.p_data, p_pkt->len);
   1434       NFC_SendData(p_cb->conn_id, p_pkt);
   1435     } else {
   1436       tNFA_EE_CBACK_DATA nfa_ee_cback_data;
   1437       nfa_ee_cback_data.status = status;
   1438       nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_NO_MEM_ERR_EVT,
   1439                           &nfa_ee_cback_data);
   1440     }
   1441   } else {
   1442     tNFA_EE_CBACK_DATA nfa_ee_cback_data;
   1443     nfa_ee_cback_data.status = status;
   1444     nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_NO_CB_ERR_EVT,
   1445                         &nfa_ee_cback_data);
   1446   }
   1447 }
   1448 
   1449 /*******************************************************************************
   1450 **
   1451 ** Function         nfa_ee_api_disconnect
   1452 **
   1453 ** Description      Initiates closing of the connection to the given NFCEE
   1454 **
   1455 ** Returns          void
   1456 **
   1457 *******************************************************************************/
   1458 void nfa_ee_api_disconnect(tNFA_EE_MSG* p_data) {
   1459   tNFA_EE_ECB* p_cb = p_data->disconnect.p_cb;
   1460   tNFA_EE_CBACK_DATA evt_data = {0};
   1461 
   1462   if (p_cb->conn_st == NFA_EE_CONN_ST_CONN) {
   1463     p_cb->conn_st = NFA_EE_CONN_ST_DISC;
   1464     NFC_ConnClose(p_cb->conn_id);
   1465   }
   1466   evt_data.handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
   1467   nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_DISCONNECT_EVT, &evt_data);
   1468 }
   1469 
   1470 /*******************************************************************************
   1471 **
   1472 ** Function         nfa_ee_report_disc_done
   1473 **
   1474 ** Description      Process the callback for NFCEE discovery response
   1475 **
   1476 ** Returns          void
   1477 **
   1478 *******************************************************************************/
   1479 void nfa_ee_report_disc_done(bool notify_enable_done) {
   1480   tNFA_EE_CBACK* p_cback;
   1481   tNFA_EE_CBACK_DATA evt_data = {0};
   1482 
   1483   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1484       "em_state:%d num_ee_expecting:%d "
   1485       "notify_enable_done:%d",
   1486       nfa_ee_cb.em_state, nfa_ee_cb.num_ee_expecting, notify_enable_done);
   1487   if (nfa_ee_cb.num_ee_expecting == 0) {
   1488     if (notify_enable_done) {
   1489       if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_INIT_DONE) {
   1490         nfa_sys_cback_notify_enable_complete(NFA_ID_EE);
   1491         if (nfa_ee_cb.p_enable_cback)
   1492           (*nfa_ee_cb.p_enable_cback)(NFA_EE_DISC_STS_ON);
   1493       } else if ((nfa_ee_cb.em_state == NFA_EE_EM_STATE_RESTORING) &&
   1494                  (nfa_ee_cb.ee_flags & NFA_EE_FLAG_NOTIFY_HCI)) {
   1495         nfa_ee_cb.ee_flags &= ~NFA_EE_FLAG_NOTIFY_HCI;
   1496         if (nfa_ee_cb.p_enable_cback)
   1497           (*nfa_ee_cb.p_enable_cback)(NFA_EE_DISC_STS_ON);
   1498       }
   1499     }
   1500 
   1501     if (nfa_ee_cb.p_ee_disc_cback) {
   1502       /* notify API callback */
   1503       p_cback = nfa_ee_cb.p_ee_disc_cback;
   1504       nfa_ee_cb.p_ee_disc_cback = NULL;
   1505       evt_data.status = NFA_STATUS_OK;
   1506       evt_data.ee_discover.num_ee = NFA_EE_MAX_EE_SUPPORTED;
   1507       NFA_EeGetInfo(&evt_data.ee_discover.num_ee, evt_data.ee_discover.ee_info);
   1508       nfa_ee_report_event(p_cback, NFA_EE_DISCOVER_EVT, &evt_data);
   1509     }
   1510     if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_EE_RECOVERY) &&
   1511         nfa_ee_cb.p_enable_cback)
   1512       (*nfa_ee_cb.p_enable_cback)(NFA_EE_RECOVERY_REDISCOVERED);
   1513   }
   1514 }
   1515 
   1516 /*******************************************************************************
   1517 **
   1518 ** Function         nfa_ee_restore_ntf_done
   1519 **
   1520 ** Description      check if any ee_status still has NFA_EE_STATUS_PENDING bit
   1521 **
   1522 ** Returns          TRUE, if all NFA_EE_STATUS_PENDING bits are removed
   1523 **
   1524 *******************************************************************************/
   1525 bool nfa_ee_restore_ntf_done(void) {
   1526   tNFA_EE_ECB* p_cb;
   1527   bool is_done = true;
   1528   int xx;
   1529 
   1530   p_cb = nfa_ee_cb.ecb;
   1531   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++) {
   1532     if ((p_cb->nfcee_id != NFA_EE_INVALID) &&
   1533         (p_cb->ee_old_status & NFA_EE_STATUS_RESTORING)) {
   1534       is_done = false;
   1535       break;
   1536     }
   1537   }
   1538   return is_done;
   1539 }
   1540 
   1541 /*******************************************************************************
   1542 **
   1543 ** Function         nfa_ee_remove_pending
   1544 **
   1545 ** Description      check if any ee_status still has NFA_EE_STATUS_RESTORING bit
   1546 **
   1547 ** Returns          TRUE, if all NFA_EE_STATUS_RESTORING bits are removed
   1548 **
   1549 *******************************************************************************/
   1550 static void nfa_ee_remove_pending(void) {
   1551   tNFA_EE_ECB* p_cb;
   1552   tNFA_EE_ECB *p_cb_n, *p_cb_end;
   1553   int xx, num_removed = 0;
   1554   int first_removed = NFA_EE_MAX_EE_SUPPORTED;
   1555 
   1556   p_cb = nfa_ee_cb.ecb;
   1557   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++) {
   1558     if ((p_cb->nfcee_id != NFA_EE_INVALID) &&
   1559         (p_cb->ee_status & NFA_EE_STATUS_RESTORING)) {
   1560       p_cb->nfcee_id = NFA_EE_INVALID;
   1561       num_removed++;
   1562       if (first_removed == NFA_EE_MAX_EE_SUPPORTED) first_removed = xx;
   1563     }
   1564   }
   1565 
   1566   DLOG_IF(INFO, nfc_debug_enabled)
   1567       << StringPrintf("cur_ee:%d, num_removed:%d first_removed:%d",
   1568                       nfa_ee_cb.cur_ee, num_removed, first_removed);
   1569   if (num_removed && (first_removed != (nfa_ee_cb.cur_ee - num_removed))) {
   1570     /* if the removes ECB entried are not at the end, move the entries up */
   1571     p_cb_end = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
   1572     p_cb = &nfa_ee_cb.ecb[first_removed];
   1573     for (p_cb_n = p_cb + 1; p_cb_n <= p_cb_end;) {
   1574       while ((p_cb_n->nfcee_id == NFA_EE_INVALID) && (p_cb_n <= p_cb_end)) {
   1575         p_cb_n++;
   1576       }
   1577 
   1578       if (p_cb_n <= p_cb_end) {
   1579         memcpy(p_cb, p_cb_n, sizeof(tNFA_EE_ECB));
   1580         p_cb_n->nfcee_id = NFA_EE_INVALID;
   1581       }
   1582       p_cb++;
   1583       p_cb_n++;
   1584     }
   1585   }
   1586   nfa_ee_cb.cur_ee -= (uint8_t)num_removed;
   1587 }
   1588 
   1589 /*******************************************************************************
   1590 **
   1591 ** Function         nfa_ee_nci_disc_rsp
   1592 **
   1593 ** Description      Process the callback for NFCEE discovery response
   1594 **
   1595 ** Returns          void
   1596 **
   1597 *******************************************************************************/
   1598 void nfa_ee_nci_disc_rsp(tNFA_EE_MSG* p_data) {
   1599   tNFC_NFCEE_DISCOVER_REVT* p_evt = p_data->disc_rsp.p_data;
   1600   tNFA_EE_ECB* p_cb;
   1601   uint8_t xx;
   1602   uint8_t num_nfcee = p_evt->num_nfcee;
   1603   bool notify_enable_done = false;
   1604 
   1605   DLOG_IF(INFO, nfc_debug_enabled)
   1606       << StringPrintf("em_state:%d cur_ee:%d, num_nfcee:%d", nfa_ee_cb.em_state,
   1607                       nfa_ee_cb.cur_ee, num_nfcee);
   1608   switch (nfa_ee_cb.em_state) {
   1609     case NFA_EE_EM_STATE_INIT:
   1610       nfa_ee_cb.cur_ee = 0;
   1611       nfa_ee_cb.num_ee_expecting = 0;
   1612       if (num_nfcee == 0) {
   1613         nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1614         notify_enable_done = true;
   1615         if (p_evt->status != NFC_STATUS_OK) {
   1616           nfa_sys_stop_timer(&nfa_ee_cb.discv_timer);
   1617         }
   1618       }
   1619       break;
   1620 
   1621     case NFA_EE_EM_STATE_INIT_DONE:
   1622       if (num_nfcee) {
   1623         /* if this is initiated by api function,
   1624          * check if the number of NFCEE expected is more than what's currently
   1625          * in CB */
   1626         if (num_nfcee > NFA_EE_MAX_EE_SUPPORTED)
   1627           num_nfcee = NFA_EE_MAX_EE_SUPPORTED;
   1628         if (nfa_ee_cb.cur_ee < num_nfcee) {
   1629           p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee];
   1630           for (xx = nfa_ee_cb.cur_ee; xx < num_nfcee; xx++, p_cb++) {
   1631             /* mark the new entries as a new one */
   1632             p_cb->nfcee_id = NFA_EE_INVALID;
   1633           }
   1634         }
   1635         nfa_ee_cb.cur_ee = num_nfcee;
   1636       }
   1637       break;
   1638 
   1639     case NFA_EE_EM_STATE_RESTORING:
   1640       if (num_nfcee == 0) {
   1641         nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1642         nfa_ee_remove_pending();
   1643         nfa_ee_check_restore_complete();
   1644         if (p_evt->status != NFC_STATUS_OK) {
   1645           nfa_sys_stop_timer(&nfa_ee_cb.discv_timer);
   1646         }
   1647       }
   1648       break;
   1649   }
   1650 
   1651   if (p_evt->status == NFC_STATUS_OK) {
   1652     nfa_ee_cb.num_ee_expecting = p_evt->num_nfcee;
   1653     if (nfa_ee_cb.num_ee_expecting > NFA_EE_MAX_EE_SUPPORTED) {
   1654       LOG(ERROR) << StringPrintf("NFA-EE num_ee_expecting:%d > max:%d",
   1655                                  nfa_ee_cb.num_ee_expecting,
   1656                                  NFA_EE_MAX_EE_SUPPORTED);
   1657     }
   1658   }
   1659   nfa_ee_report_disc_done(notify_enable_done);
   1660   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1661       "em_state:%d cur_ee:%d num_ee_expecting:%d", nfa_ee_cb.em_state,
   1662       nfa_ee_cb.cur_ee, nfa_ee_cb.num_ee_expecting);
   1663 }
   1664 
   1665 /*******************************************************************************
   1666 **
   1667 ** Function         nfa_ee_nci_disc_ntf
   1668 **
   1669 ** Description      Process the callback for NFCEE discovery notification
   1670 **
   1671 ** Returns          void
   1672 **
   1673 *******************************************************************************/
   1674 void nfa_ee_nci_disc_ntf(tNFA_EE_MSG* p_data) {
   1675   tNFC_NFCEE_INFO_REVT* p_ee = p_data->disc_ntf.p_data;
   1676   tNFA_EE_ECB* p_cb = NULL;
   1677   bool notify_enable_done = false;
   1678   bool notify_new_ee = false;
   1679   tNFA_EE_CBACK_DATA evt_data = {0};
   1680   tNFA_EE_INFO* p_info;
   1681   tNFA_EE_EM_STATE new_em_state = NFA_EE_EM_STATE_MAX;
   1682 
   1683   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1684       "em_state:%d ee_flags:0x%x cur_ee:%d "
   1685       "num_ee_expecting:%d",
   1686       nfa_ee_cb.em_state, nfa_ee_cb.ee_flags, nfa_ee_cb.cur_ee,
   1687       nfa_ee_cb.num_ee_expecting);
   1688   if (nfa_ee_cb.num_ee_expecting) {
   1689     nfa_ee_cb.num_ee_expecting--;
   1690     if ((nfa_ee_cb.num_ee_expecting == 0) &&
   1691         (nfa_ee_cb.p_ee_disc_cback != NULL)) {
   1692       /* Discovery triggered by API function */
   1693       if (NFA_GetNCIVersion() != NCI_VERSION_2_0) NFC_NfceeDiscover(false);
   1694     }
   1695   }
   1696   switch (nfa_ee_cb.em_state) {
   1697     case NFA_EE_EM_STATE_INIT:
   1698       if (nfa_ee_cb.cur_ee < NFA_EE_MAX_EE_SUPPORTED) {
   1699         /* the cb can collect up to NFA_EE_MAX_EE_SUPPORTED ee_info */
   1700         p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee++];
   1701       }
   1702 
   1703       if (nfa_ee_cb.num_ee_expecting == 0) {
   1704         /* notify init_done callback */
   1705         nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1706         notify_enable_done = true;
   1707       }
   1708       break;
   1709 
   1710     case NFA_EE_EM_STATE_INIT_DONE:
   1711       p_cb = nfa_ee_find_ecb(p_ee->nfcee_id);
   1712       if (p_cb == NULL) {
   1713         /* the NFCEE ID is not in the last NFCEE discovery
   1714          * maybe it's a new one */
   1715         p_cb = nfa_ee_find_ecb(NFA_EE_INVALID);
   1716         if (p_cb) {
   1717           nfa_ee_cb.cur_ee++;
   1718           notify_new_ee = true;
   1719         }
   1720       } else if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ORDER) {
   1721         nfa_ee_cb.cur_ee++;
   1722         notify_new_ee = true;
   1723       } else {
   1724         DLOG_IF(INFO, nfc_debug_enabled)
   1725             << StringPrintf("cur_ee:%d ecb_flags=0x%02x  ee_status=0x%x",
   1726                             nfa_ee_cb.cur_ee, p_cb->ecb_flags, p_cb->ee_status);
   1727       }
   1728       break;
   1729 
   1730     case NFA_EE_EM_STATE_RESTORING:
   1731       p_cb = nfa_ee_find_ecb(p_ee->nfcee_id);
   1732       if (p_cb == NULL) {
   1733         /* the NFCEE ID is not in the last NFCEE discovery
   1734          * maybe it's a new one */
   1735         p_cb = nfa_ee_find_ecb(NFA_EE_INVALID);
   1736         if (p_cb) {
   1737           nfa_ee_cb.cur_ee++;
   1738           notify_new_ee = true;
   1739         }
   1740       }
   1741       if (nfa_ee_cb.num_ee_expecting == 0) {
   1742         /* notify init_done callback */
   1743         notify_enable_done = true;
   1744         if (nfa_ee_restore_ntf_done()) {
   1745           new_em_state = NFA_EE_EM_STATE_INIT_DONE;
   1746         }
   1747       }
   1748       break;
   1749   }
   1750   DLOG_IF(INFO, nfc_debug_enabled)
   1751       << StringPrintf("nfa_ee_nci_disc_ntf cur_ee:%d", nfa_ee_cb.cur_ee);
   1752 
   1753   if (p_cb) {
   1754     p_cb->nfcee_id = p_ee->nfcee_id;
   1755     p_cb->ee_status = p_ee->ee_status;
   1756     p_cb->num_interface = p_ee->num_interface;
   1757     memcpy(p_cb->ee_interface, p_ee->ee_interface, p_ee->num_interface);
   1758     p_cb->num_tlvs = p_ee->num_tlvs;
   1759     memcpy(p_cb->ee_tlv, p_ee->ee_tlv, p_ee->num_tlvs * sizeof(tNFA_EE_TLV));
   1760     if (NFA_GetNCIVersion() == NCI_VERSION_2_0)
   1761       p_cb->ee_power_supply_status = p_ee->nfcee_power_ctrl;
   1762     if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_RESTORING) {
   1763       /* NCI spec says: An NFCEE_DISCOVER_NTF that contains a Protocol type of
   1764        * "HCI Access"
   1765        * SHALL NOT contain any other additional Protocol
   1766        * i.e. check only first supported NFCEE interface is HCI access */
   1767       /* NFA_HCI module handles restoring configurations for HCI access */
   1768       if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS) {
   1769         if ((nfa_ee_cb.ee_flags & NFA_EE_FLAG_WAIT_HCI) == 0) {
   1770           nfa_ee_restore_one_ecb(p_cb);
   1771         }
   1772         /* else wait for NFA-HCI module to restore the HCI network information
   1773          * before enabling the NFCEE */
   1774       }
   1775     }
   1776 
   1777     if ((nfa_ee_cb.p_ee_disc_cback == NULL) && (notify_new_ee == true)) {
   1778       if (nfa_dm_is_active() && (p_cb->ee_status != NFA_EE_STATUS_REMOVED)) {
   1779         /* report this NFA_EE_NEW_EE_EVT only after NFA_DM_ENABLE_EVT is
   1780          * reported */
   1781         p_info = &evt_data.new_ee;
   1782         p_info->ee_handle = NFA_HANDLE_GROUP_EE | (tNFA_HANDLE)p_cb->nfcee_id;
   1783         p_info->ee_status = p_cb->ee_status;
   1784         p_info->num_interface = p_cb->num_interface;
   1785         p_info->num_tlvs = p_cb->num_tlvs;
   1786         memcpy(p_info->ee_interface, p_cb->ee_interface, p_cb->num_interface);
   1787         memcpy(p_info->ee_tlv, p_cb->ee_tlv,
   1788                p_cb->num_tlvs * sizeof(tNFA_EE_TLV));
   1789         if (NFA_GetNCIVersion() == NCI_VERSION_2_0)
   1790           p_info->ee_power_supply_status = p_cb->ee_power_supply_status;
   1791         nfa_ee_report_event(NULL, NFA_EE_NEW_EE_EVT, &evt_data);
   1792       }
   1793     } else
   1794       nfa_ee_report_disc_done(notify_enable_done);
   1795 
   1796     if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ORDER) {
   1797       DLOG_IF(INFO, nfc_debug_enabled)
   1798           << StringPrintf("NFA_EE_ECB_FLAGS_ORDER");
   1799       p_cb->ecb_flags &= ~NFA_EE_ECB_FLAGS_ORDER;
   1800       nfa_ee_report_discover_req_evt();
   1801     }
   1802   }
   1803 
   1804   if (new_em_state != NFA_EE_EM_STATE_MAX) {
   1805     nfa_ee_cb.em_state = new_em_state;
   1806     nfa_ee_check_restore_complete();
   1807   }
   1808 
   1809   if ((nfa_ee_cb.cur_ee == nfa_ee_max_ee_cfg) &&
   1810       (nfa_ee_cb.em_state == NFA_EE_EM_STATE_INIT_DONE)) {
   1811     if (nfa_ee_cb.discv_timer.in_use) {
   1812       nfa_sys_stop_timer(&nfa_ee_cb.discv_timer);
   1813       p_data->hdr.event = NFA_EE_DISCV_TIMEOUT_EVT;
   1814       nfa_ee_evt_hdlr(&p_data->hdr);
   1815     }
   1816   }
   1817 }
   1818 
   1819 /*******************************************************************************
   1820 **
   1821 ** Function         nfa_ee_nci_nfcee_status_ntf
   1822 **
   1823 ** Description      Process the callback for NFCEE status notification
   1824 **
   1825 ** Returns          void
   1826 **
   1827 *******************************************************************************/
   1828 void nfa_ee_nci_nfcee_status_ntf(tNFA_EE_MSG* p_data) {
   1829   if (p_data != NULL) {
   1830     tNFC_NFCEE_STATUS_REVT* p_ee_data = p_data->nfcee_status_ntf.p_data;
   1831     if ((NFA_GetNCIVersion() == NCI_VERSION_2_0) &&
   1832         (p_ee_data->nfcee_status == NFC_NFCEE_STATUS_UNRECOVERABLE_ERROR)) {
   1833       tNFA_EE_ECB* p_cb = nfa_ee_find_ecb(p_ee_data->nfcee_id);
   1834       if (p_cb && nfa_ee_cb.p_enable_cback) {
   1835         (*nfa_ee_cb.p_enable_cback)(NFA_EE_RECOVERY_INIT);
   1836         NFC_NfceeDiscover(true);
   1837       }
   1838     }
   1839   }
   1840 }
   1841 
   1842 /*******************************************************************************
   1843 **
   1844 ** Function         nfa_ee_check_restore_complete
   1845 **
   1846 ** Description      Check if restore the NFA-EE related configuration to the
   1847 **                  state prior to low power mode is complete.
   1848 **                  If complete, notify sys.
   1849 **
   1850 ** Returns          void
   1851 **
   1852 *******************************************************************************/
   1853 void nfa_ee_check_restore_complete(void) {
   1854   uint32_t xx;
   1855   tNFA_EE_ECB* p_cb;
   1856   bool proc_complete = true;
   1857 
   1858   p_cb = nfa_ee_cb.ecb;
   1859   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++) {
   1860     if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_RESTORE) {
   1861       /* NFA_HCI module handles restoring configurations for HCI access.
   1862        * ignore the restoring status for HCI Access */
   1863       if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS) {
   1864         proc_complete = false;
   1865         break;
   1866       }
   1867     }
   1868   }
   1869 
   1870   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1871       "nfa_ee_check_restore_complete nfa_ee_cb.ee_cfg_sts:0x%02x "
   1872       "proc_complete:%d",
   1873       nfa_ee_cb.ee_cfg_sts, proc_complete);
   1874   if (proc_complete) {
   1875     /* update routing table when NFA_EE_ROUT_TIMEOUT_EVT is received */
   1876     if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_PREV_ROUTING)
   1877       nfa_ee_api_update_now(NULL);
   1878 
   1879     nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1880     nfa_sys_cback_notify_nfcc_power_mode_proc_complete(NFA_ID_EE);
   1881   }
   1882 }
   1883 
   1884 /*******************************************************************************
   1885 **
   1886 ** Function         nfa_ee_build_discover_req_evt
   1887 **
   1888 ** Description      Build NFA_EE_DISCOVER_REQ_EVT for all active NFCEE
   1889 **
   1890 ** Returns          void
   1891 **
   1892 *******************************************************************************/
   1893 static void nfa_ee_build_discover_req_evt(tNFA_EE_DISCOVER_REQ* p_evt_data) {
   1894   tNFA_EE_ECB* p_cb;
   1895   tNFA_EE_DISCOVER_INFO* p_info;
   1896   uint8_t xx;
   1897 
   1898   if (!p_evt_data) return;
   1899 
   1900   p_evt_data->num_ee = 0;
   1901   p_cb = nfa_ee_cb.ecb;
   1902   p_info = p_evt_data->ee_disc_info;
   1903 
   1904   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++) {
   1905     if ((p_cb->ee_status & NFA_EE_STATUS_INT_MASK) ||
   1906         (p_cb->ee_status != NFA_EE_STATUS_ACTIVE) ||
   1907         ((p_cb->ecb_flags & NFA_EE_ECB_FLAGS_DISC_REQ) == 0)) {
   1908       continue;
   1909     }
   1910     p_info->ee_handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
   1911     p_info->la_protocol = p_cb->la_protocol;
   1912     p_info->lb_protocol = p_cb->lb_protocol;
   1913     p_info->lf_protocol = p_cb->lf_protocol;
   1914     p_info->lbp_protocol = p_cb->lbp_protocol;
   1915     p_evt_data->num_ee++;
   1916     p_info++;
   1917 
   1918     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1919         "[%d] ee_handle:0x%x, listen protocol A:%d, B:%d, F:%d, BP:%d",
   1920         p_evt_data->num_ee, p_cb->nfcee_id, p_cb->la_protocol,
   1921         p_cb->lb_protocol, p_cb->lf_protocol, p_cb->lbp_protocol);
   1922   }
   1923 
   1924   p_evt_data->status = NFA_STATUS_OK;
   1925 }
   1926 
   1927 /*******************************************************************************
   1928 **
   1929 ** Function         nfa_ee_report_discover_req_evt
   1930 **
   1931 ** Description      Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE
   1932 **
   1933 ** Returns          void
   1934 **
   1935 *******************************************************************************/
   1936 static void nfa_ee_report_discover_req_evt(void) {
   1937   if (nfa_ee_cb.p_enable_cback)
   1938     (*nfa_ee_cb.p_enable_cback)(NFA_EE_DISC_STS_REQ);
   1939 
   1940   /* if this is restoring NFCC */
   1941   if (!nfa_dm_is_active()) {
   1942     DLOG_IF(INFO, nfc_debug_enabled)
   1943         << StringPrintf("nfa_ee_report_discover_req_evt DM is not active");
   1944     return;
   1945   }
   1946 
   1947   tNFA_EE_CBACK_DATA nfa_ee_cback_data;
   1948   nfa_ee_build_discover_req_evt(&nfa_ee_cback_data.discover_req);
   1949   nfa_ee_report_event(NULL, NFA_EE_DISCOVER_REQ_EVT, &nfa_ee_cback_data);
   1950 }
   1951 
   1952 /*******************************************************************************
   1953 **
   1954 ** Function         nfa_ee_nci_mode_set_rsp
   1955 **
   1956 ** Description      Process the result for NFCEE ModeSet response
   1957 **
   1958 ** Returns          void
   1959 **
   1960 *******************************************************************************/
   1961 void nfa_ee_nci_mode_set_rsp(tNFA_EE_MSG* p_data) {
   1962   tNFA_EE_ECB* p_cb;
   1963   tNFA_EE_MODE_SET mode_set;
   1964   tNFC_NFCEE_MODE_SET_REVT* p_rsp = p_data->mode_set_rsp.p_data;
   1965 
   1966   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   1967       "%s handle:0x%02x mode:%d", __func__, p_rsp->nfcee_id, p_rsp->mode);
   1968   p_cb = nfa_ee_find_ecb(p_rsp->nfcee_id);
   1969   if (p_cb == NULL) {
   1970     LOG(ERROR) << StringPrintf("%s Can not find cb for handle:0x%02x", __func__,
   1971                                p_rsp->nfcee_id);
   1972     return;
   1973   }
   1974 
   1975   /* Do not update routing table in EE_RECOVERY state */
   1976   if (nfa_hci_cb.hci_state != NFA_HCI_STATE_EE_RECOVERY) {
   1977     /* Start routing table update debounce timer */
   1978     nfa_ee_start_timer();
   1979   }
   1980   LOG(ERROR) << StringPrintf("%s p_rsp->status:0x%02x", __func__,
   1981                              p_rsp->status);
   1982   if (p_rsp->status == NFA_STATUS_OK) {
   1983     if (p_rsp->mode == NFA_EE_MD_ACTIVATE) {
   1984       p_cb->ee_status = NFC_NFCEE_STATUS_ACTIVE;
   1985     } else {
   1986       if (p_cb->tech_switch_on | p_cb->tech_switch_off |
   1987           p_cb->tech_battery_off | p_cb->proto_switch_on |
   1988           p_cb->proto_switch_off | p_cb->proto_battery_off |
   1989           p_cb->aid_entries) {
   1990         /* this NFCEE still has configuration when deactivated. clear the
   1991          * configuration */
   1992         nfa_ee_cb.ee_cfged &= ~nfa_ee_ecb_to_mask(p_cb);
   1993         nfa_ee_cb.ee_cfg_sts |= NFA_EE_STS_CHANGED_ROUTING;
   1994         DLOG_IF(INFO, nfc_debug_enabled)
   1995             << StringPrintf("deactivating/still configured. Force update");
   1996       }
   1997       p_cb->tech_switch_on = p_cb->tech_switch_off = p_cb->tech_battery_off = 0;
   1998       p_cb->proto_switch_on = p_cb->proto_switch_off = p_cb->proto_battery_off =
   1999           0;
   2000       p_cb->aid_entries = 0;
   2001       p_cb->ee_status = NFC_NFCEE_STATUS_INACTIVE;
   2002     }
   2003   } else if (p_rsp->mode == NFA_EE_MD_ACTIVATE) {
   2004     p_cb->ee_status = NFC_NFCEE_STATUS_REMOVED;
   2005   }
   2006   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2007       "status:%d ecb_flags  :0x%02x ee_cfged:0x%02x ee_status:%d",
   2008       p_rsp->status, p_cb->ecb_flags, nfa_ee_cb.ee_cfged, p_cb->ee_status);
   2009   if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_RESTORE) {
   2010     if (p_cb->conn_st == NFA_EE_CONN_ST_CONN) {
   2011       /* NFA_HCI module handles restoring configurations for HCI access */
   2012       if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS) {
   2013         NFC_ConnCreate(NCI_DEST_TYPE_NFCEE, p_cb->nfcee_id, p_cb->use_interface,
   2014                        nfa_ee_conn_cback);
   2015       }
   2016     } else {
   2017       p_cb->ecb_flags &= ~NFA_EE_ECB_FLAGS_RESTORE;
   2018       nfa_ee_check_restore_complete();
   2019     }
   2020   } else {
   2021     mode_set.status = p_rsp->status;
   2022     mode_set.ee_handle = (tNFA_HANDLE)p_rsp->nfcee_id | NFA_HANDLE_GROUP_EE;
   2023     mode_set.ee_status = p_cb->ee_status;
   2024 
   2025     tNFA_EE_CBACK_DATA nfa_ee_cback_data;
   2026     nfa_ee_cback_data.mode_set = mode_set;
   2027     nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_MODE_SET_EVT,
   2028                         &nfa_ee_cback_data);
   2029 
   2030     if ((p_cb->ee_status == NFC_NFCEE_STATUS_INACTIVE) ||
   2031         (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE)) {
   2032       /* Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE */
   2033       nfa_ee_report_discover_req_evt();
   2034     }
   2035   }
   2036   if (nfa_ee_cb.p_enable_cback)
   2037     (*nfa_ee_cb.p_enable_cback)(NFA_EE_MODE_SET_COMPLETE);
   2038 }
   2039 
   2040 /*******************************************************************************
   2041 **
   2042 ** Function         nfa_ee_report_update_evt
   2043 **
   2044 ** Description      Check if need to report NFA_EE_UPDATED_EVT
   2045 **
   2046 ** Returns          void
   2047 **
   2048 *******************************************************************************/
   2049 void nfa_ee_report_update_evt(void) {
   2050   tNFA_EE_CBACK_DATA evt_data;
   2051 
   2052   DLOG_IF(INFO, nfc_debug_enabled)
   2053       << StringPrintf("nfa_ee_report_update_evt ee_wait_evt:0x%x wait_rsp:%d",
   2054                       nfa_ee_cb.ee_wait_evt, nfa_ee_cb.wait_rsp);
   2055   if (nfa_ee_cb.wait_rsp == 0) {
   2056     nfa_ee_cb.ee_wait_evt &= ~NFA_EE_WAIT_UPDATE_RSP;
   2057 
   2058     if (nfa_ee_cb.ee_wait_evt & NFA_EE_WAIT_UPDATE) {
   2059       nfa_ee_cb.ee_wait_evt &= ~NFA_EE_WAIT_UPDATE;
   2060       /* finished updating NFCC; report NFA_EE_UPDATED_EVT now */
   2061       evt_data.status = NFA_STATUS_OK;
   2062       nfa_ee_report_event(NULL, NFA_EE_UPDATED_EVT, &evt_data);
   2063     }
   2064   }
   2065 }
   2066 
   2067 /*******************************************************************************
   2068 **
   2069 ** Function         nfa_ee_nci_wait_rsp
   2070 **
   2071 ** Description      Process the result for NCI response
   2072 **
   2073 ** Returns          void
   2074 **
   2075 *******************************************************************************/
   2076 void nfa_ee_nci_wait_rsp(tNFA_EE_MSG* p_data) {
   2077   tNFA_EE_NCI_WAIT_RSP* p_rsp = &p_data->wait_rsp;
   2078 
   2079   DLOG_IF(INFO, nfc_debug_enabled)
   2080       << StringPrintf("ee_wait_evt:0x%x wait_rsp:%d", nfa_ee_cb.ee_wait_evt,
   2081                       nfa_ee_cb.wait_rsp);
   2082   if (nfa_ee_cb.wait_rsp) {
   2083     if (p_rsp->opcode == NCI_MSG_RF_SET_ROUTING) nfa_ee_cb.wait_rsp--;
   2084   }
   2085   nfa_ee_report_update_evt();
   2086 }
   2087 
   2088 /*******************************************************************************
   2089 **
   2090 ** Function         nfa_ee_nci_conn
   2091 **
   2092 ** Description      process the connection callback events
   2093 **
   2094 ** Returns          void
   2095 **
   2096 *******************************************************************************/
   2097 void nfa_ee_nci_conn(tNFA_EE_MSG* p_data) {
   2098   tNFA_EE_ECB* p_cb;
   2099   tNFA_EE_NCI_CONN* p_cbk = &p_data->conn;
   2100   tNFC_CONN* p_conn = p_data->conn.p_data;
   2101   NFC_HDR* p_pkt = NULL;
   2102   tNFA_EE_CBACK_DATA evt_data = {0};
   2103   tNFA_EE_EVT event = NFA_EE_INVALID;
   2104   tNFA_EE_CBACK* p_cback = NULL;
   2105 
   2106   if (p_cbk->event == NFC_CONN_CREATE_CEVT) {
   2107     p_cb = nfa_ee_find_ecb(p_cbk->p_data->conn_create.id);
   2108   } else {
   2109     p_cb = nfa_ee_find_ecb_by_conn_id(p_cbk->conn_id);
   2110     if (p_cbk->event == NFC_DATA_CEVT) p_pkt = p_conn->data.p_data;
   2111   }
   2112 
   2113   if (p_cb) {
   2114     p_cback = p_cb->p_ee_cback;
   2115     evt_data.handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
   2116     switch (p_cbk->event) {
   2117       case NFC_CONN_CREATE_CEVT:
   2118         if (p_conn->conn_create.status == NFC_STATUS_OK) {
   2119           p_cb->conn_id = p_cbk->conn_id;
   2120           p_cb->conn_st = NFA_EE_CONN_ST_CONN;
   2121         } else {
   2122           p_cb->conn_st = NFA_EE_CONN_ST_NONE;
   2123         }
   2124         if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_RESTORE) {
   2125           p_cb->ecb_flags &= ~NFA_EE_ECB_FLAGS_RESTORE;
   2126           nfa_ee_check_restore_complete();
   2127         } else {
   2128           evt_data.connect.status = p_conn->conn_create.status;
   2129           evt_data.connect.ee_interface = p_cb->use_interface;
   2130           event = NFA_EE_CONNECT_EVT;
   2131         }
   2132         break;
   2133 
   2134       case NFC_CONN_CLOSE_CEVT:
   2135         if (p_cb->conn_st != NFA_EE_CONN_ST_DISC) event = NFA_EE_DISCONNECT_EVT;
   2136         p_cb->conn_st = NFA_EE_CONN_ST_NONE;
   2137         p_cb->p_ee_cback = NULL;
   2138         p_cb->conn_id = 0;
   2139         if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_DISABLING) {
   2140           if (nfa_ee_cb.ee_flags & NFA_EE_FLAG_WAIT_DISCONN) {
   2141             if (nfa_ee_cb.num_ee_expecting) {
   2142               nfa_ee_cb.num_ee_expecting--;
   2143             }
   2144           }
   2145           if (nfa_ee_cb.num_ee_expecting == 0) {
   2146             nfa_ee_cb.ee_flags &= ~NFA_EE_FLAG_WAIT_DISCONN;
   2147             nfa_ee_check_disable();
   2148           }
   2149         }
   2150         break;
   2151 
   2152       case NFC_DATA_CEVT:
   2153         if (p_cb->conn_st == NFA_EE_CONN_ST_CONN) {
   2154           /* report data event only in connected state */
   2155           if (p_cb->p_ee_cback && p_pkt) {
   2156             evt_data.data.len = p_pkt->len;
   2157             evt_data.data.p_buf = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
   2158             event = NFA_EE_DATA_EVT;
   2159             p_pkt = NULL; /* so this function does not free this GKI buffer */
   2160           }
   2161         }
   2162         break;
   2163     }
   2164 
   2165     if ((event != NFA_EE_INVALID) && (p_cback)) (*p_cback)(event, &evt_data);
   2166   }
   2167   if (p_pkt) GKI_freebuf(p_pkt);
   2168 }
   2169 
   2170 /*******************************************************************************
   2171 **
   2172 ** Function         nfa_ee_nci_action_ntf
   2173 **
   2174 ** Description      process the NFCEE action callback event
   2175 **
   2176 ** Returns          void
   2177 **
   2178 *******************************************************************************/
   2179 void nfa_ee_nci_action_ntf(tNFA_EE_MSG* p_data) {
   2180   tNFC_EE_ACTION_REVT* p_cbk = p_data->act.p_data;
   2181   tNFA_EE_ACTION evt_data;
   2182 
   2183   evt_data.ee_handle = (tNFA_HANDLE)p_cbk->nfcee_id | NFA_HANDLE_GROUP_EE;
   2184   evt_data.trigger = p_cbk->act_data.trigger;
   2185   memcpy(&(evt_data.param), &(p_cbk->act_data.param),
   2186          sizeof(tNFA_EE_ACTION_PARAM));
   2187   tNFA_EE_CBACK_DATA nfa_ee_cback_data;
   2188   nfa_ee_cback_data.action = evt_data;
   2189   nfa_ee_report_event(NULL, NFA_EE_ACTION_EVT, &nfa_ee_cback_data);
   2190 }
   2191 
   2192 /*******************************************************************************
   2193 **
   2194 ** Function         nfa_ee_nci_disc_req_ntf
   2195 **
   2196 ** Description      process the NFCEE discover request callback event
   2197 **
   2198 ** Returns          void
   2199 **
   2200 *******************************************************************************/
   2201 void nfa_ee_nci_disc_req_ntf(tNFA_EE_MSG* p_data) {
   2202   tNFC_EE_DISCOVER_REQ_REVT* p_cbk = p_data->disc_req.p_data;
   2203   tNFA_HANDLE ee_handle;
   2204   tNFA_EE_ECB* p_cb = NULL;
   2205   uint8_t report_ntf = 0;
   2206   uint8_t xx;
   2207 
   2208   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2209       "num_info: %d cur_ee:%d", p_cbk->num_info, nfa_ee_cb.cur_ee);
   2210 
   2211   for (xx = 0; xx < p_cbk->num_info; xx++) {
   2212     ee_handle = NFA_HANDLE_GROUP_EE | p_cbk->info[xx].nfcee_id;
   2213 
   2214     p_cb = nfa_ee_find_ecb(p_cbk->info[xx].nfcee_id);
   2215     if (!p_cb) {
   2216       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2217           "Cannot find cb for NFCEE: 0x%x", p_cbk->info[xx].nfcee_id);
   2218       p_cb = nfa_ee_find_ecb(NFA_EE_INVALID);
   2219       if (p_cb) {
   2220         p_cb->nfcee_id = p_cbk->info[xx].nfcee_id;
   2221         p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_ORDER;
   2222       } else {
   2223         LOG(ERROR) << StringPrintf("Cannot allocate cb for NFCEE: 0x%x",
   2224                                    p_cbk->info[xx].nfcee_id);
   2225         continue;
   2226       }
   2227     } else {
   2228       report_ntf |= nfa_ee_ecb_to_mask(p_cb);
   2229     }
   2230 
   2231     p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_DISC_REQ;
   2232     if (p_cbk->info[xx].op == NFC_EE_DISC_OP_ADD) {
   2233       if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_A) {
   2234         p_cb->la_protocol = p_cbk->info[xx].protocol;
   2235       } else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B) {
   2236         p_cb->lb_protocol = p_cbk->info[xx].protocol;
   2237       } else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_F) {
   2238         p_cb->lf_protocol = p_cbk->info[xx].protocol;
   2239       } else if (p_cbk->info[xx].tech_n_mode ==
   2240                  NFC_DISCOVERY_TYPE_LISTEN_B_PRIME) {
   2241         p_cb->lbp_protocol = p_cbk->info[xx].protocol;
   2242       }
   2243       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2244           "nfcee_id=0x%x ee_status=0x%x ecb_flags=0x%x la_protocol=0x%x "
   2245           "la_protocol=0x%x la_protocol=0x%x",
   2246           p_cb->nfcee_id, p_cb->ee_status, p_cb->ecb_flags, p_cb->la_protocol,
   2247           p_cb->lb_protocol, p_cb->lf_protocol);
   2248     } else {
   2249       if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_A) {
   2250         p_cb->la_protocol = 0;
   2251       } else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B) {
   2252         p_cb->lb_protocol = 0;
   2253       } else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_F) {
   2254         p_cb->lf_protocol = 0;
   2255       } else if (p_cbk->info[xx].tech_n_mode ==
   2256                  NFC_DISCOVERY_TYPE_LISTEN_B_PRIME) {
   2257         p_cb->lbp_protocol = 0;
   2258       }
   2259     }
   2260   }
   2261 
   2262   /* Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE */
   2263   if (report_ntf) nfa_ee_report_discover_req_evt();
   2264 }
   2265 
   2266 /*******************************************************************************
   2267 **
   2268 ** Function         nfa_ee_is_active
   2269 **
   2270 ** Description      Check if the given NFCEE is active
   2271 **
   2272 ** Returns          TRUE if the given NFCEE is active
   2273 **
   2274 *******************************************************************************/
   2275 bool nfa_ee_is_active(tNFA_HANDLE nfcee_id) {
   2276   bool is_active = false;
   2277   int xx;
   2278   tNFA_EE_ECB* p_cb = nfa_ee_cb.ecb;
   2279 
   2280   if ((NFA_HANDLE_GROUP_MASK & nfcee_id) == NFA_HANDLE_GROUP_EE)
   2281     nfcee_id &= NFA_HANDLE_MASK;
   2282 
   2283   if (nfcee_id == NFC_DH_ID) return true;
   2284 
   2285   /* compose output */
   2286   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++) {
   2287     if ((tNFA_HANDLE)p_cb->nfcee_id == nfcee_id) {
   2288       if (p_cb->ee_status == NFA_EE_STATUS_ACTIVE) {
   2289         is_active = true;
   2290       }
   2291       break;
   2292     }
   2293   }
   2294   return is_active;
   2295 }
   2296 
   2297 /*******************************************************************************
   2298 **
   2299 ** Function         nfa_ee_get_tech_route
   2300 **
   2301 ** Description      Given a power state, find the technology routing
   2302 **                  destination. The result is filled in the given p_handles
   2303 **                  in the order of A, B, F, Bprime
   2304 **
   2305 ** Returns          None
   2306 **
   2307 *******************************************************************************/
   2308 void nfa_ee_get_tech_route(uint8_t power_state, uint8_t* p_handles) {
   2309   int xx, yy;
   2310   tNFA_EE_ECB* p_cb;
   2311   uint8_t tech_mask_list[NFA_EE_MAX_TECH_ROUTE] = {
   2312       NFA_TECHNOLOGY_MASK_A, NFA_TECHNOLOGY_MASK_B, NFA_TECHNOLOGY_MASK_F,
   2313       NFA_TECHNOLOGY_MASK_B_PRIME};
   2314 
   2315   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%d", power_state);
   2316 
   2317   for (xx = 0; xx < NFA_EE_MAX_TECH_ROUTE; xx++) {
   2318     p_handles[xx] = NFC_DH_ID;
   2319     p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
   2320     for (yy = 0; yy < nfa_ee_cb.cur_ee; yy++, p_cb--) {
   2321       if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE) {
   2322         switch (power_state) {
   2323           case NFA_EE_PWR_STATE_ON:
   2324             if (p_cb->tech_switch_on & tech_mask_list[xx])
   2325               p_handles[xx] = p_cb->nfcee_id;
   2326             break;
   2327           case NFA_EE_PWR_STATE_SWITCH_OFF:
   2328             if (p_cb->tech_switch_off & tech_mask_list[xx])
   2329               p_handles[xx] = p_cb->nfcee_id;
   2330             break;
   2331           case NFA_EE_PWR_STATE_BATT_OFF:
   2332             if (p_cb->tech_battery_off & tech_mask_list[xx])
   2333               p_handles[xx] = p_cb->nfcee_id;
   2334             break;
   2335         }
   2336       }
   2337     }
   2338   }
   2339   DLOG_IF(INFO, nfc_debug_enabled)
   2340       << StringPrintf("0x%x, 0x%x, 0x%x, 0x%x", p_handles[0], p_handles[1],
   2341                       p_handles[2], p_handles[3]);
   2342 }
   2343 
   2344 /*******************************************************************************
   2345 **
   2346 ** Function         nfa_ee_check_set_routing
   2347 **
   2348 ** Description      If the new size exceeds the capacity of next block,
   2349 **                  send the routing command now and reset the related
   2350 **                  parameters.
   2351 **
   2352 ** Returns          void
   2353 **
   2354 *******************************************************************************/
   2355 void nfa_ee_check_set_routing(uint16_t new_size, int* p_max_len, uint8_t* p,
   2356                               int* p_cur_offset) {
   2357   uint8_t max_tlv = (uint8_t)((*p_max_len > NFA_EE_ROUT_MAX_TLV_SIZE)
   2358                                   ? NFA_EE_ROUT_MAX_TLV_SIZE
   2359                                   : *p_max_len);
   2360 
   2361   if (new_size + *p_cur_offset > max_tlv) {
   2362     if (NFC_SetRouting(true, *p, *p_cur_offset, p + 1) == NFA_STATUS_OK) {
   2363       nfa_ee_cb.wait_rsp++;
   2364     }
   2365     /* after the routing command is sent, re-use the same buffer to send the
   2366      * next routing command.
   2367      * reset the related parameters */
   2368     if (*p_max_len > *p_cur_offset)
   2369       *p_max_len -= *p_cur_offset; /* the max is reduced */
   2370     else
   2371       *p_max_len = 0;
   2372     *p_cur_offset = 0; /* nothing is in queue any more */
   2373     *p = 0;            /* num_tlv=0 */
   2374   }
   2375 }
   2376 
   2377 /*******************************************************************************
   2378 **
   2379 ** Function         nfa_ee_route_add_one_ecb_order
   2380 **
   2381 ** Description      Add the routing entries for NFCEE/DH in order defined
   2382 **
   2383 ** Returns          NFA_STATUS_OK, if ok to continue
   2384 **
   2385 *******************************************************************************/
   2386 void nfa_ee_route_add_one_ecb_by_route_order(tNFA_EE_ECB* p_cb, int rout_type,
   2387                                              int* p_max_len, bool more,
   2388                                              uint8_t* ps, int* p_cur_offset) {
   2389   nfa_ee_check_set_routing(p_cb->size_mask, p_max_len, ps, p_cur_offset);
   2390 
   2391   /* use the first byte of the buffer (ps) to keep the num_tlv */
   2392   uint8_t num_tlv = *ps;
   2393   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2394       "%s - max_len:%d, cur_offset:%d, more:%d, num_tlv:%d,rout_type:- %d",
   2395       __func__, *p_max_len, *p_cur_offset, more, num_tlv, rout_type);
   2396   uint8_t* pp = ps + 1 + *p_cur_offset;
   2397   uint8_t* p = pp;
   2398   uint16_t tlv_size = (uint8_t)*p_cur_offset;
   2399 
   2400   switch (rout_type) {
   2401     case NCI_ROUTE_ORDER_TECHNOLOGY: {
   2402       nfa_ee_add_tech_route_to_ecb(p_cb, pp, p, ps, p_cur_offset);
   2403     } break;
   2404 
   2405     case NCI_ROUTE_ORDER_PROTOCOL: {
   2406       nfa_ee_add_proto_route_to_ecb(p_cb, pp, p, ps, p_cur_offset);
   2407     } break;
   2408     case NCI_ROUTE_ORDER_AID: {
   2409       nfa_ee_add_aid_route_to_ecb(p_cb, pp, p, ps, p_cur_offset, p_max_len);
   2410     } break;
   2411     case NCI_ROUTE_ORDER_SYS_CODE: {
   2412       nfa_ee_add_sys_code_route_to_ecb(p_cb, pp, p, ps, p_cur_offset,
   2413                                        p_max_len);
   2414     } break;
   2415     default: {
   2416       DLOG_IF(INFO, nfc_debug_enabled)
   2417           << StringPrintf("%s -  Route type - NA:- %d", __func__, rout_type);
   2418     }
   2419   }
   2420 
   2421   /* update the total number of entries */
   2422   num_tlv = *ps;
   2423 
   2424   tlv_size = nfa_ee_total_lmrt_size();
   2425   if (tlv_size) {
   2426     nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
   2427   }
   2428   if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ROUTING) {
   2429     nfa_ee_cb.ee_cfg_sts |= NFA_EE_STS_CHANGED_ROUTING;
   2430   }
   2431   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2432       "ee_cfg_sts:0x%02x lmrt_size:%d", nfa_ee_cb.ee_cfg_sts, tlv_size);
   2433 
   2434   if (more == false) {
   2435     /* last entry. update routing table now */
   2436     if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_CHANGED_ROUTING) {
   2437       if (tlv_size) {
   2438         nfa_ee_cb.ee_cfg_sts |= NFA_EE_STS_PREV_ROUTING;
   2439       } else {
   2440         nfa_ee_cb.ee_cfg_sts &= ~NFA_EE_STS_PREV_ROUTING;
   2441       }
   2442       DLOG_IF(INFO, nfc_debug_enabled)
   2443           << StringPrintf("%s : set routing num_tlv:%d tlv_size:%d", __func__,
   2444                           num_tlv, tlv_size);
   2445       if (NFC_SetRouting(more, num_tlv, (uint8_t)(*p_cur_offset), ps + 1) ==
   2446           NFA_STATUS_OK) {
   2447         nfa_ee_cb.wait_rsp++;
   2448       }
   2449     } else if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_PREV_ROUTING) {
   2450       if (tlv_size == 0) {
   2451         nfa_ee_cb.ee_cfg_sts &= ~NFA_EE_STS_PREV_ROUTING;
   2452         /* indicated routing is configured to NFCC */
   2453         nfa_ee_cb.ee_cfg_sts |= NFA_EE_STS_CHANGED_ROUTING;
   2454         if (NFC_SetRouting(more, 0, 0, ps + 1) == NFA_STATUS_OK) {
   2455           nfa_ee_cb.wait_rsp++;
   2456         }
   2457       }
   2458     }
   2459   }
   2460 }
   2461 
   2462 /*******************************************************************************
   2463 **
   2464 ** Function         nfa_ee_need_recfg
   2465 **
   2466 ** Description      Check if any API function to configure the routing table or
   2467 **                  VS is called since last update
   2468 **
   2469 **                  The algorithm for the NFCEE configuration handling is as
   2470 **                  follows:
   2471 **
   2472 **                  Each NFCEE_ID/DH has its own control block - tNFA_EE_ECB
   2473 **                  Each control block uses ecb_flags to keep track if an API
   2474 **                  that changes routing/VS is invoked. This ecb_flags is
   2475 **                  cleared at the end of nfa_ee_update_rout().
   2476 **
   2477 **                  nfa_ee_cb.ee_cfged is the bitmask of the control blocks with
   2478 **                  routing/VS configuration and NFA_EE_CFGED_UPDATE_NOW.
   2479 **                  nfa_ee_cb.ee_cfged is cleared and re-calculated at the end
   2480 **                  of nfa_ee_update_rout().
   2481 **
   2482 **                  nfa_ee_cb.ee_cfg_sts is used to check is any status is
   2483 **                  changed and the associated command is issued to NFCC.
   2484 **                  nfa_ee_cb.ee_cfg_sts is AND with NFA_EE_STS_PREV at the end
   2485 **                  of nfa_ee_update_rout() to clear the NFA_EE_STS_CHANGED bits
   2486 **                  (except NFA_EE_STS_CHANGED_CANNED_VS is cleared in
   2487 **                  nfa_ee_vs_cback)
   2488 **
   2489 ** Returns          TRUE if any configuration is changed
   2490 **
   2491 *******************************************************************************/
   2492 static bool nfa_ee_need_recfg(void) {
   2493   bool needed = false;
   2494   uint32_t xx;
   2495   tNFA_EE_ECB* p_cb;
   2496   uint8_t mask;
   2497 
   2498   DLOG_IF(INFO, nfc_debug_enabled)
   2499       << StringPrintf("ee_cfged: 0x%02x ee_cfg_sts: 0x%02x", nfa_ee_cb.ee_cfged,
   2500                       nfa_ee_cb.ee_cfg_sts);
   2501   /* if no routing/vs is configured, do not need to send the info to NFCC */
   2502   if (nfa_ee_cb.ee_cfged || nfa_ee_cb.ee_cfg_sts) {
   2503     if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_CHANGED) {
   2504       needed = true;
   2505     } else {
   2506       p_cb = &nfa_ee_cb.ecb[NFA_EE_CB_4_DH];
   2507       mask = 1 << NFA_EE_CB_4_DH;
   2508       for (xx = 0; xx <= nfa_ee_cb.cur_ee; xx++) {
   2509         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2510             "%d: ecb_flags  : 0x%02x, mask: 0x%02x", xx, p_cb->ecb_flags, mask);
   2511         if ((p_cb->ecb_flags) && (nfa_ee_cb.ee_cfged & mask)) {
   2512           needed = true;
   2513           break;
   2514         }
   2515         p_cb = &nfa_ee_cb.ecb[xx];
   2516         mask = 1 << xx;
   2517       }
   2518     }
   2519   }
   2520 
   2521   return needed;
   2522 }
   2523 
   2524 /*******************************************************************************
   2525 **
   2526 ** Function         nfa_ee_rout_timeout
   2527 **
   2528 ** Description      Anytime VS or routing entries are changed,
   2529 **                  a 1 second timer is started. This function is called when
   2530 **                  the timer expires or NFA_EeUpdateNow() is called.
   2531 **
   2532 ** Returns          void
   2533 **
   2534 *******************************************************************************/
   2535 void nfa_ee_rout_timeout(__attribute__((unused)) tNFA_EE_MSG* p_data) {
   2536   uint8_t ee_cfged = nfa_ee_cb.ee_cfged;
   2537 
   2538   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
   2539   if (nfa_ee_need_recfg()) {
   2540     /* discovery is not started */
   2541     nfa_ee_update_rout();
   2542   }
   2543 
   2544   if (nfa_ee_cb.wait_rsp) nfa_ee_cb.ee_wait_evt |= NFA_EE_WAIT_UPDATE_RSP;
   2545   if (ee_cfged & NFA_EE_CFGED_UPDATE_NOW) {
   2546     /* need to report NFA_EE_UPDATED_EVT when done updating NFCC */
   2547     nfa_ee_cb.ee_wait_evt |= NFA_EE_WAIT_UPDATE;
   2548     if (!nfa_ee_cb.wait_rsp) {
   2549       nfa_ee_report_update_evt();
   2550     }
   2551   }
   2552 }
   2553 
   2554 /*******************************************************************************
   2555 **
   2556 ** Function         nfa_ee_discv_timeout
   2557 **
   2558 ** Description
   2559 **
   2560 **
   2561 **
   2562 ** Returns          void
   2563 **
   2564 *******************************************************************************/
   2565 void nfa_ee_discv_timeout(__attribute__((unused)) tNFA_EE_MSG* p_data) {
   2566   if (NFA_GetNCIVersion() != NCI_VERSION_2_0) NFC_NfceeDiscover(false);
   2567   if (nfa_ee_cb.p_enable_cback)
   2568     (*nfa_ee_cb.p_enable_cback)(NFA_EE_DISC_STS_OFF);
   2569 }
   2570 
   2571 /*******************************************************************************
   2572 **
   2573 ** Function         nfa_ee_lmrt_to_nfcc
   2574 **
   2575 ** Description      This function would set the listen mode routing table
   2576 **                  to NFCC.
   2577 **
   2578 ** Returns          void
   2579 **
   2580 *******************************************************************************/
   2581 void nfa_ee_lmrt_to_nfcc(__attribute__((unused)) tNFA_EE_MSG* p_data) {
   2582   int xx;
   2583   tNFA_EE_ECB* p_cb;
   2584   uint8_t* p = NULL;
   2585   bool more = true;
   2586   bool check = true;
   2587   uint8_t last_active = NFA_EE_INVALID;
   2588   int max_len;
   2589   tNFA_STATUS status = NFA_STATUS_FAILED;
   2590   int cur_offset;
   2591   uint8_t max_tlv;
   2592 
   2593   /* update routing table: DH and the activated NFCEEs */
   2594   p = (uint8_t*)GKI_getbuf(NFA_EE_ROUT_BUF_SIZE);
   2595   if (p == NULL) {
   2596     LOG(ERROR) << StringPrintf("no buffer to send routing info.");
   2597     tNFA_EE_CBACK_DATA nfa_ee_cback_data;
   2598     nfa_ee_cback_data.status = status;
   2599     nfa_ee_report_event(NULL, NFA_EE_NO_MEM_ERR_EVT, &nfa_ee_cback_data);
   2600     return;
   2601   }
   2602 
   2603   /* find the last active NFCEE. */
   2604   p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
   2605   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb--) {
   2606     if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE) {
   2607       if (last_active == NFA_EE_INVALID) {
   2608         last_active = p_cb->nfcee_id;
   2609         DLOG_IF(INFO, nfc_debug_enabled)
   2610             << StringPrintf("last_active: 0x%x", last_active);
   2611       }
   2612     }
   2613   }
   2614   if (last_active == NFA_EE_INVALID) {
   2615     check = false;
   2616   }
   2617 
   2618   max_len = NFC_GetLmrtSize();
   2619   max_tlv =
   2620       (uint8_t)((max_len > NFA_EE_ROUT_MAX_TLV_SIZE) ? NFA_EE_ROUT_MAX_TLV_SIZE
   2621                                                      : max_len);
   2622   cur_offset = 0;
   2623   /* use the first byte of the buffer (p) to keep the num_tlv */
   2624   *p = 0;
   2625   for (int rt = NCI_ROUTE_ORDER_AID; rt <= NCI_ROUTE_ORDER_TECHNOLOGY; rt++) {
   2626     /* add the routing entries for NFCEEs */
   2627     p_cb = &nfa_ee_cb.ecb[0];
   2628 
   2629     for (xx = 0; (xx < nfa_ee_cb.cur_ee) && check; xx++, p_cb++) {
   2630       if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE) {
   2631         DLOG_IF(INFO, nfc_debug_enabled)
   2632             << StringPrintf("%s --add the routing for NFCEEs!!", __func__);
   2633         nfa_ee_route_add_one_ecb_by_route_order(p_cb, rt, &max_len, more, p,
   2634                                                 &cur_offset);
   2635       }
   2636     }
   2637     if (rt == NCI_ROUTE_ORDER_TECHNOLOGY) more = false;
   2638     /* add the routing entries for DH */
   2639     DLOG_IF(INFO, nfc_debug_enabled)
   2640         << StringPrintf("%s --add the routing for DH!!", __func__);
   2641     nfa_ee_route_add_one_ecb_by_route_order(&nfa_ee_cb.ecb[NFA_EE_CB_4_DH], rt,
   2642                                             &max_len, more, p, &cur_offset);
   2643   }
   2644 
   2645   GKI_freebuf(p);
   2646 }
   2647 
   2648 /*******************************************************************************
   2649 **
   2650 ** Function         nfa_ee_update_rout
   2651 **
   2652 ** Description      This function would set the VS and listen mode routing table
   2653 **                  to NFCC.
   2654 **
   2655 ** Returns          void
   2656 **
   2657 *******************************************************************************/
   2658 void nfa_ee_update_rout(void) {
   2659   int xx;
   2660   tNFA_EE_ECB* p_cb;
   2661   uint8_t mask;
   2662   tNFA_EE_MSG nfa_ee_msg;
   2663 
   2664   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
   2665       "nfa_ee_update_rout ee_cfg_sts:0x%02x", nfa_ee_cb.ee_cfg_sts);
   2666 
   2667   /* use action function to send routing and VS configuration to NFCC */
   2668   nfa_ee_msg.hdr.event = NFA_EE_CFG_TO_NFCC_EVT;
   2669   nfa_ee_evt_hdlr(&nfa_ee_msg.hdr);
   2670 
   2671   /* all configuration is updated to NFCC, clear the status mask */
   2672   nfa_ee_cb.ee_cfg_sts &= NFA_EE_STS_PREV;
   2673   nfa_ee_cb.ee_cfged = 0;
   2674   p_cb = &nfa_ee_cb.ecb[0];
   2675   for (xx = 0; xx < NFA_EE_NUM_ECBS; xx++, p_cb++) {
   2676     p_cb->ecb_flags = 0;
   2677     mask = (1 << xx);
   2678     if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off |
   2679         p_cb->proto_switch_on | p_cb->proto_switch_off |
   2680         p_cb->proto_battery_off | p_cb->aid_entries |
   2681         p_cb->sys_code_cfg_entries) {
   2682       /* this entry has routing configuration. mark it configured */
   2683       nfa_ee_cb.ee_cfged |= mask;
   2684     }
   2685   }
   2686   DLOG_IF(INFO, nfc_debug_enabled)
   2687       << StringPrintf("nfa_ee_update_rout ee_cfg_sts:0x%02x ee_cfged:0x%02x",
   2688                       nfa_ee_cb.ee_cfg_sts, nfa_ee_cb.ee_cfged);
   2689 }
   2690