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