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