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