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