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