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