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