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 49const 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 56const 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 65const 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 74const 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 83static void nfa_ee_check_restore_complete(void); 84static 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*******************************************************************************/ 95static 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*******************************************************************************/ 126int 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*******************************************************************************/ 153tNFA_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*******************************************************************************/ 201void 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*******************************************************************************/ 229void 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*******************************************************************************/ 243void 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*******************************************************************************/ 274void 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*******************************************************************************/ 319void 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*******************************************************************************/ 342void 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*******************************************************************************/ 377void 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*******************************************************************************/ 406void 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*******************************************************************************/ 435void 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*******************************************************************************/ 513void 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*******************************************************************************/ 572void 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*******************************************************************************/ 588void 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*******************************************************************************/ 630void 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*******************************************************************************/ 669void 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*******************************************************************************/ 692void 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*******************************************************************************/ 739static 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*******************************************************************************/ 766static 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*******************************************************************************/ 820void 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*******************************************************************************/ 900void 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*******************************************************************************/ 1066static 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*******************************************************************************/ 1108static 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*******************************************************************************/ 1156void 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*******************************************************************************/ 1239void 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*******************************************************************************/ 1331void 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*******************************************************************************/ 1351void 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*******************************************************************************/ 1439BOOLEAN 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*******************************************************************************/ 1474void 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*******************************************************************************/ 1526tNFA_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*******************************************************************************/ 1698static 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*******************************************************************************/ 1749void 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*******************************************************************************/ 1770void 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*******************************************************************************/ 1787void 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*******************************************************************************/ 1871void 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