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