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