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