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