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