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     if (   (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     {
    544         /* nothing to change */
    545         evt_data.status = NFA_STATUS_OK;
    546         nfa_ee_report_event (p_cb->p_ee_cback, NFA_EE_SET_TECH_CFG_EVT, &evt_data);
    547         return;
    548     }
    549 
    550     p_cb->tech_switch_on   = p_data->set_tech.technologies_switch_on;
    551     p_cb->tech_switch_off  = p_data->set_tech.technologies_switch_off;
    552     p_cb->tech_battery_off = p_data->set_tech.technologies_battery_off;
    553     nfa_ee_update_route_size(p_cb);
    554     if (nfa_ee_total_lmrt_size() > NFC_GetLmrtSize())
    555     {
    556         NFA_TRACE_ERROR0 ("nfa_ee_api_set_tech_cfg Exceed LMRT size");
    557         evt_data.status        = NFA_STATUS_BUFFER_FULL;
    558         p_cb->tech_switch_on   = old_tech_switch_on;
    559         p_cb->tech_switch_off  = old_tech_switch_off;
    560         p_cb->tech_battery_off = old_tech_battery_off;
    561         p_cb->size_mask        = old_size_mask;
    562     }
    563     else
    564     {
    565         p_cb->ecb_flags       |= NFA_EE_ECB_FLAGS_TECH;
    566         if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off)
    567         {
    568             /* if any technology in any power mode is configured, mark this entry as configured */
    569             nfa_ee_cb.ee_cfged    |= nfa_ee_ecb_to_mask(p_cb);
    570         }
    571         nfa_ee_start_timer();
    572     }
    573     nfa_ee_report_event (p_cb->p_ee_cback, NFA_EE_SET_TECH_CFG_EVT, &evt_data);
    574 }
    575 
    576 /*******************************************************************************
    577 **
    578 ** Function         nfa_ee_api_set_proto_cfg
    579 **
    580 ** Description      process set protocol routing configuration from user
    581 **                  start a 1 second timer. When the timer expires,
    582 **                  the configuration collected in control block is sent to NFCC
    583 **
    584 ** Returns          void
    585 **
    586 *******************************************************************************/
    587 void nfa_ee_api_set_proto_cfg(tNFA_EE_MSG *p_data)
    588 {
    589     tNFA_EE_ECB *p_cb = p_data->cfg_hdr.p_cb;
    590     tNFA_EE_CBACK_DATA  evt_data = {0};
    591     tNFA_PROTOCOL_MASK    old_proto_switch_on   = p_cb->proto_switch_on;
    592     tNFA_PROTOCOL_MASK    old_proto_switch_off  = p_cb->proto_switch_off;
    593     tNFA_PROTOCOL_MASK    old_proto_battery_off = p_cb->proto_battery_off;
    594     UINT8                   old_size_mask        = p_cb->size_mask;
    595 
    596     if (   (p_cb->proto_switch_on == p_data->set_proto.protocols_switch_on)
    597         && (p_cb->proto_switch_off == p_data->set_proto.protocols_switch_off)
    598         && (p_cb->proto_battery_off == p_data->set_proto.protocols_battery_off)  )
    599     {
    600         /* nothing to change */
    601         evt_data.status = NFA_STATUS_OK;
    602         nfa_ee_report_event (p_cb->p_ee_cback, NFA_EE_SET_PROTO_CFG_EVT, &evt_data);
    603         return;
    604     }
    605 
    606     p_cb->proto_switch_on       = p_data->set_proto.protocols_switch_on;
    607     p_cb->proto_switch_off      = p_data->set_proto.protocols_switch_off;
    608     p_cb->proto_battery_off     = p_data->set_proto.protocols_battery_off;
    609     nfa_ee_update_route_size(p_cb);
    610     if (nfa_ee_total_lmrt_size() > NFC_GetLmrtSize())
    611     {
    612         NFA_TRACE_ERROR0 ("nfa_ee_api_set_proto_cfg Exceed LMRT size");
    613         evt_data.status         = NFA_STATUS_BUFFER_FULL;
    614         p_cb->proto_switch_on   = old_proto_switch_on;
    615         p_cb->proto_switch_off  = old_proto_switch_off;
    616         p_cb->proto_battery_off = old_proto_battery_off;
    617         p_cb->size_mask         = old_size_mask;
    618     }
    619     else
    620     {
    621         p_cb->ecb_flags            |= NFA_EE_ECB_FLAGS_PROTO;
    622         if (p_cb->proto_switch_on | p_cb->proto_switch_off | p_cb->proto_battery_off)
    623         {
    624             /* if any protocol in any power mode is configured, mark this entry as configured */
    625             nfa_ee_cb.ee_cfged         |= nfa_ee_ecb_to_mask(p_cb);
    626         }
    627         nfa_ee_start_timer();
    628     }
    629     nfa_ee_report_event (p_cb->p_ee_cback, NFA_EE_SET_PROTO_CFG_EVT, &evt_data);
    630 }
    631 
    632 /*******************************************************************************
    633 **
    634 ** Function         nfa_ee_api_add_aid
    635 **
    636 ** Description      process add an AID routing configuration from user
    637 **                  start a 1 second timer. When the timer expires,
    638 **                  the configuration collected in control block is sent to NFCC
    639 **
    640 ** Returns          void
    641 **
    642 *******************************************************************************/
    643 void nfa_ee_api_add_aid(tNFA_EE_MSG *p_data)
    644 {
    645     tNFA_EE_API_ADD_AID *p_add = &p_data->add_aid;
    646     tNFA_EE_ECB *p_cb = p_data->cfg_hdr.p_cb;
    647     tNFA_EE_ECB *p_chk_cb;
    648     UINT8   *p, *p_start;
    649     int     len, len_needed;
    650     tNFA_EE_CBACK_DATA  evt_data = {0};
    651     int offset = 0, entry = 0;
    652     UINT16  new_size;
    653 
    654     nfa_ee_trace_aid ("nfa_ee_api_add_aid", p_cb->nfcee_id, p_add->aid_len, p_add->p_aid);
    655     p_chk_cb = nfa_ee_find_aid_offset(p_add->aid_len, p_add->p_aid, &offset, &entry);
    656     if (p_chk_cb)
    657     {
    658         NFA_TRACE_DEBUG0 ("nfa_ee_api_add_aid The AID entry is already in the database");
    659         if (p_chk_cb == p_cb)
    660         {
    661             p_cb->aid_rt_info[entry]    |= NFA_EE_AE_ROUTE;
    662             new_size = nfa_ee_total_lmrt_size();
    663             if (new_size > NFC_GetLmrtSize())
    664             {
    665                 NFA_TRACE_ERROR1 ("Exceed LMRT size:%d (add ROUTE)", new_size);
    666                 evt_data.status             = NFA_STATUS_BUFFER_FULL;
    667                 p_cb->aid_rt_info[entry]    &= ~NFA_EE_AE_ROUTE;
    668             }
    669             else
    670             {
    671                 p_cb->aid_pwr_cfg[entry]     = p_add->power_state;
    672             }
    673         }
    674         else
    675         {
    676             NFA_TRACE_ERROR1 ("The AID entry is already in the database for different NFCEE ID:0x%02x", p_chk_cb->nfcee_id);
    677             evt_data.status = NFA_STATUS_SEMANTIC_ERROR;
    678         }
    679     }
    680     else
    681     {
    682         /* Find the total length so far */
    683         len = nfa_ee_find_total_aid_len(p_cb, 0);
    684 
    685         /* make sure the control block has enough room to hold this entry */
    686         len_needed  = p_add->aid_len + 2; /* tag/len */
    687 
    688         if ((len_needed + len) > NFA_EE_MAX_AID_CFG_LEN)
    689         {
    690             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);
    691             evt_data.status = NFA_STATUS_BUFFER_FULL;
    692         }
    693         else if (p_cb->aid_entries < NFA_EE_MAX_AID_ENTRIES)
    694         {
    695             new_size = nfa_ee_total_lmrt_size() + 4 + p_add->aid_len; /* 4 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) */
    696             if (new_size > NFC_GetLmrtSize())
    697             {
    698                 NFA_TRACE_ERROR1 ("Exceed LMRT size:%d", new_size);
    699                 evt_data.status        = NFA_STATUS_BUFFER_FULL;
    700             }
    701             else
    702             {
    703                 /* add AID */
    704                 p_cb->aid_pwr_cfg[p_cb->aid_entries]    = p_add->power_state;
    705                 p_cb->aid_rt_info[p_cb->aid_entries]    = NFA_EE_AE_ROUTE;
    706                 p       = p_cb->aid_cfg + len;
    707                 p_start = p;
    708                 *p++    = NFA_EE_AID_CFG_TAG_NAME;
    709                 *p++    = p_add->aid_len;
    710                 memcpy(p, p_add->p_aid, p_add->aid_len);
    711                 p      += p_add->aid_len;
    712 
    713                 p_cb->aid_len[p_cb->aid_entries++]     = (UINT8)(p - p_start);
    714             }
    715         }
    716         else
    717         {
    718             NFA_TRACE_ERROR1 ("Exceed NFA_EE_MAX_AID_ENTRIES:%d", NFA_EE_MAX_AID_ENTRIES);
    719             evt_data.status = NFA_STATUS_BUFFER_FULL;
    720         }
    721     }
    722 
    723     if (evt_data.status == NFA_STATUS_OK)
    724     {
    725         /* mark AID changed */
    726         p_cb->ecb_flags                       |= NFA_EE_ECB_FLAGS_AID;
    727         nfa_ee_cb.ee_cfged                    |= nfa_ee_ecb_to_mask(p_cb);
    728         nfa_ee_update_route_aid_size(p_cb);
    729         nfa_ee_start_timer();
    730     }
    731     NFA_TRACE_DEBUG2 ("status:%d ee_cfged:0x%02x ",evt_data.status, nfa_ee_cb.ee_cfged);
    732     /* report the status of this operation */
    733     nfa_ee_report_event (p_cb->p_ee_cback, NFA_EE_ADD_AID_EVT, &evt_data);
    734 }
    735 
    736 /*******************************************************************************
    737 **
    738 ** Function         nfa_ee_api_remove_aid
    739 **
    740 ** Description      process remove an AID routing configuration from user
    741 **                  start a 1 second timer. When the timer expires,
    742 **                  the configuration collected in control block is sent to NFCC
    743 **
    744 ** Returns          void
    745 **
    746 *******************************************************************************/
    747 void nfa_ee_api_remove_aid(tNFA_EE_MSG *p_data)
    748 {
    749     tNFA_EE_ECB  *p_cb;
    750     tNFA_EE_CBACK_DATA  evt_data = {0};
    751     int offset = 0, entry = 0, len;
    752     int rest_len;
    753     tNFA_EE_CBACK *p_cback = NULL;
    754 
    755     nfa_ee_trace_aid ("nfa_ee_api_remove_aid", 0, p_data->rm_aid.aid_len, p_data->rm_aid.p_aid);
    756     p_cb = nfa_ee_find_aid_offset(p_data->rm_aid.aid_len, p_data->rm_aid.p_aid, &offset, &entry);
    757     if (p_cb && p_cb->aid_entries)
    758     {
    759         NFA_TRACE_DEBUG2 ("aid_rt_info[%d]: 0x%02x", entry, p_cb->aid_rt_info[entry]);
    760         /* mark routing and VS changed */
    761         if (p_cb->aid_rt_info[entry] & NFA_EE_AE_ROUTE)
    762             p_cb->ecb_flags         |= NFA_EE_ECB_FLAGS_AID;
    763 
    764         if (p_cb->aid_rt_info[entry] & NFA_EE_AE_VS)
    765             p_cb->ecb_flags         |= NFA_EE_ECB_FLAGS_VS;
    766 
    767         /* remove the aid */
    768         if ((entry+1) < p_cb->aid_entries)
    769         {
    770             /* not the last entry, move the aid entries in control block */
    771             /* Find the total len from the next entry to the last one */
    772             rest_len = nfa_ee_find_total_aid_len(p_cb, entry + 1);
    773 
    774             len = p_cb->aid_len[entry];
    775             NFA_TRACE_DEBUG2 ("nfa_ee_api_remove_aid len:%d, rest_len:%d", len, rest_len);
    776             GKI_shiftup (&p_cb->aid_cfg[offset], &p_cb->aid_cfg[offset+ len], rest_len);
    777             rest_len = p_cb->aid_entries - entry;
    778             GKI_shiftup (&p_cb->aid_len[entry], &p_cb->aid_len[entry + 1], rest_len);
    779             GKI_shiftup (&p_cb->aid_pwr_cfg[entry], &p_cb->aid_pwr_cfg[entry + 1], rest_len);
    780             GKI_shiftup (&p_cb->aid_rt_info[entry], &p_cb->aid_rt_info[entry + 1], rest_len);
    781         }
    782         /* else the last entry, just reduce the aid_entries by 1 */
    783         p_cb->aid_entries--;
    784         nfa_ee_cb.ee_cfged      |= nfa_ee_ecb_to_mask(p_cb);
    785         nfa_ee_update_route_aid_size(p_cb);
    786         nfa_ee_start_timer();
    787         /* report NFA_EE_REMOVE_AID_EVT to the callback associated the NFCEE */
    788         p_cback = p_cb->p_ee_cback;
    789     }
    790     else
    791     {
    792         NFA_TRACE_ERROR0 ("nfa_ee_api_remove_aid The AID entry is not in the database");
    793         evt_data.status = NFA_STATUS_INVALID_PARAM;
    794     }
    795     nfa_ee_report_event (p_cback, NFA_EE_REMOVE_AID_EVT, &evt_data);
    796 }
    797 
    798 /*******************************************************************************
    799 **
    800 ** Function         nfa_ee_api_lmrt_size
    801 **
    802 ** Description      Reports the remaining size in the Listen Mode Routing Table
    803 **
    804 ** Returns          void
    805 **
    806 *******************************************************************************/
    807 void nfa_ee_api_lmrt_size(tNFA_EE_MSG *p_data)
    808 {
    809     tNFA_EE_CBACK_DATA  evt_data = {0};
    810     UINT16 total_size = NFC_GetLmrtSize();
    811 
    812     evt_data.size       = total_size - nfa_ee_total_lmrt_size();
    813     NFA_TRACE_DEBUG2 ("nfa_ee_api_lmrt_size total size:%d remaining size:%d", total_size, evt_data.size);
    814 
    815     nfa_ee_report_event (NULL, NFA_EE_REMAINING_SIZE_EVT, &evt_data);
    816 }
    817 
    818 /*******************************************************************************
    819 **
    820 ** Function         nfa_ee_api_update_now
    821 **
    822 ** Description      Initiates connection creation process to the given NFCEE
    823 **
    824 ** Returns          void
    825 **
    826 *******************************************************************************/
    827 void nfa_ee_api_update_now(tNFA_EE_MSG *p_data)
    828 {
    829     tNFA_EE_CBACK_DATA  evt_data;
    830 
    831     if (nfa_ee_cb.ee_wait_evt & NFA_EE_WAIT_UPDATE_ALL)
    832     {
    833         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);
    834         evt_data.status       = NFA_STATUS_SEMANTIC_ERROR;
    835         nfa_ee_report_event (NULL, NFA_EE_UPDATED_EVT, &evt_data);
    836         return;
    837     }
    838     nfa_sys_stop_timer(&nfa_ee_cb.timer);
    839     nfa_ee_cb.ee_cfged  |= NFA_EE_CFGED_UPDATE_NOW;
    840     nfa_ee_rout_timeout(p_data);
    841 }
    842 
    843 /*******************************************************************************
    844 **
    845 ** Function         nfa_ee_api_connect
    846 **
    847 ** Description      Initiates connection creation process to the given NFCEE
    848 **
    849 ** Returns          void
    850 **
    851 *******************************************************************************/
    852 void nfa_ee_api_connect(tNFA_EE_MSG *p_data)
    853 {
    854     tNFA_EE_ECB  *p_cb = p_data->connect.p_cb;
    855     int xx;
    856     tNFA_EE_CBACK_DATA  evt_data = {0};
    857 
    858     evt_data.connect.status       = NFA_STATUS_FAILED;
    859     if (p_cb->conn_st == NFA_EE_CONN_ST_NONE)
    860     {
    861         for (xx = 0; xx < p_cb->num_interface; xx++)
    862         {
    863             if (p_data->connect.ee_interface == p_cb->ee_interface[xx])
    864             {
    865                 p_cb->p_ee_cback        = p_data->connect.p_cback;
    866                 p_cb->conn_st           = NFA_EE_CONN_ST_WAIT;
    867                 p_cb->use_interface     = p_data->connect.ee_interface;
    868                 evt_data.connect.status = NFC_ConnCreate(NCI_DEST_TYPE_NFCEE, p_data->connect.nfcee_id,
    869                     p_data->connect.ee_interface, nfa_ee_conn_cback);
    870                 /* report the NFA_EE_CONNECT_EVT status on the response from NFCC */
    871                 break;
    872             }
    873         }
    874     }
    875 
    876     if (evt_data.connect.status != NCI_STATUS_OK)
    877     {
    878         evt_data.connect.ee_handle    = (tNFA_HANDLE)p_data->connect.nfcee_id | NFA_HANDLE_GROUP_EE;
    879         evt_data.connect.status       = NFA_STATUS_INVALID_PARAM;
    880         evt_data.connect.ee_interface = p_data->connect.ee_interface;
    881         nfa_ee_report_event (p_data->connect.p_cback, NFA_EE_CONNECT_EVT, &evt_data);
    882     }
    883 }
    884 
    885 /*******************************************************************************
    886 **
    887 ** Function         nfa_ee_api_send_data
    888 **
    889 ** Description      Send the given data packet to the given NFCEE
    890 **
    891 ** Returns          void
    892 **
    893 *******************************************************************************/
    894 void nfa_ee_api_send_data(tNFA_EE_MSG *p_data)
    895 {
    896     tNFA_EE_ECB  *p_cb = p_data->send_data.p_cb;
    897     BT_HDR *p_pkt;
    898     UINT16 size = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + p_data->send_data.data_len + BT_HDR_SIZE;
    899     UINT8  *p;
    900     tNFA_STATUS status = NFA_STATUS_FAILED;
    901 
    902     if (p_cb->conn_st == NFA_EE_CONN_ST_CONN)
    903     {
    904         p_pkt = (BT_HDR *)GKI_getbuf(size);
    905         if (p_pkt)
    906         {
    907             p_pkt->offset   = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
    908             p_pkt->len      = p_data->send_data.data_len;
    909             p               = (UINT8 *)(p_pkt+1) + p_pkt->offset;
    910             memcpy(p, p_data->send_data.p_data, p_pkt->len);
    911             NFC_SendData (p_cb->conn_id, p_pkt);
    912         }
    913         else
    914         {
    915             nfa_ee_report_event( p_cb->p_ee_cback, NFA_EE_NO_MEM_ERR_EVT, (tNFA_EE_CBACK_DATA *)&status);
    916         }
    917     }
    918     else
    919     {
    920         nfa_ee_report_event( p_cb->p_ee_cback, NFA_EE_NO_CB_ERR_EVT, (tNFA_EE_CBACK_DATA *)&status);
    921     }
    922 }
    923 
    924 /*******************************************************************************
    925 **
    926 ** Function         nfa_ee_api_disconnect
    927 **
    928 ** Description      Initiates closing of the connection to the given NFCEE
    929 **
    930 ** Returns          void
    931 **
    932 *******************************************************************************/
    933 void nfa_ee_api_disconnect(tNFA_EE_MSG *p_data)
    934 {
    935     tNFA_EE_ECB  *p_cb = p_data->disconnect.p_cb;
    936     tNFA_EE_CBACK_DATA  evt_data = {0};
    937 
    938     if (p_cb->conn_st == NFA_EE_CONN_ST_CONN)
    939     {
    940         p_cb->conn_st = NFA_EE_CONN_ST_DISC;
    941         NFC_ConnClose(p_cb->conn_id);
    942     }
    943     evt_data.handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
    944     nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_DISCONNECT_EVT, &evt_data);
    945 }
    946 
    947 /*******************************************************************************
    948 **
    949 ** Function         nfa_ee_report_disc_done
    950 **
    951 ** Description      Process the callback for NFCEE discovery response
    952 **
    953 ** Returns          void
    954 **
    955 *******************************************************************************/
    956 void nfa_ee_report_disc_done(BOOLEAN notify_enable_done)
    957 {
    958     tNFA_EE_CBACK           *p_cback;
    959     tNFA_EE_CBACK_DATA      evt_data = {0};
    960 
    961     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);
    962     if (nfa_ee_cb.num_ee_expecting == 0)
    963     {
    964         if (notify_enable_done)
    965         {
    966             if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_INIT_DONE)
    967             {
    968                 nfa_sys_cback_notify_enable_complete (NFA_ID_EE);
    969                 if (nfa_ee_cb.p_enable_cback)
    970                     (*nfa_ee_cb.p_enable_cback)(NFA_EE_DISC_STS_ON);
    971             }
    972             else if ((nfa_ee_cb.em_state == NFA_EE_EM_STATE_RESTORING) && (nfa_ee_cb.ee_flags & NFA_EE_FLAG_NOTIFY_HCI) )
    973             {
    974                 nfa_ee_cb.ee_flags   &= ~NFA_EE_FLAG_NOTIFY_HCI;
    975                 if (nfa_ee_cb.p_enable_cback)
    976                     (*nfa_ee_cb.p_enable_cback)(NFA_EE_DISC_STS_ON);
    977             }
    978         }
    979 
    980 
    981         if (nfa_ee_cb.p_ee_disc_cback)
    982         {
    983             /* notify API callback */
    984             p_cback                         = nfa_ee_cb.p_ee_disc_cback;
    985             nfa_ee_cb.p_ee_disc_cback       = NULL;
    986             evt_data.status                         = NFA_STATUS_OK;
    987             evt_data.ee_discover.num_ee             = NFA_EE_MAX_EE_SUPPORTED;
    988             NFA_EeGetInfo(&evt_data.ee_discover.num_ee, evt_data.ee_discover.ee_info);
    989             nfa_ee_report_event (p_cback, NFA_EE_DISCOVER_EVT, &evt_data);
    990         }
    991     }
    992 }
    993 
    994 /*******************************************************************************
    995 **
    996 ** Function         nfa_ee_restore_ntf_done
    997 **
    998 ** Description      check if any ee_status still has NFA_EE_STATUS_PENDING bit
    999 **
   1000 ** Returns          TRUE, if all NFA_EE_STATUS_PENDING bits are removed
   1001 **
   1002 *******************************************************************************/
   1003 BOOLEAN nfa_ee_restore_ntf_done(void)
   1004 {
   1005     tNFA_EE_ECB     *p_cb;
   1006     BOOLEAN         is_done = TRUE;
   1007     int             xx;
   1008 
   1009     p_cb = nfa_ee_cb.ecb;
   1010     for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
   1011     {
   1012         if ((p_cb->nfcee_id != NFA_EE_INVALID) && (p_cb->ee_old_status & NFA_EE_STATUS_RESTORING))
   1013         {
   1014             is_done = FALSE;
   1015             break;
   1016         }
   1017     }
   1018     return is_done;
   1019 }
   1020 
   1021 /*******************************************************************************
   1022 **
   1023 ** Function         nfa_ee_remove_pending
   1024 **
   1025 ** Description      check if any ee_status still has NFA_EE_STATUS_RESTORING bit
   1026 **
   1027 ** Returns          TRUE, if all NFA_EE_STATUS_RESTORING bits are removed
   1028 **
   1029 *******************************************************************************/
   1030 static void nfa_ee_remove_pending(void)
   1031 {
   1032     tNFA_EE_ECB     *p_cb;
   1033     tNFA_EE_ECB     *p_cb_n, *p_cb_end;
   1034     int             xx, num_removed = 0;
   1035     int             first_removed = NFA_EE_MAX_EE_SUPPORTED;
   1036 
   1037     p_cb = nfa_ee_cb.ecb;
   1038     for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
   1039     {
   1040         if ((p_cb->nfcee_id != NFA_EE_INVALID) && (p_cb->ee_status & NFA_EE_STATUS_RESTORING))
   1041         {
   1042             p_cb->nfcee_id  = NFA_EE_INVALID;
   1043             num_removed ++;
   1044             if (first_removed == NFA_EE_MAX_EE_SUPPORTED)
   1045                 first_removed   = xx;
   1046         }
   1047     }
   1048 
   1049     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);
   1050     if (num_removed && (first_removed != (nfa_ee_cb.cur_ee - num_removed)))
   1051     {
   1052         /* if the removes ECB entried are not at the end, move the entries up */
   1053         p_cb_end = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
   1054         p_cb = &nfa_ee_cb.ecb[first_removed];
   1055         for (p_cb_n = p_cb + 1; p_cb_n <= p_cb_end;)
   1056         {
   1057             while ((p_cb_n->nfcee_id == NFA_EE_INVALID) && (p_cb_n <= p_cb_end))
   1058             {
   1059                 p_cb_n++;
   1060             }
   1061 
   1062             if (p_cb_n <= p_cb_end)
   1063             {
   1064                 memcpy(p_cb, p_cb_n, sizeof(tNFA_EE_ECB));
   1065                 p_cb_n->nfcee_id = NFA_EE_INVALID;
   1066             }
   1067             p_cb++;
   1068             p_cb_n++;
   1069         }
   1070     }
   1071     nfa_ee_cb.cur_ee -= (UINT8)num_removed;
   1072 }
   1073 
   1074 
   1075 /*******************************************************************************
   1076 **
   1077 ** Function         nfa_ee_nci_disc_rsp
   1078 **
   1079 ** Description      Process the callback for NFCEE discovery response
   1080 **
   1081 ** Returns          void
   1082 **
   1083 *******************************************************************************/
   1084 void nfa_ee_nci_disc_rsp(tNFA_EE_MSG *p_data)
   1085 {
   1086     tNFC_NFCEE_DISCOVER_REVT    *p_evt = p_data->disc_rsp.p_data;
   1087     tNFA_EE_ECB              *p_cb;
   1088     UINT8   xx;
   1089     UINT8   num_nfcee = p_evt->num_nfcee;
   1090     BOOLEAN notify_enable_done = FALSE;
   1091 
   1092     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);
   1093     switch (nfa_ee_cb.em_state)
   1094     {
   1095     case NFA_EE_EM_STATE_INIT:
   1096         nfa_ee_cb.cur_ee            = 0;
   1097         nfa_ee_cb.num_ee_expecting  = 0;
   1098         if (num_nfcee == 0)
   1099         {
   1100             nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1101             notify_enable_done = TRUE;
   1102             if (p_evt->status != NFC_STATUS_OK)
   1103             {
   1104                 nfa_sys_stop_timer(&nfa_ee_cb.discv_timer);
   1105             }
   1106         }
   1107         break;
   1108 
   1109     case NFA_EE_EM_STATE_INIT_DONE:
   1110         if (num_nfcee)
   1111         {
   1112             /* if this is initiated by api function,
   1113              * check if the number of NFCEE expected is more than what's currently in CB */
   1114             if (num_nfcee > NFA_EE_MAX_EE_SUPPORTED)
   1115                 num_nfcee = NFA_EE_MAX_EE_SUPPORTED;
   1116             if (nfa_ee_cb.cur_ee < num_nfcee)
   1117             {
   1118                 p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee];
   1119                 for (xx = nfa_ee_cb.cur_ee; xx < num_nfcee; xx++, p_cb++)
   1120                 {
   1121                     /* mark the new entries as a new one */
   1122                     p_cb->nfcee_id = NFA_EE_INVALID;
   1123                 }
   1124             }
   1125             nfa_ee_cb.cur_ee = num_nfcee;
   1126         }
   1127         break;
   1128 
   1129     case NFA_EE_EM_STATE_RESTORING:
   1130         if (num_nfcee == 0)
   1131         {
   1132             nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1133             nfa_ee_remove_pending();
   1134             nfa_ee_check_restore_complete();
   1135             if (p_evt->status != NFC_STATUS_OK)
   1136             {
   1137                 nfa_sys_stop_timer(&nfa_ee_cb.discv_timer);
   1138             }
   1139         }
   1140         break;
   1141     }
   1142 
   1143     if (p_evt->status == NFC_STATUS_OK)
   1144     {
   1145         nfa_ee_cb.num_ee_expecting = p_evt->num_nfcee;
   1146         if (nfa_ee_cb.num_ee_expecting > NFA_EE_MAX_EE_SUPPORTED)
   1147         {
   1148             NFA_TRACE_ERROR2 ("NFA-EE num_ee_expecting:%d > max:%d", nfa_ee_cb.num_ee_expecting, NFA_EE_MAX_EE_SUPPORTED);
   1149         }
   1150     }
   1151     nfa_ee_report_disc_done(notify_enable_done);
   1152     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);
   1153 }
   1154 
   1155 /*******************************************************************************
   1156 **
   1157 ** Function         nfa_ee_nci_disc_ntf
   1158 **
   1159 ** Description      Process the callback for NFCEE discovery notification
   1160 **
   1161 ** Returns          void
   1162 **
   1163 *******************************************************************************/
   1164 void nfa_ee_nci_disc_ntf(tNFA_EE_MSG *p_data)
   1165 {
   1166     tNFC_NFCEE_INFO_REVT    *p_ee = p_data->disc_ntf.p_data;
   1167     tNFA_EE_ECB             *p_cb = NULL;
   1168     BOOLEAN                 notify_enable_done = FALSE;
   1169     BOOLEAN                 notify_new_ee = FALSE;
   1170     tNFA_EE_CBACK_DATA      evt_data = {0};
   1171     tNFA_EE_INFO            *p_info;
   1172     tNFA_EE_EM_STATE        new_em_state = NFA_EE_EM_STATE_MAX;
   1173 
   1174     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);
   1175     if (nfa_ee_cb.num_ee_expecting)
   1176     {
   1177         nfa_ee_cb.num_ee_expecting--;
   1178         if ((nfa_ee_cb.num_ee_expecting == 0) && (nfa_ee_cb.p_ee_disc_cback != NULL))
   1179         {
   1180             /* Discovery triggered by API function */
   1181             NFC_NfceeDiscover(FALSE);
   1182         }
   1183     }
   1184     switch (nfa_ee_cb.em_state)
   1185     {
   1186     case NFA_EE_EM_STATE_INIT:
   1187         if (nfa_ee_cb.cur_ee < NFA_EE_MAX_EE_SUPPORTED)
   1188         {
   1189             /* the cb can collect up to NFA_EE_MAX_EE_SUPPORTED ee_info */
   1190             p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee++];
   1191         }
   1192 
   1193         if (nfa_ee_cb.num_ee_expecting == 0)
   1194         {
   1195             /* notify init_done callback */
   1196             nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1197             notify_enable_done = TRUE;
   1198         }
   1199         break;
   1200 
   1201     case NFA_EE_EM_STATE_INIT_DONE:
   1202         p_cb = nfa_ee_find_ecb (p_ee->nfcee_id);
   1203         if (p_cb == NULL)
   1204         {
   1205             /* the NFCEE ID is not in the last NFCEE discovery
   1206              * maybe it's a new one */
   1207             p_cb = nfa_ee_find_ecb (NFA_EE_INVALID);
   1208             if (p_cb)
   1209             {
   1210                 nfa_ee_cb.cur_ee++;
   1211                 notify_new_ee = TRUE;
   1212             }
   1213         }
   1214         else if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ORDER)
   1215         {
   1216             nfa_ee_cb.cur_ee++;
   1217             notify_new_ee = TRUE;
   1218         }
   1219         else
   1220         {
   1221             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);
   1222         }
   1223         break;
   1224 
   1225     case NFA_EE_EM_STATE_RESTORING:
   1226         p_cb = nfa_ee_find_ecb (p_ee->nfcee_id);
   1227         if (p_cb == NULL)
   1228         {
   1229             /* the NFCEE ID is not in the last NFCEE discovery
   1230              * maybe it's a new one */
   1231             p_cb = nfa_ee_find_ecb (NFA_EE_INVALID);
   1232             if (p_cb)
   1233             {
   1234                 nfa_ee_cb.cur_ee++;
   1235                 notify_new_ee = TRUE;
   1236             }
   1237         }
   1238         if (nfa_ee_cb.num_ee_expecting == 0)
   1239         {
   1240             /* notify init_done callback */
   1241             notify_enable_done = TRUE;
   1242             if (nfa_ee_restore_ntf_done())
   1243             {
   1244                 new_em_state       = NFA_EE_EM_STATE_INIT_DONE;
   1245             }
   1246         }
   1247         break;
   1248     }
   1249     NFA_TRACE_DEBUG1 ("nfa_ee_nci_disc_ntf cur_ee:%d", nfa_ee_cb.cur_ee);
   1250 
   1251     if (p_cb)
   1252     {
   1253         p_cb->nfcee_id      = p_ee->nfcee_id;
   1254         p_cb->ee_status     = p_ee->ee_status;
   1255         p_cb->num_interface = p_ee->num_interface;
   1256         memcpy(p_cb->ee_interface, p_ee->ee_interface, p_ee->num_interface);
   1257         p_cb->num_tlvs      = p_ee->num_tlvs;
   1258         memcpy(p_cb->ee_tlv, p_ee->ee_tlv, p_ee->num_tlvs * sizeof(tNFA_EE_TLV));
   1259 
   1260         if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_RESTORING)
   1261         {
   1262             /* NCI spec says: An NFCEE_DISCOVER_NTF that contains a Protocol type of "HCI Access"
   1263              * SHALL NOT contain any other additional Protocol
   1264              * i.e. check only first supported NFCEE interface is HCI access */
   1265             /* NFA_HCI module handles restoring configurations for HCI access */
   1266             if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS)
   1267             {
   1268                 if ((nfa_ee_cb.ee_flags & NFA_EE_FLAG_WAIT_HCI) == 0)
   1269                 {
   1270                     nfa_ee_restore_one_ecb (p_cb);
   1271                 }
   1272                 /* else wait for NFA-HCI module to restore the HCI network information before enabling the NFCEE */
   1273             }
   1274         }
   1275 
   1276         if ((nfa_ee_cb.p_ee_disc_cback == NULL) && (notify_new_ee == TRUE))
   1277         {
   1278             if (nfa_dm_is_active() && (p_cb->ee_status != NFA_EE_STATUS_REMOVED))
   1279             {
   1280                 /* report this NFA_EE_NEW_EE_EVT only after NFA_DM_ENABLE_EVT is reported */
   1281                 p_info                  = &evt_data.new_ee;
   1282                 p_info->ee_handle       = NFA_HANDLE_GROUP_EE | (tNFA_HANDLE)p_cb->nfcee_id;
   1283                 p_info->ee_status       = p_cb->ee_status;
   1284                 p_info->num_interface   = p_cb->num_interface;
   1285                 p_info->num_tlvs        = p_cb->num_tlvs;
   1286                 memcpy(p_info->ee_interface, p_cb->ee_interface, p_cb->num_interface);
   1287                 memcpy(p_info->ee_tlv, p_cb->ee_tlv, p_cb->num_tlvs * sizeof(tNFA_EE_TLV));
   1288                 nfa_ee_report_event (NULL, NFA_EE_NEW_EE_EVT, &evt_data);
   1289             }
   1290         }
   1291         else
   1292             nfa_ee_report_disc_done(notify_enable_done);
   1293 
   1294         if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ORDER)
   1295         {
   1296             NFA_TRACE_DEBUG0 ("NFA_EE_ECB_FLAGS_ORDER");
   1297             p_cb->ecb_flags &= ~NFA_EE_ECB_FLAGS_ORDER;
   1298             nfa_ee_report_discover_req_evt();
   1299         }
   1300 
   1301     }
   1302 
   1303     if (new_em_state != NFA_EE_EM_STATE_MAX)
   1304     {
   1305         nfa_ee_cb.em_state = new_em_state;
   1306         nfa_ee_check_restore_complete();
   1307     }
   1308 
   1309     if ((nfa_ee_cb.cur_ee == nfa_ee_max_ee_cfg) && (nfa_ee_cb.em_state == NFA_EE_EM_STATE_INIT_DONE) )
   1310     {
   1311         if (nfa_ee_cb.discv_timer.in_use)
   1312         {
   1313             nfa_sys_stop_timer (&nfa_ee_cb.discv_timer);
   1314             p_data->hdr.event = NFA_EE_DISCV_TIMEOUT_EVT;
   1315             nfa_ee_evt_hdlr((BT_HDR *)p_data);
   1316         }
   1317     }
   1318 }
   1319 
   1320 /*******************************************************************************
   1321 **
   1322 ** Function         nfa_ee_check_restore_complete
   1323 **
   1324 ** Description      Check if restore the NFA-EE related configuration to the
   1325 **                  state prior to low power mode is complete.
   1326 **                  If complete, notify sys.
   1327 **
   1328 ** Returns          void
   1329 **
   1330 *******************************************************************************/
   1331 void nfa_ee_check_restore_complete(void)
   1332 {
   1333     UINT32  xx;
   1334     tNFA_EE_ECB     *p_cb;
   1335     BOOLEAN         proc_complete = TRUE;
   1336 
   1337     p_cb = nfa_ee_cb.ecb;
   1338     for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
   1339     {
   1340         if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_RESTORE)
   1341         {
   1342             /* NFA_HCI module handles restoring configurations for HCI access.
   1343              * ignore the restoring status for HCI Access */
   1344             if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS)
   1345             {
   1346                 proc_complete = FALSE;
   1347                 break;
   1348             }
   1349         }
   1350     }
   1351 
   1352     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);
   1353     if (proc_complete)
   1354     {
   1355         /* update routing table when NFA_EE_ROUT_TIMEOUT_EVT is received */
   1356         if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_PREV_ROUTING)
   1357             nfa_ee_api_update_now(NULL);
   1358 
   1359         nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
   1360         nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_EE);
   1361     }
   1362 }
   1363 
   1364 /*******************************************************************************
   1365 **
   1366 ** Function         nfa_ee_build_discover_req_evt
   1367 **
   1368 ** Description      Build NFA_EE_DISCOVER_REQ_EVT for all active NFCEE
   1369 **
   1370 ** Returns          void
   1371 **
   1372 *******************************************************************************/
   1373 static void nfa_ee_build_discover_req_evt (tNFA_EE_DISCOVER_REQ *p_evt_data)
   1374 {
   1375     tNFA_EE_ECB           *p_cb;
   1376     tNFA_EE_DISCOVER_INFO *p_info;
   1377     UINT8                 xx;
   1378 
   1379     if (!p_evt_data)
   1380         return;
   1381 
   1382     p_evt_data->num_ee = 0;
   1383     p_cb               = nfa_ee_cb.ecb;
   1384     p_info             = p_evt_data->ee_disc_info;
   1385 
   1386     for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
   1387     {
   1388         if (  (p_cb->ee_status & NFA_EE_STATUS_INT_MASK)
   1389             ||(p_cb->ee_status != NFA_EE_STATUS_ACTIVE)
   1390             ||((p_cb->ecb_flags & NFA_EE_ECB_FLAGS_DISC_REQ) == 0)  )
   1391         {
   1392             continue;
   1393         }
   1394         p_info->ee_handle       = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
   1395         p_info->la_protocol     = p_cb->la_protocol;
   1396         p_info->lb_protocol     = p_cb->lb_protocol;
   1397         p_info->lf_protocol     = p_cb->lf_protocol;
   1398         p_info->lbp_protocol    = p_cb->lbp_protocol;
   1399         p_evt_data->num_ee++;
   1400         p_info++;
   1401 
   1402         NFA_TRACE_DEBUG6 ("[%d] ee_handle:0x%x, listen protocol A:%d, B:%d, F:%d, BP:%d",
   1403                           p_evt_data->num_ee, p_cb->nfcee_id,
   1404                           p_cb->la_protocol, p_cb->lb_protocol, p_cb->lf_protocol, p_cb->lbp_protocol);
   1405     }
   1406 
   1407     p_evt_data->status     = NFA_STATUS_OK;
   1408 }
   1409 
   1410 /*******************************************************************************
   1411 **
   1412 ** Function         nfa_ee_report_discover_req_evt
   1413 **
   1414 ** Description      Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE
   1415 **
   1416 ** Returns          void
   1417 **
   1418 *******************************************************************************/
   1419 static void nfa_ee_report_discover_req_evt(void)
   1420 {
   1421     tNFA_EE_DISCOVER_REQ    evt_data;
   1422 
   1423     if (nfa_ee_cb.p_enable_cback)
   1424         (*nfa_ee_cb.p_enable_cback) (NFA_EE_DISC_STS_REQ);
   1425 
   1426 
   1427     /* if this is restoring NFCC */
   1428     if (!nfa_dm_is_active ())
   1429     {
   1430         NFA_TRACE_DEBUG0 ("nfa_ee_report_discover_req_evt DM is not active");
   1431         return;
   1432     }
   1433 
   1434     nfa_ee_build_discover_req_evt (&evt_data);
   1435     nfa_ee_report_event(NULL, NFA_EE_DISCOVER_REQ_EVT, (tNFA_EE_CBACK_DATA *)&evt_data);
   1436 }
   1437 
   1438 /*******************************************************************************
   1439 **
   1440 ** Function         nfa_ee_nci_mode_set_rsp
   1441 **
   1442 ** Description      Process the result for NFCEE ModeSet response
   1443 **
   1444 ** Returns          void
   1445 **
   1446 *******************************************************************************/
   1447 void nfa_ee_nci_mode_set_rsp(tNFA_EE_MSG *p_data)
   1448 {
   1449     tNFA_EE_ECB *p_cb;
   1450     tNFA_EE_MODE_SET    mode_set;
   1451     tNFC_NFCEE_MODE_SET_REVT    *p_rsp = p_data->mode_set_rsp.p_data;
   1452 
   1453     NFA_TRACE_DEBUG2 ("nfa_ee_nci_mode_set_rsp() handle:0x%02x mode:%d", p_rsp->nfcee_id, p_rsp->mode);
   1454     p_cb = nfa_ee_find_ecb (p_rsp->nfcee_id);
   1455     if (p_cb == NULL)
   1456     {
   1457         NFA_TRACE_ERROR1 ("nfa_ee_nci_mode_set_rsp() Can not find cb for handle:0x%02x", p_rsp->nfcee_id);
   1458         return;
   1459     }
   1460 
   1461     /* update routing table and vs on mode change */
   1462     nfa_ee_start_timer();
   1463 
   1464     if (p_rsp->status == NFA_STATUS_OK)
   1465     {
   1466 
   1467         if (p_rsp->mode == NFA_EE_MD_ACTIVATE)
   1468         {
   1469             p_cb->ee_status = NFC_NFCEE_STATUS_ACTIVE;
   1470         }
   1471         else
   1472         {
   1473             if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off |
   1474                 p_cb->proto_switch_on| p_cb->proto_switch_off| p_cb->proto_battery_off |
   1475                 p_cb->aid_entries)
   1476             {
   1477                 /* this NFCEE still has configuration when deactivated. clear the configuration */
   1478                 nfa_ee_cb.ee_cfged  &= ~nfa_ee_ecb_to_mask(p_cb);
   1479                 nfa_ee_cb.ee_cfg_sts|= NFA_EE_STS_CHANGED_ROUTING;
   1480                 NFA_TRACE_DEBUG0("deactivating/still configured. Force update");
   1481             }
   1482             p_cb->tech_switch_on    = p_cb->tech_switch_off = p_cb->tech_battery_off    = 0;
   1483             p_cb->proto_switch_on   = p_cb->proto_switch_off= p_cb->proto_battery_off   = 0;
   1484             p_cb->aid_entries       = 0;
   1485             p_cb->ee_status = NFC_NFCEE_STATUS_INACTIVE;
   1486         }
   1487     }
   1488     NFA_TRACE_DEBUG4 ("status:%d ecb_flags  :0x%02x ee_cfged:0x%02x ee_status:%d",
   1489         p_rsp->status, p_cb->ecb_flags  , nfa_ee_cb.ee_cfged, p_cb->ee_status);
   1490     if (p_cb->ecb_flags   & NFA_EE_ECB_FLAGS_RESTORE)
   1491     {
   1492         if (p_cb->conn_st == NFA_EE_CONN_ST_CONN)
   1493         {
   1494             /* NFA_HCI module handles restoring configurations for HCI access */
   1495             if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS)
   1496             {
   1497                 NFC_ConnCreate(NCI_DEST_TYPE_NFCEE, p_cb->nfcee_id,  p_cb->use_interface, nfa_ee_conn_cback);
   1498             }
   1499         }
   1500         else
   1501         {
   1502             p_cb->ecb_flags   &= ~NFA_EE_ECB_FLAGS_RESTORE;
   1503             nfa_ee_check_restore_complete();
   1504         }
   1505     }
   1506     else
   1507     {
   1508         mode_set.status     = p_rsp->status;
   1509         mode_set.ee_handle  = (tNFA_HANDLE)p_rsp->nfcee_id | NFA_HANDLE_GROUP_EE;
   1510         mode_set.ee_status  = p_cb->ee_status;
   1511 
   1512         nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_MODE_SET_EVT, (tNFA_EE_CBACK_DATA *)&mode_set);
   1513 
   1514         if ((p_cb->ee_status == NFC_NFCEE_STATUS_INACTIVE)
   1515             || (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE))
   1516         {
   1517             /* Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE */
   1518             nfa_ee_report_discover_req_evt();
   1519         }
   1520     }
   1521 }
   1522 
   1523 /*******************************************************************************
   1524 **
   1525 ** Function         nfa_ee_report_update_evt
   1526 **
   1527 ** Description      Check if need to report NFA_EE_UPDATED_EVT
   1528 **
   1529 ** Returns          void
   1530 **
   1531 *******************************************************************************/
   1532 void nfa_ee_report_update_evt (void)
   1533 {
   1534     tNFA_EE_CBACK_DATA  evt_data;
   1535 
   1536     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);
   1537     if (nfa_ee_cb.wait_rsp == 0)
   1538     {
   1539         nfa_ee_cb.ee_wait_evt &= ~NFA_EE_WAIT_UPDATE_RSP;
   1540 
   1541         if (nfa_ee_cb.ee_wait_evt & NFA_EE_WAIT_UPDATE)
   1542         {
   1543             nfa_ee_cb.ee_wait_evt &= ~NFA_EE_WAIT_UPDATE;
   1544             /* finished updating NFCC; report NFA_EE_UPDATED_EVT now */
   1545             evt_data.status       = NFA_STATUS_OK;
   1546             nfa_ee_report_event (NULL, NFA_EE_UPDATED_EVT, &evt_data);
   1547         }
   1548     }
   1549 }
   1550 
   1551 /*******************************************************************************
   1552 **
   1553 ** Function         nfa_ee_nci_wait_rsp
   1554 **
   1555 ** Description      Process the result for NCI response
   1556 **
   1557 ** Returns          void
   1558 **
   1559 *******************************************************************************/
   1560 void nfa_ee_nci_wait_rsp(tNFA_EE_MSG *p_data)
   1561 {
   1562     tNFA_EE_NCI_WAIT_RSP *p_rsp = &p_data->wait_rsp;
   1563 
   1564     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);
   1565     if (nfa_ee_cb.wait_rsp)
   1566     {
   1567         if (p_rsp->opcode == NCI_MSG_RF_SET_ROUTING)
   1568             nfa_ee_cb.wait_rsp--;
   1569     }
   1570     nfa_ee_report_update_evt ();
   1571 }
   1572 
   1573 /*******************************************************************************
   1574 **
   1575 ** Function         nfa_ee_nci_conn
   1576 **
   1577 ** Description      process the connection callback events
   1578 **
   1579 ** Returns          void
   1580 **
   1581 *******************************************************************************/
   1582 void nfa_ee_nci_conn(tNFA_EE_MSG *p_data)
   1583 {
   1584     tNFA_EE_ECB      *p_cb;
   1585     tNFA_EE_NCI_CONN    *p_cbk   = &p_data->conn;
   1586     tNFC_CONN           *p_conn  = p_data->conn.p_data;
   1587     BT_HDR              *p_pkt   = NULL;
   1588     tNFA_EE_CBACK_DATA  evt_data = {0};
   1589     tNFA_EE_EVT         event    = NFA_EE_INVALID;
   1590     tNFA_EE_CBACK       *p_cback = NULL;
   1591 
   1592     if (p_cbk->event == NFC_CONN_CREATE_CEVT)
   1593     {
   1594         p_cb = nfa_ee_find_ecb (p_cbk->p_data->conn_create.id);
   1595     }
   1596     else
   1597     {
   1598         p_cb = nfa_ee_find_ecb_by_conn_id (p_cbk->conn_id);
   1599         if (p_cbk->event == NFC_DATA_CEVT)
   1600             p_pkt = p_conn->data.p_data;
   1601     }
   1602 
   1603     if (p_cb)
   1604     {
   1605         p_cback         = p_cb->p_ee_cback;
   1606         evt_data.handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
   1607         switch (p_cbk->event)
   1608         {
   1609         case NFC_CONN_CREATE_CEVT:
   1610             if (p_conn->conn_create.status == NFC_STATUS_OK)
   1611             {
   1612                 p_cb->conn_id = p_cbk->conn_id;
   1613                 p_cb->conn_st = NFA_EE_CONN_ST_CONN;
   1614             }
   1615             else
   1616             {
   1617                 p_cb->conn_st = NFA_EE_CONN_ST_NONE;
   1618             }
   1619             if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_RESTORE)
   1620             {
   1621                 p_cb->ecb_flags &= ~NFA_EE_ECB_FLAGS_RESTORE;
   1622                 nfa_ee_check_restore_complete();
   1623             }
   1624             else
   1625             {
   1626                 evt_data.connect.status       = p_conn->conn_create.status;
   1627                 evt_data.connect.ee_interface = p_cb->use_interface;
   1628                 event = NFA_EE_CONNECT_EVT;
   1629             }
   1630             break;
   1631 
   1632         case NFC_CONN_CLOSE_CEVT:
   1633             if (p_cb->conn_st != NFA_EE_CONN_ST_DISC)
   1634                 event = NFA_EE_DISCONNECT_EVT;
   1635             p_cb->conn_st    = NFA_EE_CONN_ST_NONE;
   1636             p_cb->p_ee_cback = NULL;
   1637             p_cb->conn_id    = 0;
   1638             if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_DISABLING)
   1639             {
   1640                 if (nfa_ee_cb.ee_flags & NFA_EE_FLAG_WAIT_DISCONN)
   1641                 {
   1642                     if (nfa_ee_cb.num_ee_expecting)
   1643                     {
   1644                         nfa_ee_cb.num_ee_expecting--;
   1645                     }
   1646                 }
   1647                 if (nfa_ee_cb.num_ee_expecting == 0)
   1648                 {
   1649                     nfa_ee_cb.ee_flags &= ~NFA_EE_FLAG_WAIT_DISCONN;
   1650                     nfa_ee_check_disable();
   1651                 }
   1652             }
   1653             break;
   1654 
   1655         case NFC_DATA_CEVT:
   1656             if (p_cb->conn_st == NFA_EE_CONN_ST_CONN)
   1657             {
   1658                 /* report data event only in connected state */
   1659                 if (p_cb->p_ee_cback && p_pkt)
   1660                 {
   1661                     evt_data.data.len   = p_pkt->len;
   1662                     evt_data.data.p_buf = (UINT8 *)(p_pkt+1) + p_pkt->offset;
   1663                     event               = NFA_EE_DATA_EVT;
   1664                     p_pkt               = NULL; /* so this function does not free this GKI buffer */
   1665                 }
   1666             }
   1667             break;
   1668         }
   1669 
   1670         if ((event != NFA_EE_INVALID) && (p_cback))
   1671             (*p_cback)(event, &evt_data);
   1672     }
   1673     if (p_pkt)
   1674         GKI_freebuf (p_pkt);
   1675 }
   1676 
   1677 
   1678 /*******************************************************************************
   1679 **
   1680 ** Function         nfa_ee_nci_action_ntf
   1681 **
   1682 ** Description      process the NFCEE action callback event
   1683 **
   1684 ** Returns          void
   1685 **
   1686 *******************************************************************************/
   1687 void nfa_ee_nci_action_ntf(tNFA_EE_MSG *p_data)
   1688 {
   1689     tNFC_EE_ACTION_REVT *p_cbk = p_data->act.p_data;
   1690     tNFA_EE_ACTION      evt_data;
   1691 
   1692     evt_data.ee_handle  = (tNFA_HANDLE)p_cbk->nfcee_id | NFA_HANDLE_GROUP_EE;
   1693     evt_data.trigger    = p_cbk->act_data.trigger;
   1694     memcpy (&(evt_data.param), &(p_cbk->act_data.param), sizeof (tNFA_EE_ACTION_PARAM));
   1695     nfa_ee_report_event(NULL, NFA_EE_ACTION_EVT, (tNFA_EE_CBACK_DATA *)&evt_data);
   1696 }
   1697 
   1698 /*******************************************************************************
   1699 **
   1700 ** Function         nfa_ee_nci_disc_req_ntf
   1701 **
   1702 ** Description      process the NFCEE discover request callback event
   1703 **
   1704 ** Returns          void
   1705 **
   1706 *******************************************************************************/
   1707 void nfa_ee_nci_disc_req_ntf(tNFA_EE_MSG *p_data)
   1708 {
   1709     tNFC_EE_DISCOVER_REQ_REVT   *p_cbk = p_data->disc_req.p_data;
   1710     tNFA_HANDLE         ee_handle;
   1711     tNFA_EE_ECB         *p_cb = NULL;
   1712     UINT8               report_ntf = 0;
   1713     UINT8 xx;
   1714 
   1715     NFA_TRACE_DEBUG2 ("nfa_ee_nci_disc_req_ntf () num_info: %d cur_ee:%d", p_cbk->num_info, nfa_ee_cb.cur_ee );
   1716 
   1717     for (xx = 0; xx < p_cbk->num_info; xx++)
   1718     {
   1719         ee_handle = NFA_HANDLE_GROUP_EE|p_cbk->info[xx].nfcee_id;
   1720 
   1721         p_cb = nfa_ee_find_ecb (p_cbk->info[xx].nfcee_id);
   1722         if (!p_cb)
   1723         {
   1724             NFA_TRACE_DEBUG1 ("Cannot find cb for NFCEE: 0x%x", p_cbk->info[xx].nfcee_id);
   1725             p_cb = nfa_ee_find_ecb (NFA_EE_INVALID);
   1726             if (p_cb)
   1727             {
   1728                 p_cb->nfcee_id   = p_cbk->info[xx].nfcee_id;
   1729                 p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_ORDER;
   1730             }
   1731             else
   1732             {
   1733                 NFA_TRACE_ERROR1 ("Cannot allocate cb for NFCEE: 0x%x", p_cbk->info[xx].nfcee_id);
   1734                 continue;
   1735             }
   1736         }
   1737         else
   1738         {
   1739             report_ntf  |= nfa_ee_ecb_to_mask (p_cb);
   1740         }
   1741 
   1742         p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_DISC_REQ;
   1743         if (p_cbk->info[xx].op == NFC_EE_DISC_OP_ADD)
   1744         {
   1745             if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_A)
   1746             {
   1747                 p_cb->la_protocol = p_cbk->info[xx].protocol;
   1748             }
   1749             else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B)
   1750             {
   1751                 p_cb->lb_protocol = p_cbk->info[xx].protocol;
   1752             }
   1753             else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_F)
   1754             {
   1755                 p_cb->lf_protocol = p_cbk->info[xx].protocol;
   1756             }
   1757             else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)
   1758             {
   1759                 p_cb->lbp_protocol = p_cbk->info[xx].protocol;
   1760             }
   1761             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",
   1762                 p_cb->nfcee_id, p_cb->ee_status, p_cb->ecb_flags,
   1763                 p_cb->la_protocol, p_cb->lb_protocol, p_cb->lf_protocol);
   1764         }
   1765         else
   1766         {
   1767             if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_A)
   1768             {
   1769                 p_cb->la_protocol = 0;
   1770             }
   1771             else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B)
   1772             {
   1773                 p_cb->lb_protocol = 0;
   1774             }
   1775             else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_F)
   1776             {
   1777                 p_cb->lf_protocol = 0;
   1778             }
   1779             else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)
   1780             {
   1781                 p_cb->lbp_protocol = 0;
   1782             }
   1783         }
   1784     }
   1785 
   1786 
   1787     /* Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE */
   1788     if (report_ntf)
   1789         nfa_ee_report_discover_req_evt();
   1790 
   1791 }
   1792 
   1793 /*******************************************************************************
   1794 **
   1795 ** Function         nfa_ee_is_active
   1796 **
   1797 ** Description      Check if the given NFCEE is active
   1798 **
   1799 ** Returns          TRUE if the given NFCEE is active
   1800 **
   1801 *******************************************************************************/
   1802 BOOLEAN nfa_ee_is_active (tNFA_HANDLE nfcee_id)
   1803 {
   1804     BOOLEAN is_active = FALSE;
   1805     int     xx;
   1806     tNFA_EE_ECB  *p_cb = nfa_ee_cb.ecb;
   1807 
   1808     if ((NFA_HANDLE_GROUP_MASK & nfcee_id) == NFA_HANDLE_GROUP_EE)
   1809         nfcee_id    &= NFA_HANDLE_MASK;
   1810 
   1811     /* compose output */
   1812     for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
   1813     {
   1814         if ((tNFA_HANDLE)p_cb->nfcee_id == nfcee_id)
   1815         {
   1816             if (p_cb->ee_status == NFA_EE_STATUS_ACTIVE)
   1817             {
   1818                 is_active = TRUE;
   1819             }
   1820             break;
   1821         }
   1822     }
   1823     return is_active;
   1824 }
   1825 
   1826 /*******************************************************************************
   1827 **
   1828 ** Function         nfa_ee_get_tech_route
   1829 **
   1830 ** Description      Given a power state, find the technology routing destination.
   1831 **                  The result is filled in the given p_handles
   1832 **                  in the order of A, B, F, Bprime
   1833 **
   1834 ** Returns          None
   1835 **
   1836 *******************************************************************************/
   1837 void nfa_ee_get_tech_route (UINT8 power_state, UINT8 *p_handles)
   1838 {
   1839     int     xx, yy;
   1840     tNFA_EE_ECB *p_cb;
   1841     UINT8   tech_mask_list[NFA_EE_MAX_TECH_ROUTE] =
   1842     {
   1843         NFA_TECHNOLOGY_MASK_A,
   1844         NFA_TECHNOLOGY_MASK_B,
   1845         NFA_TECHNOLOGY_MASK_F,
   1846         NFA_TECHNOLOGY_MASK_B_PRIME
   1847     };
   1848 
   1849     NFA_TRACE_DEBUG1("nfa_ee_get_tech_route(): %d", power_state);
   1850 
   1851     for (xx = 0; xx < NFA_EE_MAX_TECH_ROUTE; xx++)
   1852     {
   1853         p_handles[xx] = NFC_DH_ID;
   1854         p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
   1855         for (yy = 0; yy < nfa_ee_cb.cur_ee; yy++, p_cb--)
   1856         {
   1857             if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE)
   1858             {
   1859                 switch (power_state)
   1860                 {
   1861                 case NFA_EE_PWR_STATE_ON:
   1862                     if (p_cb->tech_switch_on & tech_mask_list[xx])
   1863                         p_handles[xx] = p_cb->nfcee_id;
   1864                     break;
   1865                 case NFA_EE_PWR_STATE_SWITCH_OFF:
   1866                     if (p_cb->tech_switch_off & tech_mask_list[xx])
   1867                         p_handles[xx] = p_cb->nfcee_id;
   1868                     break;
   1869                 case NFA_EE_PWR_STATE_BATT_OFF:
   1870                     if (p_cb->tech_battery_off & tech_mask_list[xx])
   1871                         p_handles[xx] = p_cb->nfcee_id;
   1872                     break;
   1873                 }
   1874             }
   1875         }
   1876     }
   1877     NFA_TRACE_DEBUG4("0x%x, 0x%x, 0x%x, 0x%x", p_handles[0], p_handles[1], p_handles[2], p_handles[3]);
   1878 }
   1879 
   1880 /*******************************************************************************
   1881 **
   1882 ** Function         nfa_ee_check_set_routing
   1883 **
   1884 ** Description      If the new size exceeds the capacity of next block,
   1885 **                  send the routing command now and reset the related parameters
   1886 **
   1887 ** Returns          void
   1888 **
   1889 *******************************************************************************/
   1890 void nfa_ee_check_set_routing(UINT16 new_size, int *p_max_len, UINT8 *p, int *p_cur_offset)
   1891 {
   1892     UINT8   max_tlv = (UINT8)((*p_max_len > NFA_EE_ROUT_MAX_TLV_SIZE)?NFA_EE_ROUT_MAX_TLV_SIZE:*p_max_len);
   1893     tNFA_STATUS status = NFA_STATUS_OK;
   1894 
   1895     if (new_size + *p_cur_offset > max_tlv)
   1896     {
   1897         if (NFC_SetRouting(TRUE, *p, *p_cur_offset, p + 1) == NFA_STATUS_OK)
   1898         {
   1899             nfa_ee_cb.wait_rsp++;
   1900         }
   1901         /* after the routing command is sent, re-use the same buffer to send the next routing command.
   1902          * reset the related parameters */
   1903         if (*p_max_len > *p_cur_offset)
   1904             *p_max_len     -= *p_cur_offset;/* the max is reduced */
   1905         else
   1906             *p_max_len      = 0;
   1907         *p_cur_offset   = 0;                /* nothing is in queue any more */
   1908         *p              = 0;                /* num_tlv=0 */
   1909     }
   1910 }
   1911 
   1912 /*******************************************************************************
   1913 **
   1914 ** Function         nfa_ee_route_add_one_ecb
   1915 **
   1916 ** Description      Add the routing entries for one NFCEE/DH
   1917 **
   1918 ** Returns          NFA_STATUS_OK, if ok to continue
   1919 **
   1920 *******************************************************************************/
   1921 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)
   1922 {
   1923     UINT8   *p, *pa;
   1924     UINT16  tlv_size;
   1925     UINT8   num_tlv, len;
   1926     int     xx;
   1927     int     start_offset;
   1928     UINT8   power_cfg = 0;
   1929     UINT8   *pp = ps + *p_cur_offset;
   1930     UINT8   entry_size;
   1931     UINT8   max_tlv;
   1932     UINT8   *p_start;
   1933     UINT8   new_size;
   1934     tNFA_STATUS status = NFA_STATUS_OK;
   1935 
   1936     nfa_ee_check_set_routing (p_cb->size_mask, p_max_len, ps, p_cur_offset);
   1937     max_tlv = (UINT8)((*p_max_len > NFA_EE_ROUT_MAX_TLV_SIZE)?NFA_EE_ROUT_MAX_TLV_SIZE:*p_max_len);
   1938     /* use the first byte of the buffer (ps) to keep the num_tlv */
   1939     num_tlv  = *ps;
   1940     NFA_TRACE_DEBUG5 ("nfa_ee_route_add_one_ecb max_len:%d, max_tlv:%d, cur_offset:%d, more:%d, num_tlv:%d",
   1941         *p_max_len, max_tlv, *p_cur_offset, more, num_tlv);
   1942     pp       = ps + 1 + *p_cur_offset;
   1943     p        = pp;
   1944     tlv_size = (UINT8)*p_cur_offset;
   1945     /* add the Technology based routing */
   1946     for (xx = 0; xx < NFA_EE_NUM_TECH; xx++)
   1947     {
   1948         power_cfg = 0;
   1949         if (p_cb->tech_switch_on & nfa_ee_tech_mask_list[xx])
   1950             power_cfg |= NCI_ROUTE_PWR_STATE_ON;
   1951         if (p_cb->tech_switch_off & nfa_ee_tech_mask_list[xx])
   1952             power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
   1953         if (p_cb->tech_battery_off & nfa_ee_tech_mask_list[xx])
   1954             power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
   1955         if (power_cfg)
   1956         {
   1957             *pp++   = NFC_ROUTE_TAG_TECH;
   1958             *pp++   = 3;
   1959             *pp++   = p_cb->nfcee_id;
   1960             *pp++   = power_cfg;
   1961             *pp++   = nfa_ee_tech_list[xx];
   1962             num_tlv++;
   1963             if (power_cfg != NCI_ROUTE_PWR_STATE_ON)
   1964                 nfa_ee_cb.ee_cfged  |= NFA_EE_CFGED_OFF_ROUTING;
   1965         }
   1966     }
   1967 
   1968     /* add the Protocol based routing */
   1969     for (xx = 0; xx < NFA_EE_NUM_PROTO; xx++)
   1970     {
   1971         power_cfg = 0;
   1972         if (p_cb->proto_switch_on & nfa_ee_proto_mask_list[xx])
   1973             power_cfg |= NCI_ROUTE_PWR_STATE_ON;
   1974         if (p_cb->proto_switch_off & nfa_ee_proto_mask_list[xx])
   1975             power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
   1976         if (p_cb->proto_battery_off & nfa_ee_proto_mask_list[xx])
   1977             power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
   1978         if (power_cfg)
   1979         {
   1980             *pp++   = NFC_ROUTE_TAG_PROTO;
   1981             *pp++   = 3;
   1982             *pp++   = p_cb->nfcee_id;
   1983             *pp++   = power_cfg;
   1984             *pp++   = nfa_ee_proto_list[xx];
   1985             num_tlv++;
   1986             if (power_cfg != NCI_ROUTE_PWR_STATE_ON)
   1987                 nfa_ee_cb.ee_cfged  |= NFA_EE_CFGED_OFF_ROUTING;
   1988         }
   1989     }
   1990 
   1991     /* add NFC-DEP routing to HOST */
   1992     if (p_cb->nfcee_id == NFC_DH_ID)
   1993     {
   1994         *pp++   = NFC_ROUTE_TAG_PROTO;
   1995         *pp++   = 3;
   1996         *pp++   = NFC_DH_ID;
   1997         *pp++   = NCI_ROUTE_PWR_STATE_ON;
   1998         *pp++   = NFC_PROTOCOL_NFC_DEP;
   1999         num_tlv++;
   2000     }
   2001 
   2002     /* update the num_tlv and current offset */
   2003     entry_size       = (UINT8)(pp - p);
   2004     *p_cur_offset   += entry_size;
   2005     *ps              = num_tlv;
   2006     /* add the AID routing */
   2007     if (p_cb->aid_entries)
   2008     {
   2009         start_offset = 0;
   2010         for (xx = 0; xx < p_cb->aid_entries; xx++)
   2011         {
   2012             p_start     = pp; /* rememebr the beginning of this AID routing entry, just in case we need to put it in next command */
   2013             /* add one AID entry */
   2014             if (p_cb->aid_rt_info[xx] & NFA_EE_AE_ROUTE)
   2015             {
   2016                 num_tlv++;
   2017                 pa      = &p_cb->aid_cfg[start_offset];
   2018                 pa ++; /* EMV tag */
   2019                 len     = *pa++; /* aid_len */
   2020                 *pp++   = NFC_ROUTE_TAG_AID;
   2021                 *pp++   = len + 2;
   2022                 *pp++   = p_cb->nfcee_id;
   2023                 *pp++   = p_cb->aid_pwr_cfg[xx];
   2024                 /* copy the AID */
   2025                 memcpy(pp, pa, len);
   2026                 pp     += len;
   2027             }
   2028             start_offset += p_cb->aid_len[xx];
   2029             new_size        = (UINT8)(pp - p_start);
   2030             nfa_ee_check_set_routing(new_size, p_max_len, ps, p_cur_offset);
   2031             if (*ps == 0)
   2032             {
   2033                 /* just sent routing command, update local */
   2034                 *ps      = 1;
   2035                 num_tlv  = *ps;
   2036                 *p_cur_offset = new_size;
   2037                 pp       = ps + 1;
   2038                 p        = pp;
   2039                 tlv_size = (UINT8)*p_cur_offset;
   2040                 max_tlv  = (UINT8)((*p_max_len > NFA_EE_ROUT_MAX_TLV_SIZE)?NFA_EE_ROUT_MAX_TLV_SIZE:*p_max_len);
   2041                 memcpy (p, p_start, new_size);
   2042                 pp      += new_size;
   2043             }
   2044             else
   2045             {
   2046                 /* add the new entry */
   2047                 *ps              = num_tlv;
   2048                 *p_cur_offset   += new_size;
   2049             }
   2050         }
   2051     }
   2052 
   2053     tlv_size   = nfa_ee_total_lmrt_size();
   2054     if (tlv_size)
   2055     {
   2056         nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
   2057     }
   2058     if (p_cb->ecb_flags   & NFA_EE_ECB_FLAGS_ROUTING)
   2059     {
   2060         nfa_ee_cb.ee_cfg_sts   |= NFA_EE_STS_CHANGED_ROUTING;
   2061     }
   2062     NFA_TRACE_DEBUG2 ("ee_cfg_sts:0x%02x lmrt_size:%d", nfa_ee_cb.ee_cfg_sts, tlv_size);
   2063 
   2064     if (more == FALSE)
   2065     {
   2066         /* last entry. update routing table now */
   2067         if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_CHANGED_ROUTING)
   2068         {
   2069             if (tlv_size)
   2070             {
   2071                 nfa_ee_cb.ee_cfg_sts       |= NFA_EE_STS_PREV_ROUTING;
   2072             }
   2073             else
   2074             {
   2075                 nfa_ee_cb.ee_cfg_sts       &= ~NFA_EE_STS_PREV_ROUTING;
   2076             }
   2077             NFA_TRACE_DEBUG2 ("nfa_ee_route_add_one_ecb: set routing num_tlv:%d tlv_size:%d", num_tlv, tlv_size);
   2078             if (NFC_SetRouting(more, num_tlv, (UINT8)(*p_cur_offset), ps + 1) == NFA_STATUS_OK)
   2079             {
   2080                 nfa_ee_cb.wait_rsp++;
   2081             }
   2082         }
   2083         else if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_PREV_ROUTING)
   2084         {
   2085             if (tlv_size == 0)
   2086             {
   2087                 nfa_ee_cb.ee_cfg_sts       &= ~NFA_EE_STS_PREV_ROUTING;
   2088                 /* indicated routing is configured to NFCC */
   2089                 nfa_ee_cb.ee_cfg_sts       |= NFA_EE_STS_CHANGED_ROUTING;
   2090                 if (NFC_SetRouting(more, 0, 0, ps + 1) == NFA_STATUS_OK)
   2091                 {
   2092                     nfa_ee_cb.wait_rsp++;
   2093                 }
   2094             }
   2095         }
   2096     }
   2097 
   2098     return status;
   2099 }
   2100 
   2101 
   2102 /*******************************************************************************
   2103 **
   2104 ** Function         nfa_ee_need_recfg
   2105 **
   2106 ** Description      Check if any API function to configure the routing table or
   2107 **                  VS is called since last update
   2108 **
   2109 **                  The algorithm for the NFCEE configuration handling is as follows:
   2110 **
   2111 **                  Each NFCEE_ID/DH has its own control block - tNFA_EE_ECB
   2112 **                  Each control block uses ecb_flags to keep track if an API
   2113 **                  that changes routing/VS is invoked.
   2114 **                  This ecb_flags is cleared at the end of nfa_ee_update_rout().
   2115 **
   2116 **                  nfa_ee_cb.ee_cfged is the bitmask of the control blocks with
   2117 **                  routing/VS configuration and NFA_EE_CFGED_UPDATE_NOW.
   2118 **                  nfa_ee_cb.ee_cfged is cleared and re-calculated at the end of
   2119 **                  nfa_ee_update_rout().
   2120 **
   2121 **                  nfa_ee_cb.ee_cfg_sts is used to check is any status is changed
   2122 **                  and the associated command is issued to NFCC.
   2123 **                  nfa_ee_cb.ee_cfg_sts is AND with NFA_EE_STS_PREV at the end of
   2124 **                  nfa_ee_update_rout() to clear the NFA_EE_STS_CHANGED bits
   2125 **                  (except NFA_EE_STS_CHANGED_CANNED_VS is cleared in nfa_ee_vs_cback)
   2126 **
   2127 ** Returns          TRUE if any configuration is changed
   2128 **
   2129 *******************************************************************************/
   2130 static BOOLEAN nfa_ee_need_recfg(void)
   2131 {
   2132     BOOLEAN needed = FALSE;
   2133     UINT32  xx;
   2134     tNFA_EE_ECB  *p_cb;
   2135     UINT8   mask;
   2136 
   2137     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);
   2138     /* if no routing/vs is configured, do not need to send the info to NFCC */
   2139     if (nfa_ee_cb.ee_cfged || nfa_ee_cb.ee_cfg_sts)
   2140     {
   2141         if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_CHANGED)
   2142         {
   2143             needed = TRUE;
   2144         }
   2145         else
   2146         {
   2147             p_cb = &nfa_ee_cb.ecb[NFA_EE_CB_4_DH];
   2148             mask = 1 << NFA_EE_CB_4_DH;
   2149             for (xx = 0; xx <= nfa_ee_cb.cur_ee; xx++)
   2150             {
   2151                 NFA_TRACE_DEBUG3("%d: ecb_flags  : 0x%02x, mask: 0x%02x", xx, p_cb->ecb_flags  , mask);
   2152                 if ((p_cb->ecb_flags  ) && (nfa_ee_cb.ee_cfged & mask))
   2153                 {
   2154                     needed = TRUE;
   2155                     break;
   2156                 }
   2157                 p_cb = &nfa_ee_cb.ecb[xx];
   2158                 mask = 1 << xx;
   2159             }
   2160         }
   2161     }
   2162 
   2163     return needed;
   2164 }
   2165 
   2166 /*******************************************************************************
   2167 **
   2168 ** Function         nfa_ee_rout_timeout
   2169 **
   2170 ** Description      Anytime VS or routing entries are changed,
   2171 **                  a 1 second timer is started. This function is called when
   2172 **                  the timer expires or NFA_EeUpdateNow() is called.
   2173 **
   2174 ** Returns          void
   2175 **
   2176 *******************************************************************************/
   2177 void nfa_ee_rout_timeout(tNFA_EE_MSG *p_data)
   2178 {
   2179     UINT8               ee_cfged = nfa_ee_cb.ee_cfged;
   2180 
   2181     NFA_TRACE_DEBUG0("nfa_ee_rout_timeout()");
   2182     if (nfa_ee_need_recfg())
   2183     {
   2184         /* discovery is not started */
   2185         nfa_ee_update_rout();
   2186     }
   2187 
   2188     if (nfa_ee_cb.wait_rsp)
   2189         nfa_ee_cb.ee_wait_evt   |= NFA_EE_WAIT_UPDATE_RSP;
   2190     if (ee_cfged & NFA_EE_CFGED_UPDATE_NOW)
   2191     {
   2192         /* need to report NFA_EE_UPDATED_EVT when done updating NFCC */
   2193         nfa_ee_cb.ee_wait_evt   |= NFA_EE_WAIT_UPDATE;
   2194         if (!nfa_ee_cb.wait_rsp)
   2195         {
   2196             nfa_ee_report_update_evt();
   2197         }
   2198     }
   2199 }
   2200 
   2201 /*******************************************************************************
   2202 **
   2203 ** Function         nfa_ee_discv_timeout
   2204 **
   2205 ** Description
   2206 **
   2207 **
   2208 **
   2209 ** Returns          void
   2210 **
   2211 *******************************************************************************/
   2212 void nfa_ee_discv_timeout(tNFA_EE_MSG *p_data)
   2213 {
   2214     NFC_NfceeDiscover(FALSE);
   2215     if (nfa_ee_cb.p_enable_cback)
   2216         (*nfa_ee_cb.p_enable_cback)(NFA_EE_DISC_STS_OFF);
   2217 }
   2218 
   2219 /*******************************************************************************
   2220 **
   2221 ** Function         nfa_ee_lmrt_to_nfcc
   2222 **
   2223 ** Description      This function would set the listen mode routing table
   2224 **                  to NFCC.
   2225 **
   2226 ** Returns          void
   2227 **
   2228 *******************************************************************************/
   2229 void nfa_ee_lmrt_to_nfcc(tNFA_EE_MSG *p_data)
   2230 {
   2231     int xx;
   2232     tNFA_EE_ECB          *p_cb;
   2233     UINT8   *p = NULL;
   2234     BOOLEAN more = TRUE;
   2235     UINT8   last_active = NFA_EE_INVALID;
   2236     int     max_len, len;
   2237     tNFA_STATUS status = NFA_STATUS_FAILED;
   2238     int     cur_offset;
   2239     UINT8   max_tlv;
   2240 
   2241     /* update routing table: DH and the activated NFCEEs */
   2242     p = (UINT8 *)GKI_getbuf(NFA_EE_ROUT_BUF_SIZE);
   2243     if (p == NULL)
   2244     {
   2245         NFA_TRACE_ERROR0 ("nfa_ee_lmrt_to_nfcc() no buffer to send routing info.");
   2246         nfa_ee_report_event( NULL, NFA_EE_NO_MEM_ERR_EVT, (tNFA_EE_CBACK_DATA *)&status);
   2247         return;
   2248     }
   2249 
   2250     /* find the last active NFCEE. */
   2251     p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
   2252     for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb--)
   2253     {
   2254         if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE)
   2255         {
   2256             if (last_active == NFA_EE_INVALID)
   2257             {
   2258                 last_active = p_cb->nfcee_id;
   2259                 NFA_TRACE_DEBUG1 ("last_active: 0x%x", last_active);
   2260             }
   2261         }
   2262     }
   2263     if (last_active == NFA_EE_INVALID)
   2264     {
   2265         more = FALSE;
   2266     }
   2267 
   2268     /* add the routing for DH first */
   2269     status  = NFA_STATUS_OK;
   2270     max_len = NFC_GetLmrtSize();
   2271     max_tlv = (UINT8)((max_len > NFA_EE_ROUT_MAX_TLV_SIZE)?NFA_EE_ROUT_MAX_TLV_SIZE:max_len);
   2272     cur_offset  = 0;
   2273     /* use the first byte of the buffer (p) to keep the num_tlv */
   2274     *p          = 0;
   2275     status = nfa_ee_route_add_one_ecb(&nfa_ee_cb.ecb[NFA_EE_CB_4_DH], &max_len, more, p, &cur_offset);
   2276 
   2277     /* add only what is supported by NFCC. report overflow */
   2278     if (status == NFA_STATUS_OK)
   2279     {
   2280         /* add the routing for NFCEEs */
   2281         p_cb = &nfa_ee_cb.ecb[0];
   2282         for (xx = 0; (xx < nfa_ee_cb.cur_ee) && more; xx++, p_cb++)
   2283         {
   2284             len = 0;
   2285             if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE)
   2286             {
   2287                 NFA_TRACE_DEBUG2 ("nfcee_id:0x%x, last_active: 0x%x", p_cb->nfcee_id, last_active);
   2288                 if (last_active == p_cb->nfcee_id)
   2289                     more = FALSE;
   2290                 status = nfa_ee_route_add_one_ecb(p_cb, &max_len, more, p, &cur_offset);
   2291                 if (status != NFA_STATUS_OK)
   2292                 {
   2293                     more    = FALSE;
   2294                 }
   2295             }
   2296         }
   2297     }
   2298     if (status != NFA_STATUS_OK)
   2299     {
   2300         nfa_ee_report_event( NULL, NFA_EE_ROUT_ERR_EVT, (tNFA_EE_CBACK_DATA *)&status);
   2301     }
   2302     GKI_freebuf(p);
   2303 }
   2304 
   2305 /*******************************************************************************
   2306 **
   2307 ** Function         nfa_ee_update_rout
   2308 **
   2309 ** Description      This function would set the VS and listen mode routing table
   2310 **                  to NFCC.
   2311 **
   2312 ** Returns          void
   2313 **
   2314 *******************************************************************************/
   2315 void nfa_ee_update_rout(void)
   2316 {
   2317     int xx;
   2318     tNFA_EE_ECB          *p_cb;
   2319     UINT8   mask;
   2320     BT_HDR  msg;
   2321 
   2322     NFA_TRACE_DEBUG1 ("nfa_ee_update_rout ee_cfg_sts:0x%02x", nfa_ee_cb.ee_cfg_sts);
   2323 
   2324     /* use action function to send routing and VS configuration to NFCC */
   2325     msg.event = NFA_EE_CFG_TO_NFCC_EVT;
   2326     nfa_ee_evt_hdlr (&msg);
   2327 
   2328     /* all configuration is updated to NFCC, clear the status mask */
   2329     nfa_ee_cb.ee_cfg_sts   &= NFA_EE_STS_PREV;
   2330     nfa_ee_cb.ee_cfged  = 0;
   2331     p_cb                = &nfa_ee_cb.ecb[0];
   2332     for (xx = 0; xx < NFA_EE_NUM_ECBS; xx++, p_cb++)
   2333     {
   2334         p_cb->ecb_flags     = 0;
   2335         mask                = (1 << xx);
   2336         if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off |
   2337             p_cb->proto_switch_on| p_cb->proto_switch_off| p_cb->proto_battery_off |
   2338             p_cb->aid_entries)
   2339         {
   2340             /* this entry has routing configuration. mark it configured */
   2341             nfa_ee_cb.ee_cfged  |= mask;
   2342         }
   2343     }
   2344     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);
   2345 }
   2346 
   2347 
   2348