nfa_ee_act.c revision 63f80ce896f0f8c203191b4e44e038fecb6be02a
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);
71static void nfa_ee_report_discover_req_evt(void);
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        else if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ORDER)
937        {
938            nfa_ee_cb.cur_ee++;
939            notify_new_ee = TRUE;
940        }
941        break;
942
943    case NFA_EE_EM_STATE_RESTORING:
944        p_cb = nfa_ee_find_ecb (p_ee->nfcee_id);
945        if (p_cb == NULL)
946        {
947            /* the NFCEE ID is not in the last NFCEE discovery
948             * maybe it's a new one */
949            p_cb = nfa_ee_find_ecb (NFA_EE_INVALID);
950            if (p_cb)
951            {
952                nfa_ee_cb.cur_ee++;
953                notify_new_ee = TRUE;
954            }
955        }
956        if (nfa_ee_cb.num_ee_expecting == 0)
957        {
958            /* notify init_done callback */
959            notify_enable_done = TRUE;
960            if (nfa_ee_restore_ntf_done())
961            {
962                nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
963            }
964        }
965        break;
966    }
967    NFA_TRACE_DEBUG1 ("nfa_ee_nci_disc_ntf cur_ee:%d", nfa_ee_cb.cur_ee);
968
969    if (p_cb)
970    {
971        p_cb->nfcee_id      = p_ee->nfcee_id;
972        p_cb->ee_status     = p_ee->ee_status;
973        p_cb->num_interface = p_ee->num_interface;
974        memcpy(p_cb->ee_interface, p_ee->ee_interface, p_ee->num_interface);
975        p_cb->num_tlvs      = p_ee->num_tlvs;
976        memcpy(p_cb->ee_tlv, p_ee->ee_tlv, p_ee->num_tlvs * sizeof(tNFA_EE_TLV));
977
978        if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_RESTORING)
979        {
980            /* NCI spec says: An NFCEE_DISCOVER_NTF that contains a Protocol type of "HCI Access"
981             * SHALL NOT contain any other additional Protocol
982             * i.e. check only first supported NFCEE interface is HCI access */
983            /* NFA_HCI module handles restoring configurations for HCI access */
984            if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS)
985            {
986                if ((nfa_ee_cb.ee_flags & NFA_EE_FLAG_WAIT_HCI) == 0)
987                {
988                    nfa_ee_restore_one_ecb (p_cb);
989                }
990                /* else wait for NFA-HCI module to restore the HCI network information before enabling the NFCEE */
991            }
992        }
993
994        if ((nfa_ee_cb.p_ee_disc_cback == NULL) && (notify_new_ee == TRUE))
995        {
996            if (nfa_dm_is_active() && (p_cb->ee_status != NFA_EE_STATUS_REMOVED))
997            {
998                /* report this NFA_EE_NEW_EE_EVT only after NFA_ENABLE_EVT is reported */
999                p_info                  = &evt_data.new_ee;
1000                p_info->ee_handle       = NFA_HANDLE_GROUP_EE | (tNFA_HANDLE)p_cb->nfcee_id;
1001                p_info->ee_status       = p_cb->ee_status;
1002                p_info->num_interface   = p_cb->num_interface;
1003                p_info->num_tlvs        = p_cb->num_tlvs;
1004                memcpy(p_info->ee_interface, p_cb->ee_interface, p_cb->num_interface);
1005                memcpy(p_info->ee_tlv, p_cb->ee_tlv, p_cb->num_tlvs * sizeof(tNFA_EE_TLV));
1006                nfa_ee_report_event (NULL, NFA_EE_NEW_EE_EVT, &evt_data);
1007            }
1008        }
1009        else
1010            nfa_ee_report_disc_done(notify_enable_done);
1011
1012        if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ORDER)
1013        {
1014            p_cb->ecb_flags &= ~NFA_EE_ECB_FLAGS_ORDER;
1015            nfa_ee_report_discover_req_evt();
1016        }
1017    }
1018}
1019
1020/*******************************************************************************
1021**
1022** Function         nfa_ee_check_restore_complete
1023**
1024** Description      Check if restore the NFA-EE related configuration to the
1025**                  state prior to low power mode is complete.
1026**                  If complete, notify sys.
1027**
1028** Returns          void
1029**
1030*******************************************************************************/
1031static void nfa_ee_check_restore_complete(void)
1032{
1033    UINT32  xx;
1034    tNFA_EE_ECB     *p_cb;
1035    BOOLEAN         proc_complete = TRUE;
1036
1037    p_cb = nfa_ee_cb.ecb;
1038    for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
1039    {
1040        if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_RESTORE)
1041        {
1042            /* NFA_HCI module handles restoring configurations for HCI access.
1043             * ignore the restoring status for HCI Access */
1044            if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS)
1045            {
1046                proc_complete = FALSE;
1047                break;
1048            }
1049        }
1050    }
1051
1052    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);
1053    if (proc_complete)
1054    {
1055        /* update routing table when NFA_EE_ROUT_TIMEOUT_EVT is received */
1056        if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_PREV_ROUTING)
1057            nfa_ee_api_update_now(NULL);
1058
1059        nfa_ee_cb.em_state = NFA_EE_EM_STATE_INIT_DONE;
1060        nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_EE);
1061    }
1062}
1063
1064/*******************************************************************************
1065**
1066** Function         nfa_ee_report_discover_req_evt
1067**
1068** Description      Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE
1069**
1070** Returns          void
1071**
1072*******************************************************************************/
1073static void nfa_ee_report_discover_req_evt(void)
1074{
1075    tNFA_EE_DISCOVER_REQ    evt_data;
1076    tNFA_EE_DISCOVER_INFO   *p_info;
1077    UINT8                   xx;
1078    tNFA_EE_ECB  *p_cb = nfa_ee_cb.ecb;
1079
1080    /* if this is restoring NFCC */
1081    if (!nfa_dm_is_active ())
1082    {
1083        NFA_TRACE_DEBUG0 ("nfa_ee_report_discover_req_evt DM is not active");
1084        return;
1085    }
1086
1087    evt_data.num_ee = 0;
1088    p_cb            = nfa_ee_cb.ecb;
1089    p_info          = evt_data.ee_disc_info;
1090    for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
1091    {
1092        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))
1093        {
1094            continue;
1095        }
1096        p_info->la_protocol     = p_cb->la_protocol;
1097        p_info->lb_protocol     = p_cb->lb_protocol;
1098        p_info->lf_protocol     = p_cb->lf_protocol;
1099        p_info->lbp_protocol    = p_cb->lbp_protocol;
1100        evt_data.num_ee++;
1101        p_info++;
1102
1103        NFA_TRACE_DEBUG6 ("[%d] ee_handle:0x%x, listen protocol A:%d, B:%d, F:%d, BP:%d",
1104                          evt_data.num_ee, p_cb->nfcee_id,
1105                          p_cb->la_protocol, p_cb->lb_protocol, p_cb->lf_protocol, p_cb->lbp_protocol);
1106    }
1107
1108    evt_data.status     = NFA_STATUS_OK;
1109    nfa_ee_report_event(NULL, NFA_EE_DISCOVER_REQ_EVT, (tNFA_EE_CBACK_DATA *)&evt_data);
1110}
1111
1112/*******************************************************************************
1113**
1114** Function         nfa_ee_nci_mode_set_rsp
1115**
1116** Description      Process the result for NFCEE ModeSet response
1117**
1118** Returns          void
1119**
1120*******************************************************************************/
1121void nfa_ee_nci_mode_set_rsp(tNFA_EE_MSG *p_data)
1122{
1123    tNFA_EE_ECB *p_cb;
1124    tNFA_EE_MODE_SET    mode_set;
1125    tNFC_NFCEE_MODE_SET_REVT    *p_rsp = p_data->mode_set_rsp.p_data;
1126
1127    NFA_TRACE_DEBUG2 ("nfa_ee_nci_mode_set_rsp() handle:0x%02x mode:%d", p_rsp->nfcee_id, p_rsp->mode);
1128    p_cb = nfa_ee_find_ecb (p_rsp->nfcee_id);
1129    if (p_cb == NULL)
1130    {
1131        NFA_TRACE_ERROR1 ("nfa_ee_nci_mode_set_rsp() Can not find cb for handle:0x%02x", p_rsp->nfcee_id);
1132        return;
1133    }
1134
1135    /* update routing table and vs on mode change */
1136    nfa_ee_start_timer();
1137
1138    if (p_rsp->status == NFA_STATUS_OK)
1139    {
1140
1141        if (p_rsp->mode == NFA_EE_MD_ACTIVATE)
1142        {
1143            p_cb->ee_status = NFC_NFCEE_STATUS_ACTIVE;
1144        }
1145        else
1146        {
1147            if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off |
1148                p_cb->proto_switch_on| p_cb->proto_switch_off| p_cb->proto_battery_off |
1149                p_cb->aid_entries)
1150            {
1151                /* this NFCEE still has configuration when deactivated. clear the configuration */
1152                nfa_ee_cb.ee_cfged  &= ~nfa_ee_ecb_to_mask(p_cb);
1153                nfa_ee_cb.ee_cfg_sts|= NFA_EE_STS_CHANGED_ROUTING;
1154                NFA_TRACE_DEBUG0("deactivating/still configured. Force update");
1155            }
1156            p_cb->tech_switch_on    = p_cb->tech_switch_off = p_cb->tech_battery_off    = 0;
1157            p_cb->proto_switch_on   = p_cb->proto_switch_off= p_cb->proto_battery_off   = 0;
1158            p_cb->aid_entries       = 0;
1159            p_cb->ee_status = NFC_NFCEE_STATUS_INACTIVE;
1160        }
1161    }
1162    NFA_TRACE_DEBUG4 ("status:%d ecb_flags  :0x%02x ee_cfged:0x%02x ee_status:%d",
1163        p_rsp->status, p_cb->ecb_flags  , nfa_ee_cb.ee_cfged, p_cb->ee_status);
1164    if (p_cb->ecb_flags   & NFA_EE_ECB_FLAGS_RESTORE)
1165    {
1166        if (p_cb->conn_st == NFA_EE_CONN_ST_CONN)
1167        {
1168            /* NFA_HCI module handles restoring configurations for HCI access */
1169            if (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS)
1170            {
1171                NFC_ConnCreate(NCI_DEST_TYPE_NFCEE, p_cb->nfcee_id,  p_cb->use_interface, nfa_ee_conn_cback);
1172            }
1173        }
1174        else
1175        {
1176            p_cb->ecb_flags   &= ~NFA_EE_ECB_FLAGS_RESTORE;
1177            nfa_ee_check_restore_complete();
1178        }
1179    }
1180    else
1181    {
1182        mode_set.status     = p_rsp->status;
1183        mode_set.ee_handle  = (tNFA_HANDLE)p_rsp->nfcee_id | NFA_HANDLE_GROUP_EE;
1184        mode_set.ee_status  = p_cb->ee_status;
1185
1186        nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_MODE_SET_EVT, (tNFA_EE_CBACK_DATA *)&mode_set);
1187        if (p_cb->ee_status == NFC_NFCEE_STATUS_INACTIVE)
1188        {
1189            /* Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE */
1190            nfa_ee_report_discover_req_evt();
1191        }
1192    }
1193}
1194
1195/*******************************************************************************
1196**
1197** Function         nfa_ee_nci_conn
1198**
1199** Description      process the connection callback events
1200**
1201** Returns          void
1202**
1203*******************************************************************************/
1204void nfa_ee_nci_conn(tNFA_EE_MSG *p_data)
1205{
1206    tNFA_EE_ECB      *p_cb;
1207    tNFA_EE_NCI_CONN    *p_cbk   = &p_data->conn;
1208    tNFC_CONN           *p_conn  = p_data->conn.p_data;
1209    BT_HDR              *p_pkt   = NULL;
1210    tNFA_EE_CBACK_DATA  evt_data = {0};
1211    tNFA_EE_EVT         event    = NFA_EE_INVALID;
1212    tNFA_EE_CBACK       *p_cback = NULL;
1213
1214    if (p_cbk->event == NFC_CONN_CREATE_CEVT)
1215    {
1216        p_cb = nfa_ee_find_ecb (p_cbk->p_data->conn_create.id);
1217    }
1218    else
1219    {
1220        p_cb = nfa_ee_find_ecb_by_conn_id (p_cbk->conn_id);
1221        if (p_cbk->event == NFC_DATA_CEVT)
1222            p_pkt = p_conn->data.p_data;
1223    }
1224
1225    if (p_cb)
1226    {
1227        p_cback         = p_cb->p_ee_cback;
1228        evt_data.handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
1229        switch (p_cbk->event)
1230        {
1231        case NFC_CONN_CREATE_CEVT:
1232            if (p_conn->conn_create.status == NFC_STATUS_OK)
1233            {
1234                p_cb->conn_id = p_cbk->conn_id;
1235                p_cb->conn_st = NFA_EE_CONN_ST_CONN;
1236            }
1237            else
1238            {
1239                p_cb->conn_st = NFA_EE_CONN_ST_NONE;
1240            }
1241            if (p_cb->ecb_flags & NFA_EE_ECB_FLAGS_RESTORE)
1242            {
1243                p_cb->ecb_flags &= ~NFA_EE_ECB_FLAGS_RESTORE;
1244                nfa_ee_check_restore_complete();
1245            }
1246            else
1247            {
1248                evt_data.connect.status       = p_conn->conn_create.status;
1249                evt_data.connect.ee_interface = p_cb->use_interface;
1250                event = NFA_EE_CONNECT_EVT;
1251            }
1252            break;
1253
1254        case NFC_CONN_CLOSE_CEVT:
1255            if (p_cb->conn_st != NFA_EE_CONN_ST_DISC)
1256                event = NFA_EE_DISCONNECT_EVT;
1257            p_cb->conn_st    = NFA_EE_CONN_ST_NONE;
1258            p_cb->p_ee_cback = NULL;
1259            p_cb->conn_id    = 0;
1260            if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_DISABLING)
1261                nfa_ee_sys_disable();
1262            break;
1263
1264        case NFC_DATA_CEVT:
1265            if (p_cb->conn_st == NFA_EE_CONN_ST_CONN)
1266            {
1267                /* report data event only in connected state */
1268                if (p_cb->p_ee_cback && p_pkt)
1269                {
1270                    evt_data.data.len   = p_pkt->len;
1271                    evt_data.data.p_buf = (UINT8 *)(p_pkt+1) + p_pkt->offset;
1272                    event               = NFA_EE_DATA_EVT;
1273                    p_pkt               = NULL; /* so this function does not free this GKI buffer */
1274                }
1275            }
1276            break;
1277        }
1278
1279        if ((event != NFA_EE_INVALID) && (p_cback))
1280            (*p_cback)(event, &evt_data);
1281    }
1282    if (p_pkt)
1283        GKI_freebuf (p_pkt);
1284}
1285
1286
1287/*******************************************************************************
1288**
1289** Function         nfa_ee_nci_action_ntf
1290**
1291** Description      process the NFCEE action callback event
1292**
1293** Returns          void
1294**
1295*******************************************************************************/
1296void nfa_ee_nci_action_ntf(tNFA_EE_MSG *p_data)
1297{
1298    tNFC_EE_ACTION_REVT *p_cbk = p_data->act.p_data;
1299    tNFA_EE_ACTION      evt_data;
1300
1301    evt_data.ee_handle  = (tNFA_HANDLE)p_cbk->nfcee_id | NFA_HANDLE_GROUP_EE;
1302    evt_data.trigger    = p_cbk->act_data.trigger;
1303    memcpy (&(evt_data.param), &(p_cbk->act_data.param), sizeof (tNFA_EE_ACTION_PARAM));
1304    nfa_ee_report_event(NULL, NFA_EE_ACTION_EVT, (tNFA_EE_CBACK_DATA *)&evt_data);
1305}
1306
1307/*******************************************************************************
1308**
1309** Function         nfa_ee_nci_disc_req_ntf
1310**
1311** Description      process the NFCEE discover request callback event
1312**
1313** Returns          void
1314**
1315*******************************************************************************/
1316void nfa_ee_nci_disc_req_ntf(tNFA_EE_MSG *p_data)
1317{
1318    tNFC_EE_DISCOVER_REQ_REVT   *p_cbk = p_data->disc_req.p_data;
1319    tNFA_HANDLE         ee_handle;
1320    tNFA_EE_ECB         *p_cb = NULL;
1321    UINT8 xx;
1322
1323    NFA_TRACE_DEBUG0 ("nfa_ee_nci_disc_req_ntf ()");
1324
1325    for (xx = 0; xx < p_cbk->num_info; xx++)
1326    {
1327        ee_handle = NFA_HANDLE_GROUP_EE|p_cbk->info[xx].nfcee_id;
1328
1329        p_cb = nfa_ee_find_ecb (p_cbk->info[xx].nfcee_id);
1330        if (!p_cb)
1331        {
1332            NFA_TRACE_DEBUG1 ("Cannot find cb for NFCEE: 0x%x", p_cbk->info[xx].nfcee_id);
1333            p_cb = nfa_ee_find_ecb (NFA_EE_INVALID);
1334            if (p_cb)
1335            {
1336                p_cb->nfcee_id   = p_cbk->info[xx].nfcee_id;
1337                p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_ORDER;
1338            }
1339            else
1340            {
1341                NFA_TRACE_ERROR1 ("Cannot allocate cb for NFCEE: 0x%x", p_cbk->info[xx].nfcee_id);
1342                continue;
1343            }
1344        }
1345
1346        p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_DISC_REQ;
1347        if (p_cbk->info[xx].op == NFC_EE_DISC_OP_ADD)
1348        {
1349            if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_A)
1350            {
1351                p_cb->la_protocol = p_cbk->info[xx].protocol;
1352            }
1353            else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B)
1354            {
1355                p_cb->lb_protocol = p_cbk->info[xx].protocol;
1356            }
1357            else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_F)
1358            {
1359                p_cb->lf_protocol = p_cbk->info[xx].protocol;
1360            }
1361            else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)
1362            {
1363                p_cb->lbp_protocol = p_cbk->info[xx].protocol;
1364            }
1365        }
1366        else
1367        {
1368            if (p_cb)
1369            {
1370                if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_A)
1371                {
1372                    p_cb->la_protocol = 0;
1373                }
1374                else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B)
1375                {
1376                    p_cb->lb_protocol = 0;
1377                }
1378                else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_F)
1379                {
1380                    p_cb->lf_protocol = 0;
1381                }
1382                else if (p_cbk->info[xx].tech_n_mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)
1383                {
1384                    p_cb->lbp_protocol = 0;
1385                }
1386            }
1387        }
1388    }
1389
1390    /* Report NFA_EE_DISCOVER_REQ_EVT for all active NFCEE */
1391    if ((p_cb->ecb_flags & NFA_EE_ECB_FLAGS_ORDER) == 0)
1392        nfa_ee_report_discover_req_evt();
1393}
1394
1395/*******************************************************************************
1396**
1397** Function         nfa_ee_is_active
1398**
1399** Description      Check if the given NFCEE is active
1400**
1401** Returns          TRUE if the given NFCEE is active
1402**
1403*******************************************************************************/
1404BOOLEAN nfa_ee_is_active (tNFA_HANDLE nfcee_id)
1405{
1406    BOOLEAN is_active = FALSE;
1407    int     xx;
1408    tNFA_EE_ECB  *p_cb = nfa_ee_cb.ecb;
1409
1410    if ((NFA_HANDLE_GROUP_MASK & nfcee_id) == NFA_HANDLE_GROUP_EE)
1411        nfcee_id    &= NFA_HANDLE_MASK;
1412
1413    /* compose output */
1414    for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++)
1415    {
1416        if ((tNFA_HANDLE)p_cb->nfcee_id == nfcee_id)
1417        {
1418            if (p_cb->ee_status == NFA_EE_STATUS_ACTIVE)
1419            {
1420                is_active = TRUE;
1421            }
1422            break;
1423        }
1424    }
1425    return is_active;
1426}
1427
1428/*******************************************************************************
1429**
1430** Function         nfa_ee_get_tech_route
1431**
1432** Description      Given a power state, find the technology routing destination.
1433**                  The result is filled in the given p_handles
1434**                  in the order of A, B, F, Bprime
1435**
1436** Returns          None
1437**
1438*******************************************************************************/
1439void nfa_ee_get_tech_route (UINT8 power_state, UINT8 *p_handles)
1440{
1441    int     xx, yy;
1442    tNFA_EE_ECB *p_cb;
1443    UINT8   tech_mask_list[NFA_EE_MAX_TECH_ROUTE] =
1444    {
1445        NFA_TECHNOLOGY_MASK_A,
1446        NFA_TECHNOLOGY_MASK_B,
1447        NFA_TECHNOLOGY_MASK_F,
1448        NFA_TECHNOLOGY_MASK_B_PRIME
1449    };
1450
1451    NFA_TRACE_DEBUG1("nfa_ee_get_tech_route(): %d", power_state);
1452
1453    for (xx = 0; xx < NFA_EE_MAX_TECH_ROUTE; xx++)
1454    {
1455        p_handles[xx] = NFC_DH_ID;
1456        p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
1457        for (yy = 0; yy < nfa_ee_cb.cur_ee; yy++, p_cb--)
1458        {
1459            if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE)
1460            {
1461                switch (power_state)
1462                {
1463                case NFA_EE_PWR_STATE_ON:
1464                    if (p_cb->tech_switch_on & tech_mask_list[xx])
1465                        p_handles[xx] = p_cb->nfcee_id;
1466                    break;
1467                case NFA_EE_PWR_STATE_SWITCH_OFF:
1468                    if (p_cb->tech_switch_off & tech_mask_list[xx])
1469                        p_handles[xx] = p_cb->nfcee_id;
1470                    break;
1471                case NFA_EE_PWR_STATE_BATT_OFF:
1472                    if (p_cb->tech_battery_off & tech_mask_list[xx])
1473                        p_handles[xx] = p_cb->nfcee_id;
1474                    break;
1475                }
1476            }
1477        }
1478    }
1479    NFA_TRACE_DEBUG4("0x%x, 0x%x, 0x%x, 0x%x", p_handles[0], p_handles[1], p_handles[2], p_handles[3]);
1480}
1481
1482/*******************************************************************************
1483**
1484** Function         nfa_ee_route_add_one_ecb
1485**
1486** Description      Add the routing entries for one NFCEE/DH
1487**
1488** Returns          NFA_STATUS_OK, if ok to continue
1489**
1490*******************************************************************************/
1491tNFA_STATUS nfa_ee_route_add_one_ecb(tNFA_EE_ECB *p_cb, int max_len, BOOLEAN more, UINT8 *ps, int *p_cur_offset)
1492{
1493    UINT8   *p, tlv_size, *pa;
1494    UINT8   num_tlv, len;
1495    int     xx;
1496    int     start_offset;
1497    UINT8   power_cfg = 0;
1498    UINT8   *pp = ps + *p_cur_offset;
1499    UINT8   entry_size;
1500    UINT8   max_tlv = (UINT8)((max_len > NFA_EE_ROUT_MAX_TLV_SIZE)?NFA_EE_ROUT_MAX_TLV_SIZE:max_len);
1501    tNFA_STATUS status = NFA_STATUS_OK;
1502
1503    /* use the first byte of the buffer (ps) to keep the num_tlv */
1504    num_tlv  = *ps;
1505    NFA_TRACE_DEBUG5 ("nfa_ee_route_add_one_ecb max_len:%d, max_tlv:%d, cur_offset:%d, more:%d, num_tlv:%d",
1506        max_len, max_tlv, *p_cur_offset, more, num_tlv);
1507    pp       = ps + 1 + *p_cur_offset;
1508    p        = pp;
1509    tlv_size = (UINT8)*p_cur_offset;
1510    /* add the Technology based routing */
1511    for (xx = 0; xx < NFA_EE_NUM_TECH; xx++)
1512    {
1513        power_cfg = 0;
1514        if (p_cb->tech_switch_on & nfa_ee_tech_mask_list[xx])
1515            power_cfg |= NCI_ROUTE_PWR_STATE_ON;
1516        if (p_cb->tech_switch_off & nfa_ee_tech_mask_list[xx])
1517            power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
1518        if (p_cb->tech_battery_off & nfa_ee_tech_mask_list[xx])
1519            power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
1520        if (power_cfg)
1521        {
1522            *pp++   = NFC_ROUTE_TAG_TECH;
1523            *pp++   = 3;
1524            *pp++   = p_cb->nfcee_id;
1525            *pp++   = power_cfg;
1526            *pp++   = nfa_ee_tech_list[xx];
1527            num_tlv++;
1528            if (power_cfg != NCI_ROUTE_PWR_STATE_ON)
1529                nfa_ee_cb.ee_cfged  |= NFA_EE_CFGED_OFF_ROUTING;
1530        }
1531    }
1532
1533    /* add the Protocol based routing */
1534    for (xx = 0; xx < NFA_EE_NUM_PROTO; xx++)
1535    {
1536        power_cfg = 0;
1537        if (p_cb->proto_switch_on & nfa_ee_proto_mask_list[xx])
1538            power_cfg |= NCI_ROUTE_PWR_STATE_ON;
1539        if (p_cb->proto_switch_off & nfa_ee_proto_mask_list[xx])
1540            power_cfg |= NCI_ROUTE_PWR_STATE_SWITCH_OFF;
1541        if (p_cb->proto_battery_off & nfa_ee_proto_mask_list[xx])
1542            power_cfg |= NCI_ROUTE_PWR_STATE_BATT_OFF;
1543        if (power_cfg)
1544        {
1545            *pp++   = NFC_ROUTE_TAG_PROTO;
1546            *pp++   = 3;
1547            *pp++   = p_cb->nfcee_id;
1548            *pp++   = power_cfg;
1549            *pp++   = nfa_ee_proto_list[xx];
1550            num_tlv++;
1551            if (power_cfg != NCI_ROUTE_PWR_STATE_ON)
1552                nfa_ee_cb.ee_cfged  |= NFA_EE_CFGED_OFF_ROUTING;
1553        }
1554    }
1555
1556    /* add the AID routing */
1557    if (p_cb->aid_entries)
1558    {
1559        start_offset = 0;
1560        for (xx = 0; xx < p_cb->aid_entries; xx++)
1561        {
1562            /* add one AID entry */
1563            if (p_cb->aid_rt_info[xx] & NFA_EE_AE_ROUTE)
1564            {
1565                num_tlv++;
1566                pa      = &p_cb->aid_cfg[start_offset];
1567                pa ++; /* EMV tag */
1568                len     = *pa++; /* aid_len */
1569                *pp++   = NFC_ROUTE_TAG_AID;
1570                *pp++   = len + 2;
1571                *pp++   = p_cb->nfcee_id;
1572                *pp++   = p_cb->aid_pwr_cfg[xx];
1573                /* copy the AID */
1574                memcpy(pp, pa, len);
1575                pp     += len;
1576            }
1577            start_offset += p_cb->aid_len[xx];
1578        }
1579    }
1580    entry_size = (UINT8)(pp - p);
1581    tlv_size  += entry_size;
1582    if (entry_size)
1583    {
1584        nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
1585    }
1586    if (p_cb->ecb_flags   & NFA_EE_ECB_FLAGS_ROUTING)
1587    {
1588        nfa_ee_cb.ee_cfg_sts   |= NFA_EE_STS_CHANGED_ROUTING;
1589    }
1590    NFA_TRACE_DEBUG3 ("ee_cfg_sts:0x%02x entry_size:%d, tlv_size:%d", nfa_ee_cb.ee_cfg_sts, entry_size, tlv_size);
1591
1592    if (tlv_size > max_tlv)
1593    {
1594        /* exceeds routing table size - report ERROR */
1595        status  = NFA_STATUS_BUFFER_FULL;
1596    }
1597
1598    else if (more == FALSE)
1599    {
1600        /* last entry. update routing table now */
1601        if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_CHANGED_ROUTING)
1602        {
1603            if (tlv_size)
1604            {
1605                nfa_ee_cb.ee_cfg_sts       |= NFA_EE_STS_PREV_ROUTING;
1606            }
1607            else
1608            {
1609                nfa_ee_cb.ee_cfg_sts       &= ~NFA_EE_STS_PREV_ROUTING;
1610            }
1611            NFC_SetRouting(more, p_cb->nfcee_id, num_tlv, tlv_size, ps + 1);
1612        }
1613        else if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_PREV_ROUTING)
1614        {
1615            if (tlv_size == 0)
1616            {
1617                nfa_ee_cb.ee_cfg_sts       &= ~NFA_EE_STS_PREV_ROUTING;
1618                /* indicated routing is configured to NFCC */
1619                nfa_ee_cb.ee_cfg_sts       |= NFA_EE_STS_CHANGED_ROUTING;
1620                NFC_SetRouting(more, p_cb->nfcee_id, 0, 0, ps + 1);
1621            }
1622        }
1623    }
1624    else
1625    {
1626        /* update the total num_tlv current offset */
1627        *ps              = num_tlv;
1628        *p_cur_offset   += entry_size;
1629    }
1630
1631    return status;
1632}
1633
1634
1635/*******************************************************************************
1636**
1637** Function         nfa_ee_need_recfg
1638**
1639** Description      Check if any API function to configure the routing table or
1640**                  VS is called since last update
1641**
1642**                  The algorithm for the NFCEE configuration handling is as follows:
1643**
1644**                  Each NFCEE_ID/DH has its own control block - tNFA_EE_ECB
1645**                  Each control block uses ecb_flags to keep track if an API
1646**                  that changes routing/VS is invoked.
1647**                  This ecb_flags is cleared at the end of nfa_ee_update_rout().
1648**
1649**                  nfa_ee_cb.ee_cfged is the bitmask of the control blocks with
1650**                  routing/VS configuration and NFA_EE_CFGED_UPDATE_NOW.
1651**                  nfa_ee_cb.ee_cfged is cleared and re-calculated at the end of
1652**                  nfa_ee_update_rout().
1653**
1654**                  nfa_ee_cb.ee_cfg_sts is used to check is any status is changed
1655**                  and the associated command is issued to NFCC.
1656**                  nfa_ee_cb.ee_cfg_sts is AND with NFA_EE_STS_PREV at the end of
1657**                  nfa_ee_update_rout() to clear the NFA_EE_STS_CHANGED bits
1658**                  (except NFA_EE_STS_CHANGED_CANNED_VS is cleared in nfa_ee_vs_cback)
1659**
1660** Returns          TRUE if any configuration is changed
1661**
1662*******************************************************************************/
1663static BOOLEAN nfa_ee_need_recfg(void)
1664{
1665    BOOLEAN needed = FALSE;
1666    UINT32  xx;
1667    tNFA_EE_ECB  *p_cb;
1668    UINT8   mask;
1669
1670    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);
1671    /* if no routing/vs is configured, do not need to send the info to NFCC */
1672    if (nfa_ee_cb.ee_cfged || nfa_ee_cb.ee_cfg_sts)
1673    {
1674        if (nfa_ee_cb.ee_cfged & NFA_EE_CFGED_UPDATE_NOW)
1675        {
1676            needed = TRUE;
1677        }
1678        else if (nfa_ee_cb.ee_cfg_sts & NFA_EE_STS_CHANGED)
1679        {
1680            needed = TRUE;
1681        }
1682        else
1683        {
1684            p_cb = &nfa_ee_cb.ecb[NFA_EE_CB_4_DH];
1685            mask = 1 << NFA_EE_CB_4_DH;
1686            for (xx = 0; xx <= nfa_ee_cb.cur_ee; xx++)
1687            {
1688                NFA_TRACE_DEBUG3("%d: ecb_flags  : 0x%02x, mask: 0x%02x", xx, p_cb->ecb_flags  , mask);
1689                if ((p_cb->ecb_flags  ) && (nfa_ee_cb.ee_cfged & mask))
1690                {
1691                    needed = TRUE;
1692                    break;
1693                }
1694                p_cb = &nfa_ee_cb.ecb[xx];
1695                mask = 1 << xx;
1696            }
1697        }
1698    }
1699
1700    return needed;
1701}
1702
1703/*******************************************************************************
1704**
1705** Function         nfa_ee_rout_timeout
1706**
1707** Description      Anytime VS or routing entries are changed,
1708**                  a 1 second timer is started. This function is called when
1709**                  the timer expires or NFA_EeUpdateNow() is called.
1710**
1711** Returns          void
1712**
1713*******************************************************************************/
1714void nfa_ee_rout_timeout(tNFA_EE_MSG *p_data)
1715{
1716    NFA_TRACE_DEBUG0("nfa_ee_rout_timeout()");
1717    if (nfa_ee_need_recfg())
1718    {
1719        /* discovery is not started */
1720        nfa_ee_update_rout();
1721    }
1722}
1723
1724/*******************************************************************************
1725**
1726** Function         nfa_ee_discv_timeout
1727**
1728** Description
1729**
1730**
1731**
1732** Returns          void
1733**
1734*******************************************************************************/
1735void nfa_ee_discv_timeout(tNFA_EE_MSG *p_data)
1736{
1737    NFC_NfceeDiscover(FALSE);
1738    if (nfa_ee_cb.p_enable_cback)
1739        (*nfa_ee_cb.p_enable_cback)(TRUE);
1740}
1741
1742/*******************************************************************************
1743**
1744** Function         nfa_ee_lmrt_to_nfcc
1745**
1746** Description      This function would set the listen mode routing table
1747**                  to NFCC.
1748**
1749** Returns          void
1750**
1751*******************************************************************************/
1752void nfa_ee_lmrt_to_nfcc(tNFA_EE_MSG *p_data)
1753{
1754    int xx;
1755    tNFA_EE_ECB          *p_cb;
1756    UINT8   *p = NULL;
1757    BOOLEAN more = TRUE;
1758    UINT8   last_active = NFA_EE_INVALID;
1759    int     max_len, len;
1760    tNFA_STATUS status = NFA_STATUS_FAILED;
1761    int     cur_offset;
1762
1763    /* update routing table: DH and the activated NFCEEs */
1764    p = (UINT8 *)GKI_getbuf(NFA_EE_ROUT_BUF_SIZE);
1765    if (p == NULL)
1766    {
1767        NFA_TRACE_ERROR0 ("nfa_ee_lmrt_to_nfcc() no buffer to send routing info.");
1768        nfa_ee_report_event( NULL, NFA_EE_NO_MEM_ERR_EVT, (tNFA_EE_CBACK_DATA *)&status);
1769        return;
1770    }
1771
1772    /* find the last active NFCEE. */
1773    p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
1774    for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb--)
1775    {
1776        if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE)
1777        {
1778            if (last_active == NFA_EE_INVALID)
1779            {
1780                last_active = p_cb->nfcee_id;
1781                NFA_TRACE_DEBUG1 ("last_active: 0x%x", last_active);
1782            }
1783        }
1784    }
1785    if (last_active == NFA_EE_INVALID)
1786    {
1787        more = FALSE;
1788    }
1789
1790    /* add the routing for DH first */
1791    status  = NFA_STATUS_OK;
1792    max_len = NFC_GetLmrtSize();
1793    cur_offset  = 0;
1794    /* use the first byte of the buffer (p) to keep the num_tlv */
1795    *p          = 0;
1796    status = nfa_ee_route_add_one_ecb(&nfa_ee_cb.ecb[NFA_EE_CB_4_DH], max_len, more, p, &cur_offset);
1797
1798    /* add only what is supported by NFCC. report overflow */
1799    if (status == NFA_STATUS_OK)
1800    {
1801        /* add the routing for NFCEEs */
1802        p_cb = &nfa_ee_cb.ecb[0];
1803        for (xx = 0; (xx < nfa_ee_cb.cur_ee) && more; xx++, p_cb++)
1804        {
1805            len = 0;
1806            if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE)
1807            {
1808                NFA_TRACE_DEBUG2 ("nfcee_id:0x%x, last_active: 0x%x", p_cb->nfcee_id, last_active);
1809                if (last_active == p_cb->nfcee_id)
1810                    more = FALSE;
1811                status = nfa_ee_route_add_one_ecb(p_cb, max_len, more, p, &cur_offset);
1812                if (status != NFA_STATUS_OK)
1813                {
1814                    more    = FALSE;
1815                }
1816            }
1817        }
1818    }
1819    if (status != NFA_STATUS_OK)
1820    {
1821        nfa_ee_report_event( NULL, NFA_EE_ROUT_ERR_EVT, (tNFA_EE_CBACK_DATA *)&status);
1822    }
1823    GKI_freebuf(p);
1824}
1825
1826/*******************************************************************************
1827**
1828** Function         nfa_ee_update_rout
1829**
1830** Description      This function would set the VS and listen mode routing table
1831**                  to NFCC.
1832**
1833** Returns          void
1834**
1835*******************************************************************************/
1836void nfa_ee_update_rout(void)
1837{
1838    int xx;
1839    tNFA_EE_ECB          *p_cb;
1840    UINT8   mask;
1841    BT_HDR  msg;
1842
1843    NFA_TRACE_DEBUG1 ("nfa_ee_update_rout ee_cfg_sts:0x%02x", nfa_ee_cb.ee_cfg_sts);
1844
1845    /* use action function to send routing and VS configuration to NFCC */
1846    msg.event = NFA_EE_CFG_TO_NFCC_EVT;
1847    nfa_ee_evt_hdlr (&msg);
1848
1849    /* all configuration is updated to NFCC, clear the status mask */
1850    nfa_ee_cb.ee_cfg_sts   &= NFA_EE_STS_PREV;
1851    nfa_ee_cb.ee_cfged  = 0;
1852    p_cb                = &nfa_ee_cb.ecb[0];
1853    for (xx = 0; xx < NFA_EE_NUM_ECBS; xx++, p_cb++)
1854    {
1855        p_cb->ecb_flags     = 0;
1856        mask                = (1 << xx);
1857        if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off |
1858            p_cb->proto_switch_on| p_cb->proto_switch_off| p_cb->proto_battery_off |
1859            p_cb->aid_entries)
1860        {
1861            /* this entry has routing configuration. mark it configured */
1862            nfa_ee_cb.ee_cfged  |= mask;
1863        }
1864    }
1865    NFA_TRACE_DEBUG2 ("ee_cfg_sts:0x%02x ee_cfged:0x%02x", nfa_ee_cb.ee_cfg_sts, nfa_ee_cb.ee_cfged);
1866}
1867
1868
1869