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