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