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