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