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