| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /****************************************************************************** |
| * |
| * The original Work has been changed by NXP Semiconductors. |
| * |
| * Copyright (C) 2015-2018 NXP Semiconductors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| /* |
| * Communicate with secure elements that are attached to the NFC |
| * controller. |
| */ |
| #include "SecureElement.h" |
| #include <ScopedLocalRef.h> |
| #include <android-base/stringprintf.h> |
| #include <base/logging.h> |
| #include <errno.h> |
| #include <semaphore.h> |
| #include "DataQueue.h" |
| #include "HciEventManager.h" |
| #include "JavaClassConstants.h" |
| #include "PeerToPeer.h" |
| #include "PowerSwitch.h" |
| #include "TransactionController.h" |
| #include "config.h" |
| #include "nfc_api.h" |
| #include "nfc_config.h" |
| #include "phNxpConfig.h" |
| #if (NXP_EXTNS == TRUE) |
| #include "MposManager.h" |
| #include "RoutingManager.h" |
| |
| #include <signal.h> |
| #include <sys/types.h> |
| #include "nfa_api.h" |
| #endif |
| using android::base::StringPrintf; |
| |
| extern bool nfc_debug_enabled; |
| /***************************************************************************** |
| ** |
| ** public variables |
| ** |
| *****************************************************************************/ |
| static int gSEId = |
| -1; // secure element ID to use in connectEE(), -1 means not set |
| static int gGatePipe = |
| -1; // gate id or static pipe id to use in connectEE(), -1 means not set |
| static bool gUseStaticPipe = false; // if true, use gGatePipe as static pipe |
| // id. if false, use as gate id |
| extern bool gTypeB_listen; |
| bool hold_the_transceive = false; |
| int dual_mode_current_state = 0; |
| nfc_jni_native_data* mthreadnative; |
| #if (NXP_EXTNS == TRUE) |
| nfcee_disc_state sNfcee_disc_state; |
| extern uint8_t nfcee_swp_discovery_status; |
| extern int32_t gSeDiscoverycount; |
| static void rfFeildEventTimeoutCallback(union sigval); |
| pthread_t passiveListenEnable_thread; |
| void* passiveListenEnableThread(void* arg); |
| bool ceTransactionPending = false; |
| static uint8_t passiveListenState = 0x00; |
| static bool isTransceiveOngoing = false; |
| static void passiveListenDisablecallBack(union sigval); |
| #endif |
| namespace android { |
| extern void startRfDiscovery(bool isStart); |
| extern void setUiccIdleTimeout(bool enable); |
| extern bool isDiscoveryStarted(); |
| extern void requestFwDownload(); |
| extern int getScreenState(); |
| extern void checkforNfceeConfig(uint8_t type); |
| #if (NXP_EXTNS == TRUE) |
| extern bool nfcManager_checkNfcStateBusy(); |
| #endif |
| extern bool isp2pActivated(); |
| extern SyncEvent sNfaSetConfigEvent; |
| extern tNFA_STATUS ResetEseSession(); |
| extern void start_timer_msec(struct timeval* start_tv); |
| extern long stop_timer_getdifference_msec(struct timeval* start_tv, |
| struct timeval* stop_tv); |
| extern bool nfcManager_isNfcActive(); |
| extern bool nfcManager_isNfcDisabling(); |
| extern Mutex mSPIDwpSyncMutex; |
| #if (NXP_EXTNS == TRUE) |
| extern int gMaxEERecoveryTimeout; |
| extern uint8_t nfcManager_getNfcState(); |
| #endif |
| } // namespace android |
| #if (NXP_EXTNS == TRUE) |
| static uint32_t |
| nfccStandbytimeout; // timeout for secelem standby mode detection |
| int active_ese_reset_control = 0; |
| bool hold_wired_mode = false; |
| static nfcc_standby_operation_t standby_state = STANDBY_MODE_ON; |
| SyncEvent mWiredModeHoldEvent; |
| static int gWtxCount = 0; |
| static void NFCC_StandbyModeTimerCallBack(union sigval); |
| /* hold the transceive flag should be set when the prio session is |
| * actrive/about to active*/ |
| /* Event used to inform the prio session end and transceive resume*/ |
| SyncEvent sSPIPrioSessionEndEvent; |
| SyncEvent sSPISignalHandlerEvent; |
| SyncEvent sSPIForceEnableDWPEvent; |
| SyncEvent sSPISVDDSyncOnOffEvent; |
| int spiDwpSyncState = STATE_IDLE; |
| void* spiEventHandlerThread(void* arg); |
| Mutex mSPIEvtMutex; |
| DataQueue gSPIEvtQueue; |
| volatile uint16_t usSPIActEvent = 0; |
| pthread_t spiEvtHandler_thread; |
| bool createSPIEvtHandlerThread(); |
| void releaseSPIEvtHandlerThread(); |
| static void nfaVSC_SVDDSyncOnOff(bool type); |
| static tNFA_STATUS nfaVSC_ForceDwpOnOff(bool type); |
| #endif |
| SyncEvent mDualModeEvent; |
| static void setSPIState(bool mState); |
| ////////////////////////////////////////////// |
| ////////////////////////////////////////////// |
| #if (NXP_EXTNS == TRUE) |
| #define STATIC_PIPE_0x19 0x19 // PN54X Gemalto's proprietary static pipe |
| #define STATIC_PIPE_0x70 0x70 // Broadcom's proprietary static pipe |
| uint8_t SecureElement::mStaticPipeProp; |
| |
| #endif |
| |
| SecureElement SecureElement::sSecElem; |
| const char* SecureElement::APP_NAME = "nfc_jni"; |
| const uint16_t ACTIVE_SE_USE_ANY = 0xFFFF; |
| |
| /******************************************************************************* |
| ** |
| ** Function: SecureElement |
| ** |
| ** Description: Initialize member variables. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| SecureElement::SecureElement() |
| : mActiveEeHandle(NFA_HANDLE_INVALID), |
| #if (NXP_EXTNS == TRUE) |
| mETSI12InitStatus(NFA_STATUS_FAILED), |
| mWmMaxWtxCount(0), |
| meseETSI12Recovery(false), |
| mPassiveListenTimeout(0), |
| mPassiveListenCnt(0), |
| meSESessionIdOk(false), |
| mIsWiredModeOpen(false), |
| mIsAllowWiredInDesfireMifareCE(false), |
| mRfFieldEventTimeout(0), |
| mModeSetInfo(NFA_STATUS_FAILED), |
| mPwrCmdstatus(NFA_STATUS_FAILED), |
| mNfccPowerMode(0), |
| mIsIntfRstEnabled(false), |
| #endif |
| mDestinationGate(4), // loopback gate |
| mNativeData(NULL), |
| mIsInit(false), |
| mActualNumEe(0), |
| mbNewEE(true), // by default we start w/thinking there are new EE |
| mNewPipeId(0), |
| mNewSourceGate(0), |
| mActiveSeOverride(ACTIVE_SE_USE_ANY), |
| mCommandStatus(NFA_STATUS_OK), |
| mIsPiping(false), |
| mCurrentRouteSelection(NoRoute), |
| mActualResponseSize(0), |
| mAtrInfolen(0), |
| mAtrStatus(0), |
| mUseOberthurWarmReset(false), |
| mActivatedInListenMode(false), |
| mOberthurWarmResetCommand(3), |
| mGetAtrRspwait(false), |
| mRfFieldIsOn(false), |
| mTransceiveWaitOk(false) { |
| memset(&mEeInfo, 0, |
| nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED * sizeof(tNFA_EE_INFO)); |
| memset(&mUiccInfo, 0, sizeof(mUiccInfo)); |
| memset(&mHciCfg, 0, sizeof(mHciCfg)); |
| memset(mAidForEmptySelect, 0, sizeof(mAidForEmptySelect)); |
| memset(&mLastRfFieldToggle, 0, sizeof(mLastRfFieldToggle)); |
| memset(mAtrInfo, 0, sizeof(mAtrInfo)); |
| memset(&mNfceeData_t, 0, sizeof(mNfceeData_t)); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: ~SecureElement |
| ** |
| ** Description: Release all resources. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| SecureElement::~SecureElement() {} |
| |
| /******************************************************************************* |
| ** |
| ** Function: getInstance |
| ** |
| ** Description: Get the SecureElement singleton object. |
| ** |
| ** Returns: SecureElement object. |
| ** |
| *******************************************************************************/ |
| SecureElement& SecureElement::getInstance() { return sSecElem; } |
| |
| /******************************************************************************* |
| ** |
| ** Function: setActiveSeOverride |
| ** |
| ** Description: Specify which secure element to turn on. |
| ** activeSeOverride: ID of secure element |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::setActiveSeOverride(uint8_t activeSeOverride) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "SecureElement::setActiveSeOverride, seid=0x%X", activeSeOverride); |
| mActiveSeOverride = activeSeOverride; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: initialize |
| ** |
| ** Description: Initialize all member variables. |
| ** native: Native data. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::initialize(nfc_jni_native_data* native) { |
| static const char fn[] = "SecureElement::initialize"; |
| tNFA_STATUS nfaStat; |
| unsigned long num = 0; |
| unsigned long retValue; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| if (NfcConfig::hasKey("NFA_HCI_DEFAULT_DEST_GATE")) { |
| mDestinationGate = NfcConfig::getUnsigned("NFA_HCI_DEFAULT_DEST_GATE"); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Default destination gate: 0x%X", fn, mDestinationGate); |
| |
| mStaticPipeProp = |
| nfcFL.nfccFL._GEMALTO_SE_SUPPORT ? STATIC_PIPE_0x19 : STATIC_PIPE_0x70; |
| |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| if (NfcConfig::hasKey(NAME_NXP_NFCC_PASSIVE_LISTEN_TIMEOUT)) { |
| mPassiveListenTimeout = |
| NfcConfig::getUnsigned(NAME_NXP_NFCC_PASSIVE_LISTEN_TIMEOUT); |
| } else { |
| mPassiveListenTimeout = 2500; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFCC Passive Listen Disable timeout =%u", fn, |
| mPassiveListenTimeout); |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFCC Passive Listen Disable timeout =%u", fn, |
| mPassiveListenTimeout); |
| } |
| if (NfcConfig::hasKey(NAME_NXP_NFCC_STANDBY_TIMEOUT)) { |
| nfccStandbytimeout = |
| NfcConfig::getUnsigned(NAME_NXP_NFCC_STANDBY_TIMEOUT); |
| } else { |
| nfccStandbytimeout = 20000; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFCC standby mode timeout =0x%u", fn, nfccStandbytimeout); |
| if (nfccStandbytimeout > 0 && nfccStandbytimeout < 5000) { |
| nfccStandbytimeout = 5000; |
| } else if (nfccStandbytimeout > 20000) { |
| nfccStandbytimeout = 20000; |
| } |
| standby_state = STANDBY_MODE_ON; |
| if (nfcFL.eseFL._ESE_JCOP_DWNLD_PROTECTION || nfcFL.eseFL._ESE_SVDD_SYNC || |
| nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| spiDwpSyncState = STATE_IDLE; |
| } |
| |
| if (NfcConfig::hasKey(NAME_NXP_WM_MAX_WTX_COUNT)) { |
| mWmMaxWtxCount = NfcConfig::getUnsigned(NAME_NXP_WM_MAX_WTX_COUNT); |
| } else |
| mWmMaxWtxCount = 9000; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFCC Wired Mode Max WTX Count =%hu", fn, mWmMaxWtxCount); |
| dual_mode_current_state = SPI_DWPCL_NOT_ACTIVE; |
| hold_the_transceive = false; |
| active_ese_reset_control = 0; |
| hold_wired_mode = false; |
| mlistenDisabled = false; |
| mIsExclusiveWiredMode = false; |
| |
| if (NfcConfig::hasKey(NAME_NXP_NFCC_RF_FIELD_EVENT_TIMEOUT)) { |
| mRfFieldEventTimeout = |
| NfcConfig::getUnsigned(NAME_NXP_NFCC_RF_FIELD_EVENT_TIMEOUT); |
| } else { |
| mRfFieldEventTimeout = 2000; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: RF Field Off event timeout =%u", fn, mRfFieldEventTimeout); |
| } |
| |
| if (NfcConfig::hasKey(NAME_NXP_ALLOW_WIRED_IN_MIFARE_DESFIRE_CLT)) { |
| retValue = |
| NfcConfig::getUnsigned(NAME_NXP_ALLOW_WIRED_IN_MIFARE_DESFIRE_CLT); |
| mIsAllowWiredInDesfireMifareCE = (retValue == 0x00) ? false : true; |
| } else { |
| mIsAllowWiredInDesfireMifareCE = false; |
| } |
| |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| if (NfcConfig::hasKey(NAME_NXP_ESE_POWER_DH_CONTROL)) { |
| num = NfcConfig::getUnsigned(NAME_NXP_ESE_POWER_DH_CONTROL); |
| mNfccPowerMode = (uint8_t)num; |
| } else { |
| mNfccPowerMode = 0; |
| } |
| } |
| |
| retValue = 0; |
| if (NfcConfig::hasKey(NAME_NXP_DWP_INTF_RESET_ENABLE)) { |
| retValue = NfcConfig::getUnsigned(NAME_NXP_DWP_INTF_RESET_ENABLE); |
| mIsIntfRstEnabled = (retValue == 0x00) ? false : true; |
| } |
| } |
| |
| #endif |
| mActiveEeHandle = NFA_HANDLE_INVALID; |
| mNfaHciHandle = NFA_HANDLE_INVALID; |
| |
| mNativeData = native; |
| mthreadnative = native; |
| mActualNumEe = nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED; |
| mbNewEE = true; |
| mNewPipeId = 0; |
| mNewSourceGate = 0; |
| mRfFieldIsOn = false; |
| mActivatedInListenMode = false; |
| mCurrentRouteSelection = NoRoute; |
| if (nfcFL.nfcNxpEse && |
| nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| mPassiveListenEnabled = true; |
| meseUiccConcurrentAccess = false; |
| } |
| |
| memset(mEeInfo, 0, sizeof(mEeInfo)); |
| memset(&mUiccInfo, 0, sizeof(mUiccInfo)); |
| memset(&mHciCfg, 0, sizeof(mHciCfg)); |
| mUsedAids.clear(); |
| memset(mAidForEmptySelect, 0, sizeof(mAidForEmptySelect)); |
| #if (NXP_EXTNS == TRUE) |
| mIsWiredModeBlocked = false; |
| #endif |
| |
| // if no SE is to be used, get out. |
| if (mActiveSeOverride == 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: No SE; No need to initialize SecureElement", fn); |
| return (false); |
| } |
| |
| initializeEeHandle(); |
| |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: try hci register", fn); |
| SyncEventGuard guard(mHciRegisterEvent); |
| nfaStat = |
| NFA_HciRegister(const_cast<char*>(APP_NAME), nfaHciCallback, true); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail hci register; error=0x%X", fn, |
| nfaStat); |
| return (false); |
| } else { |
| mHciRegisterEvent.wait(); |
| } |
| } |
| |
| if (NfcConfig::hasKey(NAME_AID_FOR_EMPTY_SELECT)) { |
| std::vector<uint8_t> emptyAidVector; |
| emptyAidVector.resize(9); |
| emptyAidVector = NfcConfig::getBytes(NAME_AID_FOR_EMPTY_SELECT); |
| for(unsigned int i=0;i<emptyAidVector.size();i++) { |
| mAidForEmptySelect[i] = emptyAidVector[i]; |
| } |
| } |
| |
| mIsInit = true; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| return (true); |
| } |
| #if ((NXP_EXTNS == TRUE)) |
| /******************************************************************************* |
| ** |
| ** Function: updateEEStatus |
| ** |
| ** Description: updateEEStatus |
| ** Reads EE related information from libnfc |
| ** and updates in JNI |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::updateEEStatus() { |
| tNFA_STATUS nfaStat; |
| mActualNumEe = nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Enter", __func__); |
| |
| if (!getEeInfo()) return (false); |
| |
| // If the controller has an HCI Network, register for that |
| for (size_t xx = 0; xx < mActualNumEe; xx++) { |
| if ((!nfcFL.nfccFL._GEMALTO_SE_SUPPORT && |
| (mEeInfo[xx].ee_handle != EE_HANDLE_0xF4)) || |
| (nfcFL.nfccFL._GEMALTO_SE_SUPPORT && |
| (((mEeInfo[xx].ee_interface[0] == NCI_NFCEE_INTERFACE_HCI_ACCESS)) || |
| (NFA_GetNCIVersion() == NCI_VERSION_2_0)))) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Found HCI network, try hci register", __func__); |
| |
| SyncEventGuard guard(mHciRegisterEvent); |
| |
| nfaStat = |
| NFA_HciRegister(const_cast<char*>(APP_NAME), nfaHciCallback, true); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail hci register; error=0x%X", |
| __func__, nfaStat); |
| return (false); |
| } |
| mHciRegisterEvent.wait(); |
| break; |
| } |
| } |
| |
| if (NfcConfig::hasKey(NAME_AID_FOR_EMPTY_SELECT)) { |
| std::vector<uint8_t> emptyAidVector; |
| emptyAidVector.resize(9); |
| emptyAidVector = NfcConfig::getBytes(NAME_AID_FOR_EMPTY_SELECT); |
| for(unsigned int i=0;i < emptyAidVector.size();i++) { |
| mAidForEmptySelect[i] = emptyAidVector[i]; |
| } |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); |
| return (true); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: isTeckInfoReceived |
| ** |
| ** Description: isTeckInfoReceived |
| ** Checks if discovery_req_ntf received |
| ** for a given EE |
| ** |
| ** Returns: True if discovery_req_ntf is received. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::isTeckInfoReceived(uint16_t eeHandle) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); |
| bool stat = false; |
| if (!getEeInfo()) { |
| LOG(ERROR) << StringPrintf("%s: No updated eeInfo available", __func__); |
| stat = false; |
| } else { |
| for (uint8_t xx = 0; xx < mActualNumEe; xx++) { |
| if ((mEeInfo[xx].ee_handle == eeHandle) && |
| ((mEeInfo[xx].la_protocol != 0x00) || |
| (mEeInfo[xx].lb_protocol != 0x00) || |
| (mEeInfo[xx].lf_protocol != 0x00) || |
| (mEeInfo[xx].lbp_protocol != 0x00))) { |
| stat = true; |
| break; |
| } |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: stat : 0x%02x", __func__, stat); |
| return stat; |
| } |
| #endif |
| /******************************************************************************* |
| ** |
| ** Function: finalize |
| ** |
| ** Description: Release all resources. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::finalize() { |
| static const char fn[] = "SecureElement::finalize"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| |
| /* if (mNfaHciHandle != NFA_HANDLE_INVALID) |
| NFA_HciDeregister (const_cast<char*>(APP_NAME));*/ |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| NfccStandByOperation(STANDBY_TIMER_STOP); |
| } |
| #endif |
| |
| mNfaHciHandle = NFA_HANDLE_INVALID; |
| mNativeData = NULL; |
| mIsInit = false; |
| mActualNumEe = 0; |
| mNewPipeId = 0; |
| mNewSourceGate = 0; |
| mIsPiping = false; |
| memset(mEeInfo, 0, sizeof(mEeInfo)); |
| memset(&mUiccInfo, 0, sizeof(mUiccInfo)); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getEeInfo |
| ** |
| ** Description: Get latest information about execution environments from |
| *stack. |
| ** |
| ** Returns: True if at least 1 EE is available. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::getEeInfo() { |
| static const char fn[] = "SecureElement::getEeInfo"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; mbNewEE=%d, mActualNumEe=%d", fn, mbNewEE, mActualNumEe); |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| |
| /*Reading latest eEinfo incase it is updated*/ |
| #if (NXP_EXTNS == TRUE) |
| mbNewEE = true; |
| uint8_t eeIndex = 0; |
| #endif |
| // If mbNewEE is true then there is new EE info. |
| if (mbNewEE) { |
| #if (NXP_EXTNS == TRUE) |
| memset(&mNfceeData_t, 0, sizeof(mNfceeData_t)); |
| #endif |
| |
| mActualNumEe = nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED; |
| tNFA_EE_INFO eeInfo[MAX_NUM_EE]; |
| memset(&eeInfo, 0, nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED * sizeof(tNFA_EE_INFO)); |
| if ((nfaStat = NFA_EeGetInfo(&mActualNumEe, eeInfo)) != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail get info; error=0x%X", fn, nfaStat); |
| mActualNumEe = 0; |
| } else { |
| mbNewEE = false; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: num EEs discovered: %u", fn, mActualNumEe); |
| if (mActualNumEe != 0) { |
| for (uint8_t xx = 0; xx < mActualNumEe; xx++) { |
| if (eeInfo[xx].ee_interface[0] != NCI_NFCEE_INTERFACE_HCI_ACCESS) { |
| mEeInfo[eeIndex]=eeInfo[xx]; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: EE[%u] Handle: 0x%04x Status: %s Num I/f: %u: (0x%02x, " |
| "0x%02x) Num TLVs: %u, Tech : (LA:0x%02x, LB:0x%02x, " |
| "LF:0x%02x, LBP:0x%02x)", |
| fn, eeIndex, mEeInfo[eeIndex].ee_handle, |
| eeStatusToString(mEeInfo[eeIndex].ee_status), |
| mEeInfo[eeIndex].num_interface, mEeInfo[eeIndex].ee_interface[0], |
| mEeInfo[eeIndex].ee_interface[1], mEeInfo[eeIndex].num_tlvs, |
| mEeInfo[eeIndex].la_protocol, mEeInfo[eeIndex].lb_protocol, |
| mEeInfo[eeIndex].lf_protocol, mEeInfo[eeIndex].lbp_protocol); |
| #if (NXP_EXTNS == TRUE) |
| mNfceeData_t.mNfceeHandle[eeIndex] = mEeInfo[eeIndex].ee_handle; |
| mNfceeData_t.mNfceeStatus[eeIndex] = mEeInfo[eeIndex].ee_status; |
| #endif |
| for (size_t yy = 0; yy < mEeInfo[eeIndex].num_tlvs; yy++) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: EE[%u] TLV[%lu] Tag: 0x%02x Len: %u Values[]: 0x%02x " |
| "0x%02x 0x%02x ...", |
| fn, eeIndex, yy, mEeInfo[eeIndex].ee_tlv[yy].tag, |
| mEeInfo[eeIndex].ee_tlv[yy].len, mEeInfo[eeIndex].ee_tlv[yy].info[0], |
| mEeInfo[eeIndex].ee_tlv[yy].info[1], mEeInfo[eeIndex].ee_tlv[yy].info[2]); |
| } |
| eeIndex++; |
| } |
| } |
| } |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; mActualNumEe=%d, NumEePresent=%d", fn, |
| mActualNumEe, eeIndex); |
| |
| #if (NXP_EXTNS == TRUE) |
| mNfceeData_t.mNfceePresent = eeIndex; |
| #endif |
| |
| return (mActualNumEe != 0); |
| } |
| /******************************************************************************* |
| ** |
| ** Function: activateAllNfcee |
| ** |
| ** Description: Activate all Nfcee present/connected to NFCC. |
| ** |
| ** Returns: True/False based on activation status. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::activateAllNfcee() { |
| static const char fn[] = "SecureElement::activateAllNfcee"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| int numActivatedEe = 0; |
| uint8_t numEe = SecureElement::MAX_NUM_EE; |
| tNFA_EE_INFO mEeInfo[numEe]; |
| |
| if ((nfaStat = NFA_AllEeGetInfo(&numEe, mEeInfo)) != NFA_STATUS_OK) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s failed to get info, error = 0x%X ", __func__, nfaStat); |
| mActualNumEe = 0; |
| return false; |
| } |
| { |
| if (numEe != 0) { |
| for (uint8_t xx = 0; xx < numEe; xx++) { |
| tNFA_EE_INFO& eeItem = mEeInfo[xx]; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: set EE mode activate; h=0x%X status : %d interface : 0x%X", fn, |
| eeItem.ee_handle, eeItem.ee_status, eeItem.ee_interface[0]); |
| if (eeItem.ee_status != NFC_NFCEE_STATUS_INACTIVE || |
| eeItem.ee_interface[0] == NCI_NFCEE_INTERFACE_HCI_ACCESS) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: h=0x%X already activated", fn, eeItem.ee_handle); |
| numActivatedEe++; |
| continue; |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: set EE mode activate; h=0x%X", fn, eeItem.ee_handle); |
| if ((nfaStat = SecElem_EeModeSet( |
| eeItem.ee_handle, NFA_EE_MD_ACTIVATE)) == NFA_STATUS_OK) { |
| if (eeItem.ee_status == NFC_NFCEE_STATUS_ACTIVE) numActivatedEe++; |
| } |
| } |
| } |
| } |
| } |
| return (nfaStat == NFA_STATUS_OK ? true : false); |
| } |
| /******************************************************************************* |
| ** |
| ** Function TimeDiff |
| ** |
| ** Description Computes time difference in milliseconds. |
| ** |
| ** Returns Time difference in milliseconds |
| ** |
| *******************************************************************************/ |
| static uint32_t TimeDiff(timespec start, timespec end) { |
| end.tv_sec -= start.tv_sec; |
| end.tv_nsec -= start.tv_nsec; |
| |
| if (end.tv_nsec < 0) { |
| end.tv_nsec += 10e8; |
| end.tv_sec -= 1; |
| } |
| |
| return (end.tv_sec * 1000) + (end.tv_nsec / 10e5); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: isRfFieldOn |
| ** |
| ** Description: Can be used to determine if the SE is in an RF field |
| ** |
| ** Returns: True if the SE is activated in an RF field |
| ** |
| *******************************************************************************/ |
| bool SecureElement::isRfFieldOn() { |
| AutoMutex mutex(mMutex); |
| if (mRfFieldIsOn) { |
| return true; |
| } |
| struct timespec now; |
| int ret = clock_gettime(CLOCK_MONOTONIC, &now); |
| if (ret == -1) { |
| LOG(ERROR) << StringPrintf("isRfFieldOn(): clock_gettime failed"); |
| return false; |
| } |
| if (TimeDiff(mLastRfFieldToggle, now) < 50) { |
| // If it was less than 50ms ago that RF field |
| // was turned off, still return ON. |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: setEseListenTechMask |
| ** |
| ** Description: Can be used to force ESE to only listen the specific |
| ** Technologies. |
| ** NFA_TECHNOLOGY_MASK_A 0x01 |
| ** NFA_TECHNOLOGY_MASK_B 0x02 |
| ** |
| ** Returns: True if listening is configured. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::setEseListenTechMask(uint8_t tech_mask) { |
| static const char fn[] = "SecureElement::setEseListenTechMask"; |
| tNFA_STATUS nfaStat; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| |
| if (!mIsInit) { |
| LOG(ERROR) << StringPrintf("%s: not init", fn); |
| return false; |
| } |
| |
| { |
| SyncEventGuard guard(SecureElement::getInstance().mEseListenEvent); |
| nfaStat = NFA_CeConfigureEseListenTech(EE_HANDLE_0xF3, (0x00)); |
| if (nfaStat == NFA_STATUS_OK) { |
| SecureElement::getInstance().mEseListenEvent.wait(); |
| return true; |
| } else |
| LOG(ERROR) << StringPrintf("fail to stop ESE listen"); |
| } |
| |
| { |
| SyncEventGuard guard(SecureElement::getInstance().mEseListenEvent); |
| nfaStat = NFA_CeConfigureEseListenTech(EE_HANDLE_0xF3, (tech_mask)); |
| if (nfaStat == NFA_STATUS_OK) { |
| SecureElement::getInstance().mEseListenEvent.wait(); |
| return true; |
| } else |
| LOG(ERROR) << StringPrintf("fail to start ESE listen"); |
| } |
| |
| return false; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: isActivatedInListenMode |
| ** |
| ** Description: Can be used to determine if the SE is activated in listen |
| *mode |
| ** |
| ** Returns: True if the SE is activated in listen mode |
| ** |
| *******************************************************************************/ |
| bool SecureElement::isActivatedInListenMode() { return mActivatedInListenMode; } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getListOfEeHandles |
| ** |
| ** Description: Get the list of handles of all execution environments. |
| ** e: Java Virtual Machine. |
| ** |
| ** Returns: List of handles of all execution environments. |
| ** |
| *******************************************************************************/ |
| jintArray SecureElement::getListOfEeHandles(JNIEnv* e) { |
| static const char fn[] = "SecureElement::getListOfEeHandles"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| if (mNfceeData_t.mNfceePresent == 0) return NULL; |
| |
| if (!mIsInit) { |
| LOG(ERROR) << StringPrintf("%s: not init", fn); |
| return (NULL); |
| } |
| |
| // Get Fresh EE info. |
| if (!getEeInfo()) return (NULL); |
| |
| jintArray list = e->NewIntArray(mNfceeData_t.mNfceePresent); // allocate array |
| jint jj = 0; |
| int cnt = 0; |
| for (int ii = 0; ii < mActualNumEe && cnt < mNfceeData_t.mNfceePresent; ii++) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: %u = 0x%X", fn, ii, mEeInfo[ii].ee_handle); |
| if (mEeInfo[ii].ee_interface[0] == NCI_NFCEE_INTERFACE_HCI_ACCESS) { |
| continue; |
| } |
| |
| jj = mEeInfo[ii].ee_handle & ~NFA_HANDLE_GROUP_EE; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Handle %u = 0x%X", fn, ii, jj); |
| |
| jj = getGenericEseId(jj); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Generic id %u = 0x%X", fn, ii, jj); |
| e->SetIntArrayRegion(list, cnt++, 1, &jj); |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| return list; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getActiveSecureElementList |
| ** |
| ** Description: Get the list of Activated Secure elements. |
| ** e: Java Virtual Machine. |
| ** |
| ** Returns: List of Activated Secure elements. |
| ** |
| *******************************************************************************/ |
| jintArray SecureElement::getActiveSecureElementList(JNIEnv* e) { |
| uint8_t num_of_nfcee_present = 0; |
| tNFA_HANDLE nfcee_handle[MAX_NFCEE]; |
| tNFA_EE_STATUS nfcee_status[MAX_NFCEE]; |
| jint seId = 0; |
| int cnt = 0; |
| int i; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); |
| |
| if (!getEeInfo()) return (NULL); |
| |
| num_of_nfcee_present = mNfceeData_t.mNfceePresent; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: num_of_nfcee_present:%d", __func__, num_of_nfcee_present); |
| |
| jintArray list = e->NewIntArray(num_of_nfcee_present); // allocate array |
| |
| for (i = 0; i < num_of_nfcee_present; i++) { |
| nfcee_handle[i] = mNfceeData_t.mNfceeHandle[i]; |
| nfcee_status[i] = mNfceeData_t.mNfceeStatus[i]; |
| |
| if (nfcee_handle[i] == EE_HANDLE_0xF3 && |
| nfcee_status[i] == NFC_NFCEE_STATUS_ACTIVE) { |
| seId = getGenericEseId(EE_HANDLE_0xF3 & ~NFA_HANDLE_GROUP_EE); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: eSE Active", __func__); |
| } |
| |
| if (nfcee_handle[i] == EE_HANDLE_0xF4 && |
| nfcee_status[i] == NFC_NFCEE_STATUS_ACTIVE) { |
| seId = getGenericEseId(EE_HANDLE_0xF4 & ~NFA_HANDLE_GROUP_EE); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: UICC/SIM/SIM1 Active", __func__); |
| } |
| |
| if (nfcee_handle[i] == EE_HANDLE_0xF8 && |
| nfcee_status[i] == NFC_NFCEE_STATUS_ACTIVE) { |
| seId = getGenericEseId(EE_HANDLE_0xF8 & ~NFA_HANDLE_GROUP_EE); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: UICC/SIM/SIM1 Active", __func__); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Generic-ID %u = 0x%02X", __func__, i, seId); |
| e->SetIntArrayRegion(list, cnt++, 1, &seId); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); |
| return list; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: activate |
| ** |
| ** Description: Turn on the secure element. |
| ** seID: ID of secure element; 0xF3 or 0xF4. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::activate(jint seID) { |
| static const char fn[] = "SecureElement::activate"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| int numActivatedEe = 0; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; seID=0x%X", fn, seID); |
| |
| tNFA_HANDLE handle = getEseHandleFromGenericId(seID); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: handle=0x%X", fn, handle); |
| |
| if (!mIsInit) { |
| LOG(ERROR) << StringPrintf("%s: not init", fn); |
| return false; |
| } |
| |
| // if (mActiveEeHandle != NFA_HANDLE_INVALID) |
| //{ |
| // DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: already active", |
| // fn); |
| // return true; |
| //} |
| |
| // Get Fresh EE info if needed. |
| if (!getEeInfo()) { |
| LOG(ERROR) << StringPrintf("%s: no EE info", fn); |
| return false; |
| } |
| |
| uint16_t overrideEeHandle = 0; |
| // If the Active SE is overridden |
| if (mActiveSeOverride && (mActiveSeOverride != ACTIVE_SE_USE_ANY)) |
| overrideEeHandle = NFA_HANDLE_GROUP_EE | mActiveSeOverride; |
| else // NXP |
| overrideEeHandle = handle; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: override ee h=0x%X", fn, overrideEeHandle); |
| |
| if (!nfcFL.nfcNxpEse && mRfFieldIsOn) { |
| LOG(ERROR) << StringPrintf("%s: RF field indication still on, resetting", |
| fn); |
| mRfFieldIsOn = false; |
| } |
| |
| // activate every discovered secure element |
| for (int index = 0; index < mActualNumEe; index++) { |
| tNFA_EE_INFO& eeItem = mEeInfo[index]; |
| |
| if ((eeItem.ee_handle == EE_HANDLE_0xF3) || |
| (eeItem.ee_handle == EE_HANDLE_0xF4) || |
| (nfcFL.nfccFL._NFCC_DYNAMIC_DUAL_UICC && |
| (eeItem.ee_handle == EE_HANDLE_0xF8))) { |
| if (overrideEeHandle && (overrideEeHandle != eeItem.ee_handle)) |
| continue; // do not enable all SEs; only the override one |
| |
| if (eeItem.ee_status != NFC_NFCEE_STATUS_INACTIVE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: h=0x%X already activated", fn, eeItem.ee_handle); |
| numActivatedEe++; |
| continue; |
| } |
| |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: set EE mode activate; h=0x%X", fn, eeItem.ee_handle); |
| #if (NXP_EXTNS == TRUE) |
| if ((nfaStat = SecElem_EeModeSet( |
| eeItem.ee_handle, NFA_EE_MD_ACTIVATE)) == NFA_STATUS_OK) { |
| if (eeItem.ee_status == NFC_NFCEE_STATUS_ACTIVE) numActivatedEe++; |
| if (eeItem.ee_handle == EE_HANDLE_0xF3) { |
| SyncEventGuard guard(SecureElement::getInstance().mModeSetNtf); |
| if (SecureElement::getInstance().mModeSetNtf.wait(500) == false) { |
| LOG(ERROR) << StringPrintf("%s: timeout waiting for setModeNtf", |
| __func__); |
| } |
| } |
| } else |
| #endif |
| LOG(ERROR) << StringPrintf("%s: NFA_EeModeSet failed; error=0x%X", fn, |
| nfaStat); |
| } |
| } |
| } // for |
| #if (NXP_EXTNS == TRUE) |
| mActiveEeHandle = getActiveEeHandle(handle); |
| #else |
| mActiveEeHandle = getDefaultEeHandle(); |
| #endif |
| |
| if (mActiveEeHandle == NFA_HANDLE_INVALID) |
| LOG(ERROR) << StringPrintf("%s: ee handle not found", fn); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; active ee h=0x%X", fn, mActiveEeHandle); |
| return mActiveEeHandle != NFA_HANDLE_INVALID; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: deactivate |
| ** |
| ** Description: Turn off the secure element. |
| ** seID: ID of secure element; 0xF3 or 0xF4. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::deactivate(jint seID) { |
| static const char fn[] = "SecureElement::deactivate"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| bool retval = false; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; seID=0x%X, mActiveEeHandle=0x%X", fn, seID, mActiveEeHandle); |
| |
| tNFA_HANDLE handle = getEseHandleFromGenericId(seID); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: handle=0x%X", fn, handle); |
| |
| if (!mIsInit) { |
| LOG(ERROR) << StringPrintf("%s: not init", fn); |
| goto TheEnd; |
| } |
| |
| // if the controller is routing to sec elems or piping, |
| // then the secure element cannot be deactivated |
| if ((mCurrentRouteSelection == SecElemRoute) || mIsPiping) { |
| LOG(ERROR) << StringPrintf("%s: still busy", fn); |
| goto TheEnd; |
| } |
| |
| // if (mActiveEeHandle == NFA_HANDLE_INVALID) |
| // { |
| // LOG(ERROR) << StringPrintf("%s: invalid EE handle", fn); |
| // goto TheEnd; |
| // } |
| |
| if (seID == NFA_HANDLE_INVALID) { |
| LOG(ERROR) << StringPrintf("%s: invalid EE handle", fn); |
| goto TheEnd; |
| } |
| |
| mActiveEeHandle = NFA_HANDLE_INVALID; |
| |
| // NXP |
| // deactivate secure element |
| for (int index = 0; index < mActualNumEe; index++) { |
| tNFA_EE_INFO& eeItem = mEeInfo[index]; |
| |
| if (eeItem.ee_handle == handle && |
| ((eeItem.ee_handle == EE_HANDLE_0xF3) || |
| (eeItem.ee_handle == EE_HANDLE_0xF4) || |
| (nfcFL.nfccFL._NFCC_DYNAMIC_DUAL_UICC && |
| (eeItem.ee_handle == EE_HANDLE_0xF8)))) { |
| if (eeItem.ee_status == NFC_NFCEE_STATUS_INACTIVE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: h=0x%X already deactivated", fn, eeItem.ee_handle); |
| break; |
| } |
| |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: set EE mode activate; h=0x%X", fn, eeItem.ee_handle); |
| #if (NXP_EXTNS == TRUE) |
| if ((nfaStat = SecElem_EeModeSet( |
| eeItem.ee_handle, NFA_EE_MD_DEACTIVATE)) == NFA_STATUS_OK) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: eeItem.ee_status =0x%X NFC_NFCEE_STATUS_INACTIVE = %x", fn, |
| eeItem.ee_status, NFC_NFCEE_STATUS_INACTIVE); |
| if (eeItem.ee_status == NFC_NFCEE_STATUS_INACTIVE) { |
| LOG(ERROR) << StringPrintf("%s: NFA_EeModeSet success; status=0x%X", |
| fn, nfaStat); |
| retval = true; |
| } |
| } else |
| #endif |
| LOG(ERROR) << StringPrintf("%s: NFA_EeModeSet failed; error=0x%X", fn, |
| nfaStat); |
| } |
| } |
| } // for |
| |
| TheEnd: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; ok=%u", fn, retval); |
| return retval; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: notifyTransactionListenersOfAid |
| ** |
| ** Description: Notify the NFC service about a transaction event from secure |
| *element. |
| ** aid: Buffer contains application ID. |
| ** aidLen: Length of application ID. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::notifyTransactionListenersOfAid(const uint8_t* aidBuffer, |
| uint8_t aidBufferLen, |
| const uint8_t* dataBuffer, |
| uint32_t dataBufferLen, |
| uint32_t evtSrc) { |
| static const char fn[] = "SecureElement::notifyTransactionListenersOfAid"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; aid len=%u data len=%u", fn, aidBufferLen, dataBufferLen); |
| |
| if (aidBufferLen == 0) { |
| return; |
| } |
| |
| JNIEnv* e = NULL; |
| ScopedAttach attach(mNativeData->vm, &e); |
| if (e == NULL) { |
| LOG(ERROR) << StringPrintf("%s: jni env is null", fn); |
| return; |
| } |
| |
| const uint16_t tlvMaxLen = aidBufferLen + 10; |
| uint8_t* tlv = new uint8_t[tlvMaxLen]; |
| if (tlv == NULL) { |
| LOG(ERROR) << StringPrintf("%s: fail allocate tlv", fn); |
| return; |
| } |
| |
| memcpy(tlv, aidBuffer, aidBufferLen); |
| uint16_t tlvActualLen = aidBufferLen; |
| |
| ScopedLocalRef<jobject> tlvJavaArray(e, e->NewByteArray(tlvActualLen)); |
| if (tlvJavaArray.get() == NULL) { |
| LOG(ERROR) << StringPrintf("%s: fail allocate array", fn); |
| goto TheEnd; |
| } |
| |
| e->SetByteArrayRegion((jbyteArray)tlvJavaArray.get(), 0, tlvActualLen, |
| (jbyte*)tlv); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail fill array", fn); |
| goto TheEnd; |
| } |
| |
| if (dataBufferLen > 0) { |
| const uint32_t dataTlvMaxLen = dataBufferLen + 10; |
| uint8_t* datatlv = new uint8_t[dataTlvMaxLen]; |
| if (datatlv == NULL) { |
| LOG(ERROR) << StringPrintf("%s: fail allocate tlv", fn); |
| return; |
| } |
| |
| memcpy(datatlv, dataBuffer, dataBufferLen); |
| uint16_t dataTlvActualLen = dataBufferLen; |
| |
| ScopedLocalRef<jobject> dataTlvJavaArray(e, |
| e->NewByteArray(dataTlvActualLen)); |
| if (dataTlvJavaArray.get() == NULL) { |
| LOG(ERROR) << StringPrintf("%s: fail allocate array", fn); |
| goto Clean; |
| } |
| |
| e->SetByteArrayRegion((jbyteArray)dataTlvJavaArray.get(), 0, |
| dataTlvActualLen, (jbyte*)datatlv); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail fill array", fn); |
| goto Clean; |
| } |
| |
| e->CallVoidMethod(mNativeData->manager, |
| android::gCachedNfcManagerNotifyTransactionListeners, |
| tlvJavaArray.get(), dataTlvJavaArray.get(), evtSrc); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail notify", fn); |
| goto Clean; |
| } |
| |
| Clean: |
| delete[] datatlv; |
| } else { |
| e->CallVoidMethod(mNativeData->manager, |
| android::gCachedNfcManagerNotifyTransactionListeners, |
| tlvJavaArray.get(), NULL, evtSrc); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail notify", fn); |
| goto TheEnd; |
| } |
| } |
| TheEnd: |
| delete[] tlv; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: notifyEmvcoMultiCardDetectedListeners |
| ** |
| ** Description: Notify the NFC service about a multiple card presented to |
| ** Emvco reader. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::notifyEmvcoMultiCardDetectedListeners() { |
| static const char fn[] = |
| "SecureElement::notifyEmvcoMultiCardDetectedListeners"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| |
| JNIEnv* e = NULL; |
| ScopedAttach attach(mNativeData->vm, &e); |
| if (e == NULL) { |
| LOG(ERROR) << StringPrintf("%s: jni env is null", fn); |
| return; |
| } |
| |
| e->CallVoidMethod( |
| mNativeData->manager, |
| android::gCachedNfcManagerNotifyEmvcoMultiCardDetectedListeners); |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail notify", fn); |
| goto TheEnd; |
| } |
| |
| TheEnd: |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: connectEE |
| ** |
| ** Description: Connect to the execution environment. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::connectEE() { |
| static const char fn[] = "SecureElement::connectEE"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| bool retVal = false; |
| uint8_t destHost = 0; |
| char pipeConfName[40]; |
| tNFA_HANDLE eeHandle = mActiveEeHandle; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter, mActiveEeHandle: 0x%04x, SEID: 0x%x, pipe_gate_num=%d, use " |
| "pipe=%d", |
| fn, mActiveEeHandle, gSEId, gGatePipe, gUseStaticPipe); |
| |
| if (!mIsInit) { |
| LOG(ERROR) << StringPrintf("%s: not init", fn); |
| return (false); |
| } |
| |
| if (gSEId != -1) { |
| eeHandle = gSEId | NFA_HANDLE_GROUP_EE; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Using SEID: 0x%x", fn, eeHandle); |
| } |
| |
| if (eeHandle == NFA_HANDLE_INVALID) { |
| LOG(ERROR) << StringPrintf("%s: invalid handle 0x%X", fn, eeHandle); |
| return (false); |
| } |
| |
| tNFA_EE_INFO* pEE = findEeByHandle(eeHandle); |
| |
| if (pEE == NULL) { |
| LOG(ERROR) << StringPrintf("%s: Handle 0x%04x NOT FOUND !!", fn, eeHandle); |
| return (false); |
| } |
| |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._ESE_WIRED_MODE_DISABLE_DISCOVERY) { |
| // Disable RF discovery completely while the DH is connected |
| android::startRfDiscovery(false); |
| } |
| } else { |
| android::startRfDiscovery(false); |
| } |
| #else |
| android::startRfDiscovery(false); |
| #endif |
| |
| // Disable UICC idle timeout while the DH is connected |
| // android::setUiccIdleTimeout (false); |
| |
| mNewSourceGate = 0; |
| |
| if (gGatePipe == -1) { |
| // pipe/gate num was not specifed by app, get from config file |
| mNewPipeId = 0; |
| |
| // Construct the PIPE name based on the EE handle (e.g. |
| // NFA_HCI_STATIC_PIPE_ID_F3 for UICC0). |
| if(eeHandle == 0x4C0) { |
| snprintf(pipeConfName, sizeof(pipeConfName), "OFF_HOST_ESE_PIPE_ID"); |
| } |
| else { |
| snprintf(pipeConfName, sizeof(pipeConfName), "OFF_HOST_SIM_PIPE_ID"); |
| } |
| |
| if (NfcConfig::hasKey(pipeConfName)) { |
| mNewPipeId = NfcConfig::getUnsigned(pipeConfName); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Using static pipe id: 0x%X", __func__, mNewPipeId); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Did not find value '%s' defined in the .conf", |
| __func__, pipeConfName); |
| } |
| } else { |
| if (gUseStaticPipe) { |
| mNewPipeId = gGatePipe; |
| } else { |
| mNewPipeId = 0; |
| mDestinationGate = gGatePipe; |
| } |
| } |
| |
| // If the .conf file had a static pipe to use, just use it. |
| if (mNewPipeId != 0) { |
| #if (NXP_EXTNS == TRUE) |
| uint8_t host; |
| if (mActiveEeHandle == EE_HANDLE_0xF3) { |
| host = (mNewPipeId == mStaticPipeProp) ? 0xC0 : 0x03; |
| } else { |
| host = (mNewPipeId == STATIC_PIPE_UICC) ? 0x02 : 0x03; |
| } |
| #else |
| uint8_t host = (mNewPipeId == mStaticPipeProp) ? 0x02 : 0x03; |
| #endif |
| // TODO according ETSI12 APDU Gate |
| #if (NXP_EXTNS == TRUE) |
| uint8_t gate; |
| if (mActiveEeHandle == EE_HANDLE_0xF3) { |
| gate = (mNewPipeId == mStaticPipeProp) ? 0xF0 : 0xF1; |
| } else { |
| gate = (mNewPipeId == STATIC_PIPE_UICC) ? 0x30 : 0x31; |
| } |
| #else |
| uint8_t gate = (mNewPipeId == mStaticPipeProp) ? 0xF0 : 0xF1; |
| #endif |
| #if (NXP_EXTNS == TRUE) |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Using host id : 0x%X,gate id : 0x%X,pipe id : 0x%X", __func__, |
| host, gate, mNewPipeId); |
| #endif |
| if (nfcFL.eseFL._LEGACY_APDU_GATE && |
| (getApduGateInfo() != ETSI_12_APDU_GATE)) { |
| nfaStat = NFA_HciAddStaticPipe(mNfaHciHandle, host, gate, mNewPipeId); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail create static pipe; error=0x%X", |
| fn, nfaStat); |
| retVal = false; |
| goto TheEnd; |
| } |
| } |
| } else { |
| if ((pEE->num_tlvs >= 1) && (pEE->ee_tlv[0].tag == NFA_EE_TAG_HCI_HOST_ID)) |
| destHost = pEE->ee_tlv[0].info[0]; |
| else |
| #if (NXP_EXTNS == TRUE) |
| destHost = (EE_HANDLE_0xF3 & ~NFA_HANDLE_GROUP_EE); |
| #else |
| destHost = 2; |
| #endif |
| |
| // Get a list of existing gates and pipes |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: get gate, pipe list", fn); |
| SyncEventGuard guard(mPipeListEvent); |
| nfaStat = NFA_HciGetGateAndPipeList(mNfaHciHandle); |
| if (nfaStat == NFA_STATUS_OK) { |
| mPipeListEvent.wait(); |
| if (mHciCfg.status == NFA_STATUS_OK) { |
| for (uint8_t xx = 0; xx < mHciCfg.num_pipes; xx++) { |
| if ((mHciCfg.pipe[xx].dest_host == destHost) && |
| (mHciCfg.pipe[xx].dest_gate == mDestinationGate)) { |
| mNewSourceGate = mHciCfg.pipe[xx].local_gate; |
| mNewPipeId = mHciCfg.pipe[xx].pipe_id; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: found configured gate: 0x%02x pipe: 0x%02x", fn, |
| mNewSourceGate, mNewPipeId); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| if (mNewSourceGate == 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: allocate gate", fn); |
| // allocate a source gate and store in mNewSourceGate |
| SyncEventGuard guard(mAllocateGateEvent); |
| if ((nfaStat = NFA_HciAllocGate(mNfaHciHandle, mDestinationGate)) != |
| NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail allocate source gate; error=0x%X", |
| fn, nfaStat); |
| goto TheEnd; |
| } |
| mAllocateGateEvent.wait(); |
| if (mCommandStatus != NFA_STATUS_OK) goto TheEnd; |
| } |
| |
| if (mNewPipeId == 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: create pipe", fn); |
| SyncEventGuard guard(mCreatePipeEvent); |
| nfaStat = NFA_HciCreatePipe(mNfaHciHandle, mNewSourceGate, destHost, |
| mDestinationGate); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail create pipe; error=0x%X", fn, |
| nfaStat); |
| goto TheEnd; |
| } |
| mCreatePipeEvent.wait(); |
| if (mCommandStatus != NFA_STATUS_OK) goto TheEnd; |
| } |
| |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: open pipe", fn); |
| SyncEventGuard guard(mPipeOpenedEvent); |
| nfaStat = NFA_HciOpenPipe(mNfaHciHandle, mNewPipeId); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf("%s: fail open pipe; error=0x%X", fn, |
| nfaStat); |
| goto TheEnd; |
| } |
| mPipeOpenedEvent.wait(); |
| if (mCommandStatus != NFA_STATUS_OK) goto TheEnd; |
| } |
| } |
| |
| retVal = true; |
| |
| TheEnd: |
| mIsPiping = retVal; |
| if (!retVal) { |
| // if open failed we need to de-allocate the gate |
| disconnectEE(0); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; ok=%u", fn, retVal); |
| return retVal; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: disconnectEE |
| ** |
| ** Description: Disconnect from the execution environment. |
| ** seID: ID of secure element. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::disconnectEE(jint seID) { |
| static const char fn[] = "SecureElement::disconnectEE"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| tNFA_HANDLE eeHandle = seID; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: seID=0x%X; handle=0x%04x", fn, seID, eeHandle); |
| |
| if (mUseOberthurWarmReset) { |
| // send warm-reset command to Oberthur secure element which deselects the |
| // applet; |
| // this is an Oberthur-specific command; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: try warm-reset on pipe id 0x%X; cmd=0x%X", fn, |
| mNewPipeId, mOberthurWarmResetCommand); |
| SyncEventGuard guard(mRegistryEvent); |
| nfaStat = NFA_HciSetRegistry(mNfaHciHandle, mNewPipeId, 1, 1, |
| &mOberthurWarmResetCommand); |
| if (nfaStat == NFA_STATUS_OK) { |
| mRegistryEvent.wait(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: completed warm-reset on pipe 0x%X", fn, mNewPipeId); |
| } |
| } |
| |
| if (mNewSourceGate && (mNewSourceGate != NFA_HCI_ETSI12_APDU_GATE)) { |
| SyncEventGuard guard(mDeallocateGateEvent); |
| if ((nfaStat = NFA_HciDeallocGate(mNfaHciHandle, mNewSourceGate)) == |
| NFA_STATUS_OK) |
| mDeallocateGateEvent.wait(); |
| else |
| LOG(ERROR) << StringPrintf("%s: fail dealloc gate; error=0x%X", fn, |
| nfaStat); |
| } |
| |
| mIsPiping = false; |
| |
| if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE && nfcFL.eseFL._ESE_SVDD_SYNC && |
| (dual_mode_current_state & SPI_ON)) { |
| /*The state of the SPI should not be cleared based on DWP state close. |
| * dual_mode_current_state updated in spi_prio_signal_handler function.*/ |
| /*clear the SPI transaction flag*/ |
| dual_mode_current_state ^= SPI_ON; |
| } |
| |
| hold_the_transceive = false; |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| hold_wired_mode = false; |
| } |
| #endif |
| |
| // Re-enable UICC low-power mode |
| // Re-enable RF discovery |
| // Note that it only effactuates the current configuration, |
| // so if polling/listening were configured OFF (forex because |
| // the screen was off), they will stay OFF with this call. |
| /*Blocked as part done in connectEE, to allow wired mode during reader |
| * mode.*/ |
| if (nfcFL.nfcNxpEse && nfcFL.chipType != pn547C2) { |
| // Do Nothing |
| } else { |
| android::setUiccIdleTimeout(true); |
| android::startRfDiscovery(true); |
| } |
| |
| return true; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: transceive |
| ** |
| ** Description: Send data to the secure element; read it's response. |
| ** xmitBuffer: Data to transmit. |
| ** xmitBufferSize: Length of data. |
| ** recvBuffer: Buffer to receive response. |
| ** recvBufferMaxSize: Maximum size of buffer. |
| ** recvBufferActualSize: Actual length of response. |
| ** timeoutMillisec: timeout in millisecond. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| #if (NXP_EXTNS == TRUE) |
| eTransceiveStatus SecureElement::transceive(uint8_t* xmitBuffer, |
| int32_t xmitBufferSize, |
| uint8_t* recvBuffer, |
| int32_t recvBufferMaxSize, |
| int32_t& recvBufferActualSize, |
| int32_t timeoutMillisec) |
| #else |
| bool SecureElement::transceive(uint8_t* xmitBuffer, int32_t xmitBufferSize, |
| uint8_t* recvBuffer, int32_t recvBufferMaxSize, |
| int32_t& recvBufferActualSize, |
| int32_t timeoutMillisec) |
| #endif |
| { |
| |
| static const char fn[] = "SecureElement::transceive"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| mTransceiveWaitOk = false; |
| uint8_t newSelectCmd[NCI_MAX_AID_LEN + 10]; |
| #if (NXP_EXTNS == TRUE) |
| eTransceiveStatus tranStatus = TRANSCEIVE_STATUS_FAILED; |
| #else |
| bool isSuccess = false; |
| #endif |
| #if (NXP_EXTNS == TRUE) |
| bool isEseAccessSuccess = false; |
| #endif |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: enter; xmitBufferSize=%d; recvBufferMaxSize=%d; timeout=%d", fn, |
| xmitBufferSize, recvBufferMaxSize, timeoutMillisec); |
| |
| // Check if we need to replace an "empty" SELECT command. |
| // 1. Has there been a AID configured, and |
| // 2. Is that AID a valid length (i.e 16 bytes max), and |
| // 3. Is the APDU at least 4 bytes (for header), and |
| // 4. Is INS == 0xA4 (SELECT command), and |
| // 5. Is P1 == 0x04 (SELECT by AID), and |
| // 6. Is the APDU len 4 or 5 bytes. |
| // |
| // Note, the length of the configured AID is in the first |
| // byte, and AID starts from the 2nd byte. |
| if (mAidForEmptySelect[0] // 1 |
| && (mAidForEmptySelect[0] <= NCI_MAX_AID_LEN) // 2 |
| && (xmitBufferSize >= 4) // 3 |
| && (xmitBuffer[1] == 0xA4) // 4 |
| && (xmitBuffer[2] == 0x04) // 5 |
| && (xmitBufferSize <= 5)) // 6 |
| { |
| uint8_t idx = 0; |
| |
| // Copy APDU command header from the input buffer. |
| memcpy(&newSelectCmd[0], &xmitBuffer[0], 4); |
| idx = 4; |
| |
| // Set the Lc value to length of the new AID |
| newSelectCmd[idx++] = mAidForEmptySelect[0]; |
| |
| // Copy the AID |
| memcpy(&newSelectCmd[idx], &mAidForEmptySelect[1], mAidForEmptySelect[0]); |
| idx += mAidForEmptySelect[0]; |
| |
| // If there is an Le (5th byte of APDU), add it to the end. |
| if (xmitBufferSize == 5) newSelectCmd[idx++] = xmitBuffer[4]; |
| |
| // Point to the new APDU |
| xmitBuffer = &newSelectCmd[0]; |
| xmitBufferSize = idx; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Empty AID SELECT cmd detected, substituting AID from config file, " |
| "new length=%d", |
| fn, idx); |
| } |
| |
| #if (NXP_EXTNS == TRUE) |
| NfccStandByOperation(STANDBY_MODE_OFF); |
| #endif |
| { |
| SyncEventGuard guard(mTransceiveEvent); |
| mActualResponseSize = 0; |
| memset(recvBuffer, 0, recvBufferMaxSize); |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| struct timeval start_timer, end_timer; |
| int32_t time_elapsed = 0; |
| while (hold_the_transceive == true) { |
| android::start_timer_msec(&start_timer); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: holding the transceive for %d ms.\n", fn, |
| (timeoutMillisec - time_elapsed)); |
| SyncEventGuard guard(sSPIPrioSessionEndEvent); |
| if (sSPIPrioSessionEndEvent.wait(timeoutMillisec - time_elapsed) == |
| false) { |
| LOG(ERROR) << StringPrintf("%s: wait response timeout \n", fn); |
| time_elapsed = |
| android::stop_timer_getdifference_msec(&start_timer, &end_timer); |
| time_elapsed = 0; |
| goto TheEnd; |
| } |
| time_elapsed += |
| android::stop_timer_getdifference_msec(&start_timer, &end_timer); |
| if ((timeoutMillisec - time_elapsed) <= 0) { |
| LOG(ERROR) << StringPrintf( |
| "%s: wait response timeout - time_elapsed \n", fn); |
| time_elapsed = 0; |
| goto TheEnd; |
| } |
| } |
| } |
| #endif |
| if ((mNewPipeId == mStaticPipeProp) || (mNewPipeId == STATIC_PIPE_0x71)) |
| #if (NXP_EXTNS == TRUE) |
| { |
| if (nfcFL.nfccFL._NFCEE_REMOVED_NTF_RECOVERY) { |
| if ((RoutingManager::getInstance().is_ee_recovery_ongoing())) { |
| SyncEventGuard guard(mEEdatapacketEvent); |
| if (mEEdatapacketEvent.wait(timeoutMillisec) == false) goto TheEnd; |
| } |
| } |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME == |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME || |
| nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME == |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| if (!checkForWiredModeAccess()) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s, Dont allow wired mode in this RF state", fn); |
| goto TheEnd; |
| } |
| } |
| } |
| |
| if (((nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_2) || |
| (nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_3)) && |
| nfcFL.eseFL._TRIPLE_MODE_PROTECTION) { |
| if (dual_mode_current_state == SPI_DWPCL_BOTH_ACTIVE) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s, Dont allow wired mode...Dual Mode..", fn); |
| SyncEventGuard guard(mDualModeEvent); |
| mDualModeEvent.wait(); |
| } |
| } |
| |
| if (nfcFL.nfcNxpEse) { |
| active_ese_reset_control |= TRANS_WIRED_ONGOING; |
| if ((((nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_1) || |
| (nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_2))) && |
| (NFC_GetEseAccess((void*)&timeoutMillisec) != 0)) { |
| LOG(ERROR) << StringPrintf("%s: NFC_ReqWiredAccess timeout", fn); |
| goto TheEnd; |
| } |
| isEseAccessSuccess = true; |
| } |
| #endif |
| if (nfcFL.nfcNxpEse && |
| nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| isTransceiveOngoing = true; |
| } |
| nfaStat = NFA_HciSendEvent(mNfaHciHandle, mNewPipeId, EVT_SEND_DATA, |
| xmitBufferSize, xmitBuffer, recvBufferMaxSize, |
| recvBuffer, timeoutMillisec); |
| #if (NXP_EXTNS == TRUE) |
| } else if (mNewPipeId == STATIC_PIPE_UICC) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s, Starting UICC wired mode!!!!!!.....", fn); |
| nfaStat = NFA_HciSendEvent(mNfaHciHandle, mNewPipeId, EVT_SEND_DATA, |
| xmitBufferSize, xmitBuffer, recvBufferMaxSize, |
| recvBuffer, timeoutMillisec); |
| } |
| #endif |
| else |
| #if (NXP_EXTNS == TRUE) |
| { |
| if (nfcFL.nfcNxpEse) { |
| active_ese_reset_control |= TRANS_WIRED_ONGOING; |
| if (((nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_1) || |
| (nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_2)) && |
| (NFC_GetEseAccess((void*)&timeoutMillisec) != 0)) { |
| LOG(ERROR) << StringPrintf("%s: NFC_ReqWiredAccess timeout", fn); |
| goto TheEnd; |
| } |
| isEseAccessSuccess = true; |
| } |
| #endif |
| if (nfcFL.nfcNxpEse && |
| nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| isTransceiveOngoing = true; |
| } |
| nfaStat = NFA_HciSendEvent( |
| mNfaHciHandle, mNewPipeId, NFA_HCI_EVT_POST_DATA, xmitBufferSize, |
| xmitBuffer, recvBufferMaxSize, recvBuffer, timeoutMillisec); |
| #if (NXP_EXTNS == TRUE) |
| } |
| #endif |
| if (nfaStat == NFA_STATUS_OK) { |
| // waitOk = mTransceiveEvent.wait (timeoutMillisec); |
| mTransceiveEvent.wait(timeoutMillisec); |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse && (gWtxCount > mWmMaxWtxCount)) { |
| tranStatus = TRANSCEIVE_STATUS_MAX_WTX_REACHED; |
| gWtxCount = 0; |
| goto TheEnd; |
| } |
| #endif |
| if (nfcFL.nfcNxpEse && |
| nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| isTransceiveOngoing = false; |
| } |
| |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._JCOP_WA_ENABLE && |
| (active_ese_reset_control & TRANS_WIRED_ONGOING)) { |
| active_ese_reset_control ^= TRANS_WIRED_ONGOING; |
| |
| /*If only reset event is pending*/ |
| if ((active_ese_reset_control & RESET_BLOCKED)) { |
| SyncEventGuard guard(mResetOngoingEvent); |
| mResetOngoingEvent.wait(); |
| } |
| |
| if (!(active_ese_reset_control & TRANS_CL_ONGOING) && |
| (active_ese_reset_control & RESET_BLOCKED)) { |
| active_ese_reset_control ^= RESET_BLOCKED; |
| } |
| } |
| if (mTransceiveWaitOk == false) { |
| LOG(ERROR) << StringPrintf("%s: transceive timed out", fn); |
| goto TheEnd; |
| } |
| } |
| #endif |
| } else { |
| LOG(ERROR) << StringPrintf("%s: fail send data; error=0x%X", fn, nfaStat); |
| goto TheEnd; |
| } |
| } |
| if (mActualResponseSize > recvBufferMaxSize) |
| recvBufferActualSize = recvBufferMaxSize; |
| else |
| recvBufferActualSize = mActualResponseSize; |
| |
| #if (NXP_EXTNS == TRUE) |
| tranStatus = TRANSCEIVE_STATUS_OK; |
| #else |
| isSuccess = true; |
| #endif |
| TheEnd: |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if ((((nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_1) || |
| (nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_2))) && |
| isEseAccessSuccess == true) { |
| if (NFC_RelEseAccess((void*)&nfaStat) != 0) { |
| LOG(ERROR) << StringPrintf("%s: NFC_RelEseAccess failed", fn); |
| } |
| } |
| if ((nfcFL.eseFL._JCOP_WA_ENABLE) && |
| (active_ese_reset_control & TRANS_WIRED_ONGOING)) |
| active_ese_reset_control ^= TRANS_WIRED_ONGOING; |
| } |
| #endif |
| |
| #if (NXP_EXTNS == TRUE) |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; tranStatus: %d; recvBufferActualSize: %d", fn, |
| tranStatus, recvBufferActualSize); |
| return (tranStatus); |
| #else |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; isSuccess: %d; recvBufferActualSize: %d", fn, |
| isSuccess, recvBufferActualSize); |
| return (isSuccess); |
| #endif |
| } |
| /******************************************************************************* |
| ** |
| ** Function: setCLState |
| ** |
| ** Description: Update current DWP CL state based on CL activation status |
| ** |
| ** Returns: None . |
| ** |
| *******************************************************************************/ |
| void SecureElement::setCLState(bool mState) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Entry setCLState \n", __func__); |
| /*Check if the state is already dual mode*/ |
| bool inDualModeAlready = (dual_mode_current_state == SPI_DWPCL_BOTH_ACTIVE); |
| if (mState) { |
| dual_mode_current_state |= CL_ACTIVE; |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse && nfcFL.eseFL._JCOP_WA_ENABLE) { |
| active_ese_reset_control |= TRANS_CL_ONGOING; |
| } |
| #endif |
| } else { |
| if (dual_mode_current_state & CL_ACTIVE) { |
| dual_mode_current_state ^= CL_ACTIVE; |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._JCOP_WA_ENABLE && |
| (active_ese_reset_control & TRANS_CL_ONGOING)) { |
| active_ese_reset_control ^= TRANS_CL_ONGOING; |
| |
| /*If there is no pending wired rapdu or CL session*/ |
| if (((active_ese_reset_control & RESET_BLOCKED)) && |
| (!(active_ese_reset_control & (TRANS_WIRED_ONGOING)))) { |
| /*unblock pending reset event*/ |
| SyncEventGuard guard(sSecElem.mResetEvent); |
| sSecElem.mResetEvent.notifyOne(); |
| active_ese_reset_control ^= RESET_BLOCKED; |
| } |
| } |
| } |
| #endif |
| if (inDualModeAlready) { |
| SyncEventGuard guard(mDualModeEvent); |
| mDualModeEvent.notifyOne(); |
| } |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Exit setCLState = %d\n", __func__, dual_mode_current_state); |
| } |
| |
| void SecureElement::notifyModeSet(tNFA_HANDLE eeHandle, bool success, |
| tNFA_EE_STATUS eeStatus) { |
| static const char* fn = "SecureElement::notifyModeSet"; |
| if (success) { |
| tNFA_EE_INFO* pEE = sSecElem.findEeByHandle(eeHandle); |
| if (pEE) { |
| pEE->ee_status = eeStatus; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_EE_MODE_SET_EVT; pEE->ee_status: %s (0x%04x)", fn, |
| SecureElement::eeStatusToString(pEE->ee_status), pEE->ee_status); |
| } else |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_EE_MODE_SET_EVT; EE: 0x%04x not found. mActiveEeHandle: " |
| "0x%04x", |
| fn, eeHandle, sSecElem.mActiveEeHandle); |
| } |
| SyncEventGuard guard(sSecElem.mEeSetModeEvent); |
| sSecElem.mEeSetModeEvent.notifyOne(); |
| } |
| |
| #if (NXP_EXTNS == TRUE) |
| static void NFCC_StandbyModeTimerCallBack(union sigval) { |
| if (!nfcFL.nfcNxpEse) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s tnfcNxpEse not available. Returning", __func__); |
| return; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s timer timedout , sending standby mode cmd", __func__); |
| SecureElement::getInstance().NfccStandByOperation(STANDBY_TIMER_TIMEOUT); |
| } |
| #endif |
| /******************************************************************************* |
| ** |
| ** Function: notifyListenModeState |
| ** |
| ** Description: Notify the NFC service about whether the SE was activated |
| ** in listen mode. |
| ** isActive: Whether the secure element is activated. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::notifyListenModeState(bool isActivated) { |
| static const char fn[] = "SecureElement::notifyListenMode"; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; listen mode active=%u", fn, isActivated); |
| |
| JNIEnv* e = NULL; |
| if (mNativeData == NULL) { |
| LOG(ERROR) << StringPrintf("%s: mNativeData is null", fn); |
| return; |
| } |
| |
| ScopedAttach attach(mNativeData->vm, &e); |
| if (e == NULL) { |
| LOG(ERROR) << StringPrintf("%s: jni env is null", fn); |
| return; |
| } |
| |
| mActivatedInListenMode = isActivated; |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if (!isActivated) { |
| setCLState(false); |
| if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME != |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| setDwpTranseiveState(false, NFCC_DEACTIVATED_NTF); |
| } |
| } else { |
| /* activated in listen mode */ |
| if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME != |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| setDwpTranseiveState(true, NFCC_ACTIVATED_NTF); |
| } |
| } |
| } |
| #endif |
| if (mNativeData != NULL) { |
| if (isActivated) { |
| e->CallVoidMethod(mNativeData->manager, |
| android::gCachedNfcManagerNotifySeListenActivated); |
| } else { |
| e->CallVoidMethod(mNativeData->manager, |
| android::gCachedNfcManagerNotifySeListenDeactivated); |
| } |
| } |
| |
| if (e->ExceptionCheck()) { |
| e->ExceptionClear(); |
| LOG(ERROR) << StringPrintf("%s: fail notify", fn); |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: notifyRfFieldEvent |
| ** |
| ** Description: Notify the NFC service about RF field events from the stack. |
| ** isActive: Whether any secure element is activated. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::notifyRfFieldEvent(bool isActive) { |
| static const char fn[] = "SecureElement::notifyRfFieldEvent"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; is active=%u", fn, isActive); |
| |
| mMutex.lock(); |
| int ret = clock_gettime(CLOCK_MONOTONIC, &mLastRfFieldToggle); |
| if (ret == -1) { |
| LOG(ERROR) << StringPrintf("%s: clock_gettime failed", fn); |
| // There is no good choice here... |
| } |
| |
| if (isActive) { |
| mRfFieldIsOn = true; |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION && |
| (isTransceiveOngoing == false && meseUiccConcurrentAccess == true && |
| mPassiveListenEnabled == false)) { |
| startThread(0x01); |
| } |
| if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME != |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| setDwpTranseiveState(true, NFCC_RF_FIELD_EVT); |
| } |
| } |
| #endif |
| } else { |
| mRfFieldIsOn = false; |
| setCLState(false); |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse && (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME != |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME)) { |
| setDwpTranseiveState(false, NFCC_RF_FIELD_EVT); |
| } |
| #endif |
| } |
| mMutex.unlock(); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: resetRfFieldStatus |
| ** |
| ** Description: Resets the field status. |
| ** isActive: Whether any secure element is activated. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::resetRfFieldStatus() { |
| static const char fn[] = "SecureElement::resetRfFieldStatus`"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter;", fn); |
| |
| mMutex.lock(); |
| mRfFieldIsOn = false; |
| int ret = clock_gettime(CLOCK_MONOTONIC, &mLastRfFieldToggle); |
| if (ret == -1) { |
| LOG(ERROR) << StringPrintf("%s: clock_gettime failed", fn); |
| // There is no good choice here... |
| } |
| mMutex.unlock(); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: storeUiccInfo |
| ** |
| ** Description: Store a copy of the execution environment information from |
| *the stack. |
| ** info: execution environment information. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::storeUiccInfo(tNFA_EE_DISCOVER_REQ& info) { |
| static const char fn[] = "SecureElement::storeUiccInfo"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Status: %u Num EE: %u", fn, info.status, info.num_ee); |
| |
| SyncEventGuard guard(mUiccInfoEvent); |
| memcpy(&mUiccInfo, &info, sizeof(mUiccInfo)); |
| for (uint8_t xx = 0; xx < info.num_ee; xx++) { |
| // for each technology (A, B, F, B'), print the bit field that shows |
| // what protocol(s) is support by that technology |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s EE[%u] Handle: 0x%04x techA: 0x%02x techB: 0x%02x techF: " |
| "0x%02x techBprime: 0x%02x", |
| fn, xx, info.ee_disc_info[xx].ee_handle, |
| info.ee_disc_info[xx].la_protocol, info.ee_disc_info[xx].lb_protocol, |
| info.ee_disc_info[xx].lf_protocol, info.ee_disc_info[xx].lbp_protocol); |
| } |
| mUiccInfoEvent.notifyOne(); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function getSeVerInfo |
| ** |
| ** Description Gets version information and id for a secure element. The |
| ** seIndex parmeter is the zero based index of the secure |
| ** element to get verion info for. The version infommation |
| ** is returned as a string int the verInfo parameter. |
| ** |
| ** Returns ture on success, false on failure |
| ** |
| *******************************************************************************/ |
| bool SecureElement::getSeVerInfo(int seIndex, char* verInfo, int verInfoSz, |
| uint8_t* seid) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter, seIndex=%d", __func__, seIndex); |
| |
| if (seIndex > (mActualNumEe - 1)) { |
| LOG(ERROR) << StringPrintf( |
| "%s: invalid se index: %d, only %d SEs in system", __func__, seIndex, |
| mActualNumEe); |
| return false; |
| } |
| |
| *seid = mEeInfo[seIndex].ee_handle; |
| |
| if ((mEeInfo[seIndex].num_interface == 0) || |
| (mEeInfo[seIndex].ee_interface[0] == NCI_NFCEE_INTERFACE_HCI_ACCESS)) { |
| return false; |
| } |
| |
| strncpy(verInfo, "Version info not available", verInfoSz - 1); |
| verInfo[verInfoSz - 1] = '\0'; |
| |
| uint8_t pipe = (mEeInfo[seIndex].ee_handle == EE_HANDLE_0xF3) ? 0x70 : 0x71; |
| uint8_t host = (pipe == mStaticPipeProp) ? 0x02 : 0x03; |
| uint8_t gate = (pipe == mStaticPipeProp) ? 0xF0 : 0xF1; |
| |
| tNFA_STATUS nfaStat = NFA_HciAddStaticPipe(mNfaHciHandle, host, gate, pipe); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf( |
| "%s: NFA_HciAddStaticPipe() failed, pipe = 0x%x, error=0x%X", __func__, |
| pipe, nfaStat); |
| return true; |
| } |
| |
| SyncEventGuard guard(mVerInfoEvent); |
| if (NFA_STATUS_OK == |
| (nfaStat = NFA_HciGetRegistry(mNfaHciHandle, pipe, 0x02))) { |
| if (false == mVerInfoEvent.wait(200)) { |
| LOG(ERROR) << StringPrintf("%s: wait response timeout", __func__); |
| } else { |
| snprintf(verInfo, verInfoSz - 1, "Oberthur OS S/N: 0x%02x%02x%02x", |
| mVerInfo[0], mVerInfo[1], mVerInfo[2]); |
| verInfo[verInfoSz - 1] = '\0'; |
| } |
| } else { |
| LOG(ERROR) << StringPrintf("%s: NFA_HciGetRegistry () failed: 0x%X", |
| __func__, nfaStat); |
| } |
| return true; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function getActualNumEe |
| ** |
| ** Description Returns number of secure elements we know about. |
| ** |
| ** Returns Number of secure elements we know about. |
| ** |
| *******************************************************************************/ |
| uint8_t SecureElement::getActualNumEe() { |
| if (NFA_GetNCIVersion() == NCI_VERSION_2_0) |
| return mActualNumEe + 1; |
| else |
| return mActualNumEe; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: handleClearAllPipe |
| ** |
| ** Description: To handle clear all pipe event received from HCI based on |
| *the |
| ** deleted host |
| ** eventData: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::handleClearAllPipe(tNFA_HCI_EVT_DATA* eventData) { |
| static const char fn[] = "SecureElement::handleClearAllPipe"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Deleted host=0x%X", fn, eventData->deleted.host); |
| if (eventData->deleted.host == |
| (SecureElement::getInstance().EE_HANDLE_0xF4 & |
| ~NFA_HANDLE_GROUP_EE)) { /* To stop mode-set being called when a clear |
| all pipe is being issued */ |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_DELETE_PIPE_EVT for UICC1 start", fn); |
| sSecElem.eSE_ClearAllPipe_handler( |
| SecureElement::getInstance().EE_HANDLE_0xF4 & ~NFA_HANDLE_GROUP_EE); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_DELETE_PIPE_EVT for UICC1 poll end", fn); |
| } else if (eventData->deleted.host == |
| (EE_HANDLE_0xF8 & ~NFA_HANDLE_GROUP_EE)) { |
| /* To stop mode-set being called when a clear all pipe is being issued */ |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_DELETE_PIPE_EVT for UICC2 start", fn); |
| sSecElem.eSE_ClearAllPipe_handler(EE_HANDLE_0xF8 & ~NFA_HANDLE_GROUP_EE); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_DELETE_PIPE_EVT for UICC2 poll end", fn); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: nfaHciCallback |
| ** |
| ** Description: Receive Host Controller Interface-related events from stack. |
| ** event: Event code. |
| ** eventData: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::nfaHciCallback(tNFA_HCI_EVT event, |
| tNFA_HCI_EVT_DATA* eventData) { |
| static const char fn[] = "SecureElement::nfaHciCallback"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: event=0x%X", fn, event); |
| |
| switch (event) { |
| case NFA_HCI_REGISTER_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_REGISTER_EVT; status=0x%X; handle=0x%X", fn, |
| eventData->hci_register.status, eventData->hci_register.hci_handle); |
| SyncEventGuard guard(sSecElem.mHciRegisterEvent); |
| sSecElem.mNfaHciHandle = eventData->hci_register.hci_handle; |
| sSecElem.mHciRegisterEvent.notifyOne(); |
| } break; |
| |
| case NFA_HCI_ALLOCATE_GATE_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_ALLOCATE_GATE_EVT; status=0x%X; gate=0x%X", fn, |
| eventData->status, eventData->allocated.gate); |
| SyncEventGuard guard(sSecElem.mAllocateGateEvent); |
| sSecElem.mCommandStatus = eventData->status; |
| sSecElem.mNewSourceGate = (eventData->allocated.status == NFA_STATUS_OK) |
| ? eventData->allocated.gate |
| : 0; |
| sSecElem.mAllocateGateEvent.notifyOne(); |
| } break; |
| |
| case NFA_HCI_DEALLOCATE_GATE_EVT: { |
| tNFA_HCI_DEALLOCATE_GATE& deallocated = eventData->deallocated; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_DEALLOCATE_GATE_EVT; status=0x%X; gate=0x%X", fn, |
| deallocated.status, deallocated.gate); |
| SyncEventGuard guard(sSecElem.mDeallocateGateEvent); |
| sSecElem.mDeallocateGateEvent.notifyOne(); |
| } break; |
| |
| case NFA_HCI_GET_GATE_PIPE_LIST_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_GET_GATE_PIPE_LIST_EVT; status=0x%X; num_pipes: %u " |
| "num_gates: %u", |
| fn, eventData->gates_pipes.status, eventData->gates_pipes.num_pipes, |
| eventData->gates_pipes.num_gates); |
| SyncEventGuard guard(sSecElem.mPipeListEvent); |
| sSecElem.mCommandStatus = eventData->gates_pipes.status; |
| sSecElem.mHciCfg = eventData->gates_pipes; |
| sSecElem.mPipeListEvent.notifyOne(); |
| } break; |
| |
| case NFA_HCI_CREATE_PIPE_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_CREATE_PIPE_EVT; status=0x%X; pipe=0x%X; src gate=0x%X; " |
| "dest host=0x%X; dest gate=0x%X", |
| fn, eventData->created.status, eventData->created.pipe, |
| eventData->created.source_gate, eventData->created.dest_host, |
| eventData->created.dest_gate); |
| SyncEventGuard guard(sSecElem.mCreatePipeEvent); |
| sSecElem.mCommandStatus = eventData->created.status; |
| if (eventData->created.dest_gate == 0xF0) { |
| LOG(ERROR) << StringPrintf( |
| "Pipe=0x%x is created and updated for se transcieve", |
| eventData->created.pipe); |
| sSecElem.mNewPipeId = eventData->created.pipe; |
| } |
| #if (NXP_EXTNS == TRUE) |
| sSecElem.mCreatedPipe = eventData->created.pipe; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_CREATE_PIPE_EVT; pipe=0x%X", fn, |
| eventData->created.pipe); |
| #endif |
| sSecElem.mCreatePipeEvent.notifyOne(); |
| } break; |
| #if (NXP_EXTNS == TRUE) |
| case NFA_HCI_DELETE_PIPE_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_DELETE_PIPE_EVT; status=0x%X; host=0x%X", fn, |
| eventData->deleted.status, eventData->deleted.host); |
| sSecElem.handleClearAllPipe(eventData); |
| } break; |
| #endif |
| case NFA_HCI_OPEN_PIPE_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_OPEN_PIPE_EVT; status=0x%X; pipe=0x%X", |
| fn, eventData->opened.status, eventData->opened.pipe); |
| SyncEventGuard guard(sSecElem.mPipeOpenedEvent); |
| sSecElem.mCommandStatus = eventData->opened.status; |
| sSecElem.mPipeOpenedEvent.notifyOne(); |
| } break; |
| |
| case NFA_HCI_EVENT_SENT_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_EVENT_SENT_EVT; status=0x%X", fn, |
| eventData->evt_sent.status); |
| if (eventData->evt_sent.status != NFA_STATUS_OK) { |
| sSecElem.mTransceiveEvent.notifyOne(); |
| } |
| break; |
| |
| case NFA_HCI_RSP_RCVD_EVT: // response received from secure element |
| { |
| tNFA_HCI_RSP_RCVD& rsp_rcvd = eventData->rsp_rcvd; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_RSP_RCVD_EVT; status: 0x%X; code: 0x%X; pipe: 0x%X; " |
| "len: %u", |
| fn, rsp_rcvd.status, rsp_rcvd.rsp_code, rsp_rcvd.pipe, |
| rsp_rcvd.rsp_len); |
| if ((rsp_rcvd.rsp_code == NFA_HCI_ANY_E_PIPE_NOT_OPENED) && |
| (sSecElem.IsCmdsentOnOpenDwpSession)) { |
| SyncEventGuard guard(sSecElem.mPipeStatusCheckEvent); |
| sSecElem.mCommandStatus = eventData->closed.status; |
| sSecElem.pipeStatus = NFA_HCI_ANY_E_PIPE_NOT_OPENED; |
| sSecElem.mPipeStatusCheckEvent.notifyOne(); |
| sSecElem.IsCmdsentOnOpenDwpSession = false; |
| } |
| } break; |
| |
| case NFA_HCI_GET_REG_RSP_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_GET_REG_RSP_EVT; status: 0x%X; pipe: 0x%X, len: %d", fn, |
| eventData->registry.status, eventData->registry.pipe, |
| eventData->registry.data_len); |
| if (sSecElem.mGetAtrRspwait == true) { |
| /*GetAtr response*/ |
| sSecElem.mGetAtrRspwait = false; |
| SyncEventGuard guard(sSecElem.mGetRegisterEvent); |
| memcpy(sSecElem.mAtrInfo, eventData->registry.reg_data, |
| eventData->registry.data_len); |
| sSecElem.mAtrInfolen = eventData->registry.data_len; |
| sSecElem.mAtrStatus = eventData->registry.status; |
| sSecElem.mGetRegisterEvent.notifyOne(); |
| } else if (eventData->registry.data_len >= 19 && |
| ((eventData->registry.pipe == mStaticPipeProp) || |
| (eventData->registry.pipe == STATIC_PIPE_0x71))) { |
| SyncEventGuard guard(sSecElem.mVerInfoEvent); |
| // Oberthur OS version is in bytes 16,17, and 18 |
| sSecElem.mVerInfo[0] = eventData->registry.reg_data[16]; |
| sSecElem.mVerInfo[1] = eventData->registry.reg_data[17]; |
| sSecElem.mVerInfo[2] = eventData->registry.reg_data[18]; |
| sSecElem.mVerInfoEvent.notifyOne(); |
| } |
| break; |
| |
| case NFA_HCI_EVENT_RCVD_EVT: |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT; code: 0x%X; pipe: 0x%X; data len: %u", |
| fn, eventData->rcvd_evt.evt_code, eventData->rcvd_evt.pipe, |
| eventData->rcvd_evt.evt_len); |
| |
| if (eventData->rcvd_evt.evt_code == NFA_HCI_EVT_WTX) { |
| #if (NXP_EXTNS == TRUE) |
| gWtxCount++; |
| if (sSecElem.mWmMaxWtxCount >= gWtxCount) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT: NFA_HCI_EVT_WTX gWtxCount:%d", fn, |
| gWtxCount); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT: NFA_HCI_EVT_WTX gWtxCount:%d", fn, |
| gWtxCount); |
| sSecElem.mTransceiveEvent.notifyOne(); |
| break; |
| } |
| #endif |
| } |
| #if (NXP_EXTNS == TRUE) |
| else if (sSecElem.IsCmdsentOnOpenDwpSession) { |
| SyncEventGuard guard(sSecElem.mPipeStatusCheckEvent); |
| sSecElem.mCommandStatus = eventData->closed.status; |
| sSecElem.mPipeStatusCheckEvent.notifyOne(); |
| sSecElem.IsCmdsentOnOpenDwpSession = false; |
| |
| } else if (((eventData->rcvd_evt.evt_code == NFA_HCI_ABORT) || |
| (eventData->rcvd_evt.last_SentEvtType == EVT_ABORT)) && |
| (eventData->rcvd_evt.pipe == mStaticPipeProp)) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT: NFA_HCI_ABORT; status:0x%X, " |
| "pipe:0x%X, len:%d", |
| fn, eventData->rcvd_evt.status, eventData->rcvd_evt.pipe, |
| eventData->rcvd_evt.evt_len); |
| if (eventData->rcvd_evt.evt_len > 0) { |
| sSecElem.mAbortEventWaitOk = true; |
| SyncEventGuard guard(sSecElem.mAbortEvent); |
| memcpy(sSecElem.mAtrInfo, eventData->rcvd_evt.p_evt_buf, |
| eventData->rcvd_evt.evt_len); |
| sSecElem.mAtrInfolen = eventData->rcvd_evt.evt_len; |
| sSecElem.mAtrStatus = eventData->rcvd_evt.status; |
| sSecElem.mAbortEvent.notifyOne(); |
| } else { |
| sSecElem.mAbortEventWaitOk = false; |
| SyncEventGuard guard(sSecElem.mAbortEvent); |
| sSecElem.mAbortEvent.notifyOne(); |
| } |
| } |
| #endif |
| else if ((eventData->rcvd_evt.pipe == mStaticPipeProp) || |
| (eventData->rcvd_evt.pipe == STATIC_PIPE_0x71)) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT; data from static pipe", fn); |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE && |
| ((spiDwpSyncState & STATE_WK_WAIT_RSP) && |
| (eventData->rcvd_evt.evt_len == 2))) { |
| spiDwpSyncState ^= STATE_WK_WAIT_RSP; |
| SyncEventGuard guard(sSPIForceEnableDWPEvent); |
| sSPIForceEnableDWPEvent.notifyOne(); |
| break; |
| } |
| #endif |
| SyncEventGuard guard(sSecElem.mTransceiveEvent); |
| sSecElem.mActualResponseSize = |
| (eventData->rcvd_evt.evt_len > MAX_RESPONSE_SIZE) |
| ? MAX_RESPONSE_SIZE |
| : eventData->rcvd_evt.evt_len; |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| if (eventData->rcvd_evt.evt_len > 0) { |
| sSecElem.mTransceiveWaitOk = true; |
| if (nfcFL.eseFL._ESE_ETSI_READER_ENABLE) { |
| se_rd_req_state_t state = |
| MposManager::getInstance().getEtsiReaederState(); |
| if ((state == STATE_SE_RDR_MODE_STOPPED) || |
| (state == STATE_SE_RDR_MODE_STOP_CONFIG)) { |
| sSecElem.NfccStandByOperation(STANDBY_TIMER_START); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "ETSI in progress, do not start standby timer"); |
| } |
| } else { |
| sSecElem.NfccStandByOperation(STANDBY_TIMER_START); |
| } |
| } |
| /*If there is pending reset event to process*/ |
| if ((nfcFL.eseFL._JCOP_WA_ENABLE) && |
| (active_ese_reset_control & RESET_BLOCKED) && |
| (!(active_ese_reset_control & (TRANS_CL_ONGOING)))) { |
| SyncEventGuard guard(sSecElem.mResetEvent); |
| sSecElem.mResetEvent.notifyOne(); |
| } |
| gWtxCount = 0; |
| } else { |
| if (eventData->rcvd_evt.evt_len > 0) { |
| sSecElem.mTransceiveWaitOk = true; |
| } |
| } |
| #endif |
| sSecElem.mTransceiveEvent.notifyOne(); |
| } else if (eventData->rcvd_evt.evt_code == NFA_HCI_EVT_POST_DATA) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT; NFA_HCI_EVT_POST_DATA", fn); |
| SyncEventGuard guard(sSecElem.mTransceiveEvent); |
| sSecElem.mActualResponseSize = |
| (eventData->rcvd_evt.evt_len > MAX_RESPONSE_SIZE) |
| ? MAX_RESPONSE_SIZE |
| : eventData->rcvd_evt.evt_len; |
| sSecElem.mTransceiveEvent.notifyOne(); |
| } else if (eventData->rcvd_evt.evt_code == NFA_HCI_EVT_TRANSACTION) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT; NFA_HCI_EVT_TRANSACTION", fn); |
| // If we got an AID, notify any listeners |
| if ((eventData->rcvd_evt.evt_len > 3) && |
| (eventData->rcvd_evt.p_evt_buf[0] == 0x81)) { |
| int aidlen = eventData->rcvd_evt.p_evt_buf[1]; |
| uint8_t* data = NULL; |
| int32_t datalen = 0; |
| uint8_t dataStartPosition = 0; |
| if ((eventData->rcvd_evt.evt_len > 2 + aidlen) && |
| (eventData->rcvd_evt.p_evt_buf[2 + aidlen] == 0x82)) { |
| // BERTLV decoding here, to support extended data length for params. |
| datalen = SecureElement::decodeBerTlvLength( |
| (uint8_t*)eventData->rcvd_evt.p_evt_buf, 2 + aidlen + 1, |
| eventData->rcvd_evt.evt_len); |
| } |
| if (datalen >= 0) { |
| /* Over 128 bytes data of transaction can not receive on PN547, Ref. |
| * BER-TLV length fields in ISO/IEC 7816 */ |
| if (datalen < 0x80) { |
| dataStartPosition = 2 + aidlen + 2; |
| } else if (datalen < 0x100) { |
| dataStartPosition = 2 + aidlen + 3; |
| } else if (datalen < 0x10000) { |
| dataStartPosition = 2 + aidlen + 4; |
| } else if (datalen < 0x1000000) { |
| dataStartPosition = 2 + aidlen + 5; |
| } |
| data = &eventData->rcvd_evt.p_evt_buf[dataStartPosition]; |
| if (nfcFL.nfcNxpEse && nfcFL.eseFL._ESE_ETSI_READER_ENABLE) { |
| if (MposManager::getInstance().validateHCITransactionEventParams( |
| data, datalen) == NFA_STATUS_OK) { |
| HciEventManager::getInstance().nfaHciEvtHandler(event, |
| eventData); |
| } |
| } else { |
| HciEventManager::getInstance().nfaHciEvtHandler(event, eventData); |
| } |
| } else { |
| LOG(ERROR) << StringPrintf( |
| "Event data TLV length encoding Unsupported!"); |
| } |
| } |
| } else if (eventData->rcvd_evt.evt_code == NFA_HCI_EVT_CONNECTIVITY) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT; NFA_HCI_EVT_CONNECTIVITY", fn); |
| int evtSrc = 0xFF; |
| if (eventData->rcvd_evt.pipe == 0x0A) // UICC |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_EVENT_RCVD_EVT; source UICC", fn); |
| evtSrc = SecureElement::getInstance().getGenericEseId( |
| SecureElement::getInstance().EE_HANDLE_0xF4 & |
| ~NFA_HANDLE_GROUP_EE); // UICC |
| } else if (eventData->rcvd_evt.pipe == 0x16) // ESE |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_EVENT_RCVD_EVT; source ESE", fn); |
| evtSrc = SecureElement::getInstance().getGenericEseId( |
| EE_HANDLE_0xF3 & ~NFA_HANDLE_GROUP_EE); // ESE |
| } else if (nfcFL.nfccFL._NFC_NXP_STAT_DUAL_UICC_WO_EXT_SWITCH && |
| (eventData->rcvd_evt.pipe == 0x23)) /*UICC2*/ |
| { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_EVENT_RCVD_EVT; source UICC2", fn); |
| evtSrc = SecureElement::getInstance().getGenericEseId( |
| EE_HANDLE_0xF8 & ~NFA_HANDLE_GROUP_EE); /*UICC2*/ |
| } |
| // int pipe = (eventData->rcvd_evt.pipe); |
| // /*commented to eliminate unused variable warning*/ |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT; ################################### " |
| "eventData->rcvd_evt.evt_code = 0x%x , NFA_HCI_EVT_CONNECTIVITY = " |
| "0x%x", |
| fn, eventData->rcvd_evt.evt_code, NFA_HCI_EVT_CONNECTIVITY); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EVENT_RCVD_EVT; ################################### ", |
| fn); |
| } |
| break; |
| |
| case NFA_HCI_SET_REG_RSP_EVT: // received response to write registry |
| // command |
| { |
| tNFA_HCI_REGISTRY& registry = eventData->registry; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_SET_REG_RSP_EVT; status=0x%X; pipe=0x%X", |
| fn, registry.status, registry.pipe); |
| SyncEventGuard guard(sSecElem.mRegistryEvent); |
| sSecElem.mRegistryEvent.notifyOne(); |
| break; |
| } |
| #if (NXP_EXTNS == TRUE) |
| case NFA_HCI_CONFIG_DONE_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_CONFIG_DONE_EVT; status=0x%X", fn, |
| eventData->admin_rsp_rcvd.status); |
| sSecElem.mETSI12InitStatus = eventData->admin_rsp_rcvd.status; |
| SyncEventGuard guard(sSecElem.mNfceeInitCbEvent); |
| sSecElem.mNfceeInitCbEvent.notifyOne(); |
| break; |
| } |
| case NFA_HCI_EE_RECOVERY_EVT: { |
| tNFA_HCI_EE_RECOVERY_EVT& ee_recovery = eventData->ee_recovery; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EE_RECOVERY_EVT; status=0x%X", fn, ee_recovery.status); |
| if (ee_recovery.status == NFA_HCI_EE_RECOVERY_STARTED) |
| RoutingManager::getInstance().setEERecovery(true); |
| else if (ee_recovery.status == NFA_HCI_EE_RECOVERY_COMPLETED) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_HCI_EE_RECOVERY_EVT; recovery completed status=0x%X", fn, |
| ee_recovery.status); |
| RoutingManager::getInstance().setEERecovery(false); |
| if (active_ese_reset_control & TRANS_WIRED_ONGOING) { |
| SyncEventGuard guard(sSecElem.mTransceiveEvent); |
| sSecElem.mTransceiveEvent.notifyOne(); |
| } |
| } |
| break; |
| } |
| case NFA_HCI_ADD_STATIC_PIPE_EVT: { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HCI_ADD_STATIC_PIPE_EVT; status=0x%X", fn, |
| eventData->admin_rsp_rcvd.status); |
| SyncEventGuard guard(sSecElem.mHciAddStaticPipe); |
| sSecElem.mHciAddStaticPipe.notifyOne(); |
| break; |
| } |
| #endif |
| default: |
| LOG(ERROR) << StringPrintf("%s: unknown event code=0x%X ????", fn, event); |
| break; |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: findEeByHandle |
| ** |
| ** Description: Find information about an execution environment. |
| ** eeHandle: Handle to execution environment. |
| ** |
| ** Returns: Information about an execution environment. |
| ** |
| *******************************************************************************/ |
| tNFA_EE_INFO* SecureElement::findEeByHandle(tNFA_HANDLE eeHandle) { |
| for (uint8_t xx = 0; xx < mActualNumEe; xx++) { |
| if (mEeInfo[xx].ee_handle == eeHandle) return (&mEeInfo[xx]); |
| } |
| return (NULL); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getSETechnology |
| ** |
| ** Description: return the technologies suported by se. |
| ** eeHandle: Handle to execution environment. |
| ** |
| ** Returns: Information about an execution environment. |
| ** |
| *******************************************************************************/ |
| jint SecureElement::getSETechnology(tNFA_HANDLE eeHandle) { |
| int tech_mask = 0x00; |
| static const char fn[] = "SecureElement::getSETechnology"; |
| // Get Fresh EE info. |
| if (!getEeInfo()) { |
| LOG(ERROR) << StringPrintf("%s: No updated eeInfo available", fn); |
| } |
| |
| tNFA_EE_INFO* eeinfo = findEeByHandle(eeHandle); |
| |
| if (eeinfo != NULL) { |
| if (eeinfo->la_protocol != 0x00) { |
| tech_mask |= 0x01; |
| } |
| |
| if (eeinfo->lb_protocol != 0x00) { |
| tech_mask |= 0x02; |
| } |
| |
| if (eeinfo->lf_protocol != 0x00) { |
| tech_mask |= 0x04; |
| } |
| } |
| |
| return tech_mask; |
| } |
| /******************************************************************************* |
| ** |
| ** Function: getDefaultEeHandle |
| ** |
| ** Description: Get the handle to the execution environment. |
| ** |
| ** Returns: Handle to the execution environment. |
| ** |
| *******************************************************************************/ |
| tNFA_HANDLE SecureElement::getDefaultEeHandle() { |
| static const char fn[] = "SecureElement::activate"; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: - Enter", fn); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: - mActualNumEe = %x mActiveSeOverride = 0x%02X", fn, |
| mActualNumEe, mActiveSeOverride); |
| |
| uint16_t overrideEeHandle = NFA_HANDLE_GROUP_EE | mActiveSeOverride; |
| // Find the first EE that is not the HCI Access i/f. |
| for (uint8_t xx = 0; xx < mActualNumEe; xx++) { |
| if ((mActiveSeOverride != ACTIVE_SE_USE_ANY) && |
| (overrideEeHandle != mEeInfo[xx].ee_handle)) |
| continue; // skip all the EE's that are ignored |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: - mEeInfo[xx].ee_handle = 0x%02x, mEeInfo[xx].ee_status = 0x%02x", |
| fn, mEeInfo[xx].ee_handle, mEeInfo[xx].ee_status); |
| |
| if ((nfcFL.nfccFL._GEMALTO_SE_SUPPORT && |
| (mEeInfo[xx].ee_interface[0] != NCI_NFCEE_INTERFACE_HCI_ACCESS))) { |
| return (mEeInfo[xx].ee_handle); |
| } else if ((!nfcFL.nfccFL._GEMALTO_SE_SUPPORT && |
| ((mEeInfo[xx].ee_handle == EE_HANDLE_0xF3 || |
| mEeInfo[xx].ee_handle == |
| SecureElement::getInstance().EE_HANDLE_0xF4 || |
| (mEeInfo[xx].ee_handle == EE_HANDLE_0xF8 && |
| nfcFL.nfccFL._NFCC_DYNAMIC_DUAL_UICC)) && |
| (mEeInfo[xx].ee_status != NFC_NFCEE_STATUS_INACTIVE)))) { |
| return (mEeInfo[xx].ee_handle); |
| } |
| } |
| return NFA_HANDLE_INVALID; |
| } |
| #if (NXP_EXTNS == TRUE) |
| /******************************************************************************* |
| ** |
| ** Function: getActiveEeHandle |
| ** |
| ** Description: Get the handle to the execution environment. |
| ** |
| ** Returns: Handle to the execution environment. |
| ** |
| *******************************************************************************/ |
| tNFA_HANDLE SecureElement::getActiveEeHandle(tNFA_HANDLE handle) { |
| static const char fn[] = "SecureElement::getActiveEeHandle"; |
| |
| LOG(ERROR) << StringPrintf("%s: - Enter", fn); |
| LOG(ERROR) << StringPrintf( |
| "%s: - mActualNumEe = %x mActiveSeOverride = 0x%02X", fn, mActualNumEe, |
| mActiveSeOverride); |
| |
| uint16_t overrideEeHandle = NFA_HANDLE_GROUP_EE | mActiveSeOverride; |
| LOG(ERROR) << StringPrintf( |
| "%s: - mActualNumEe = %x overrideEeHandle = 0x%02X", fn, mActualNumEe, |
| overrideEeHandle); |
| |
| for (uint8_t xx = 0; xx < mActualNumEe; xx++) { |
| if ((mActiveSeOverride != ACTIVE_SE_USE_ANY) && |
| (overrideEeHandle != mEeInfo[xx].ee_handle)) |
| LOG(ERROR) << StringPrintf( |
| "%s: - mEeInfo[xx].ee_handle = 0x%02x, mEeInfo[xx].ee_status = " |
| "0x%02x", |
| fn, mEeInfo[xx].ee_handle, mEeInfo[xx].ee_status); |
| |
| if (nfcFL.nfccFL._GEMALTO_SE_SUPPORT && |
| (mEeInfo[xx].ee_interface[0] != NCI_NFCEE_INTERFACE_HCI_ACCESS) && |
| (mEeInfo[xx].ee_status != NFC_NFCEE_STATUS_INACTIVE) && |
| (mEeInfo[xx].ee_handle == handle)) { |
| return (mEeInfo[xx].ee_handle); |
| } else if (!nfcFL.nfccFL._GEMALTO_SE_SUPPORT && |
| (mEeInfo[xx].ee_handle == EE_HANDLE_0xF3 || |
| mEeInfo[xx].ee_handle == |
| SecureElement::getInstance().EE_HANDLE_0xF4 || |
| (mEeInfo[xx].ee_handle == EE_HANDLE_0xF8 && |
| nfcFL.nfccFL._NFCC_DYNAMIC_DUAL_UICC)) && |
| (mEeInfo[xx].ee_status != NFC_NFCEE_STATUS_INACTIVE) && |
| (mEeInfo[xx].ee_handle == handle)) { |
| return (mEeInfo[xx].ee_handle); |
| } |
| } |
| return NFA_HANDLE_INVALID; |
| } |
| #endif |
| /******************************************************************************* |
| ** |
| ** Function: findUiccByHandle |
| ** |
| ** Description: Find information about an execution environment. |
| ** eeHandle: Handle of the execution environment. |
| ** |
| ** Returns: Information about the execution environment. |
| ** |
| *******************************************************************************/ |
| tNFA_EE_DISCOVER_INFO* SecureElement::findUiccByHandle(tNFA_HANDLE eeHandle) { |
| for (uint8_t index = 0; index < mUiccInfo.num_ee; index++) { |
| if (mUiccInfo.ee_disc_info[index].ee_handle == eeHandle) { |
| return (&mUiccInfo.ee_disc_info[index]); |
| } |
| } |
| LOG(ERROR) << StringPrintf( |
| "SecureElement::findUiccByHandle: ee h=0x%4x not found", eeHandle); |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: eeStatusToString |
| ** |
| ** Description: Convert status code to status text. |
| ** status: Status code |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| const char* SecureElement::eeStatusToString(uint8_t status) { |
| switch (status) { |
| case NFC_NFCEE_STATUS_ACTIVE: |
| return ("Connected/Active"); |
| case NFC_NFCEE_STATUS_INACTIVE: |
| return ("Connected/Inactive"); |
| case NFC_NFCEE_STATUS_REMOVED: |
| return ("Removed"); |
| } |
| return ("?? Unknown ??"); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: connectionEventHandler |
| ** |
| ** Description: Receive card-emulation related events from stack. |
| ** event: Event code. |
| ** eventData: Event data. |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void SecureElement::connectionEventHandler(uint8_t event, |
| tNFA_CONN_EVT_DATA* /*eventData*/) { |
| switch (event) { |
| case NFA_CE_UICC_LISTEN_CONFIGURED_EVT: { |
| SyncEventGuard guard(mUiccListenEvent); |
| mUiccListenEvent.notifyOne(); |
| } break; |
| |
| case NFA_CE_ESE_LISTEN_CONFIGURED_EVT: { |
| SyncEventGuard guard(mEseListenEvent); |
| mEseListenEvent.notifyOne(); |
| } break; |
| } |
| } |
| /******************************************************************************* |
| ** |
| ** Function: getAtr |
| ** |
| ** Description: GetAtr response from the connected eSE |
| ** |
| ** Returns: Returns True if success |
| ** |
| *******************************************************************************/ |
| bool SecureElement::getAtr(jint seID, uint8_t* recvBuffer, |
| int32_t* recvBufferSize) { |
| static const char fn[] = "SecureElement::getAtr"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| uint8_t reg_index = 0x01; |
| int timeoutMillisec = 10000; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; seID=0x%X", fn, seID); |
| #if (NXP_EXTNS == TRUE) |
| if (nfcFL.nfcNxpEse) { |
| se_apdu_gate_info gateInfo = NO_APDU_GATE; |
| |
| if (nfcFL.nfccFL._NFCEE_REMOVED_NTF_RECOVERY) { |
| if ((RoutingManager::getInstance().is_ee_recovery_ongoing())) { |
| SyncEventGuard guard(mEEdatapacketEvent); |
| if (mEEdatapacketEvent.wait(android::gMaxEERecoveryTimeout) == false) { |
| return false; |
| } |
| } |
| } |
| if (!checkForWiredModeAccess()) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("Denying /atr in SE listen mode active"); |
| return false; |
| } |
| if ((((nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_1) || |
| (nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_2))) && |
| NFC_GetEseAccess((void*)&timeoutMillisec) != 0) { |
| LOG(ERROR) << StringPrintf("%s: NFC_ReqWiredAccess timeout", fn); |
| return false; |
| } |
| NfccStandByOperation(STANDBY_MODE_OFF); |
| |
| gateInfo = getApduGateInfo(); |
| if (gateInfo == PROPREITARY_APDU_GATE) { |
| SyncEventGuard guard(mGetRegisterEvent); |
| nfaStat = NFA_HciGetRegistry(mNfaHciHandle, mNewPipeId, reg_index); |
| if (nfaStat == NFA_STATUS_OK) { |
| mGetAtrRspwait = true; |
| mGetRegisterEvent.wait(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Received ATR response on pipe 0x%x ", fn, mNewPipeId); |
| } |
| *recvBufferSize = mAtrInfolen; |
| memcpy(recvBuffer, mAtrInfo, mAtrInfolen); |
| } else if (gateInfo == ETSI_12_APDU_GATE) { |
| mAbortEventWaitOk = false; |
| uint8_t mAtrInfo1[EVT_ABORT_MAX_RSP_LEN] = {0}; |
| uint8_t atr_len = EVT_ABORT_MAX_RSP_LEN; |
| SyncEventGuard guard(mAbortEvent); |
| nfaStat = NFA_HciSendEvent(mNfaHciHandle, mNewPipeId, EVT_ABORT, 0, NULL, |
| atr_len, mAtrInfo1, timeoutMillisec); |
| if (nfaStat == NFA_STATUS_OK) { |
| mAbortEvent.wait(); |
| } |
| if (mAbortEventWaitOk == false) { |
| LOG(ERROR) << StringPrintf("%s (EVT_ABORT)Wait reposne timeout", fn); |
| nfaStat = NFA_STATUS_FAILED; |
| } else { |
| *recvBufferSize = mAtrInfolen; |
| memcpy(recvBuffer, mAtrInfo, mAtrInfolen); |
| } |
| } |
| |
| if ((nfcFL.eseFL._JCOP_WA_ENABLE) && (mAtrStatus == NFA_HCI_ANY_E_NOK)) |
| reconfigureEseHciInit(); |
| |
| if (((nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_1) || |
| (nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_2)) && |
| NFC_RelEseAccess((void*)&nfaStat) != 0) { |
| LOG(ERROR) << StringPrintf("%s: NFC_ReqWiredAccess timeout", fn); |
| } |
| #endif |
| } |
| return (nfaStat == NFA_STATUS_OK) ? true : false; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: routeToSecureElement |
| ** |
| ** Description: Adjust controller's listen-mode routing table so |
| *transactions |
| ** are routed to the secure elements. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::routeToSecureElement() { |
| static const char fn[] = "SecureElement::routeToSecureElement"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| |
| // tNFA_TECHNOLOGY_MASK tech_mask = NFA_TECHNOLOGY_MASK_A | |
| // NFA_TECHNOLOGY_MASK_B; /*commented to eliminate unused variable |
| // warning*/ |
| bool retval = false; |
| |
| if (!mIsInit) { |
| LOG(ERROR) << StringPrintf("%s: not init", fn); |
| return false; |
| } |
| |
| if (mCurrentRouteSelection == SecElemRoute) { |
| LOG(ERROR) << StringPrintf("%s: already sec elem route", fn); |
| return true; |
| } |
| |
| if (mActiveEeHandle == NFA_HANDLE_INVALID) { |
| LOG(ERROR) << StringPrintf("%s: invalid EE handle", fn); |
| return false; |
| } |
| |
| /* tNFA_EE_INFO* eeinfo = findEeByHandle(mActiveEeHandle); |
| if(eeinfo!=NULL){ |
| if(eeinfo->la_protocol == 0x00 && eeinfo->lb_protocol != 0x00 ) |
| { |
| gTypeB_listen = true; |
| } |
| }*/ |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; ok=%u", fn, retval); |
| return retval; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: isBusy |
| ** |
| ** Description: Whether controller is routing listen-mode events to |
| ** secure elements or a pipe is connected. |
| ** |
| ** Returns: True if either case is true. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::isBusy() { |
| bool retval = mIsPiping; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("SecureElement::isBusy: %u", retval); |
| return retval; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getGenericEseId |
| ** |
| ** Description: Whether controller is routing listen-mode events to |
| ** secure elements or a pipe is connected. |
| ** |
| ** Returns: Return the generic SE id ex:- 00,01,02,04 |
| ** |
| *******************************************************************************/ |
| jint SecureElement::getGenericEseId(tNFA_HANDLE handle) { |
| jint ret = 0xFF; |
| static const char fn[] = "SecureElement::getGenericEseId"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; SE-Handle = 0x%X", fn, handle); |
| // Map the actual handle to generic id |
| if (handle == (EE_HANDLE_0xF3 & ~NFA_HANDLE_GROUP_EE)) // ESE - 0xC0 |
| { |
| ret = ESE_ID; |
| } else if (handle == (SecureElement::getInstance().EE_HANDLE_0xF4 & |
| ~NFA_HANDLE_GROUP_EE)) // UICC - 0x02 |
| { |
| ret = UICC_ID; |
| } else if ((nfcFL.nfccFL._NFCC_DYNAMIC_DUAL_UICC || |
| nfcFL.nfccFL._NFC_NXP_STAT_DUAL_UICC_WO_EXT_SWITCH) && |
| (handle == |
| (EE_HANDLE_0xF8 & ~NFA_HANDLE_GROUP_EE))) // UICC2 - 0x04 |
| { |
| ret = UICC2_ID; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; SE-Generic-ID = 0x%02X", fn, ret); |
| return ret; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getEseHandleFromGenericId |
| ** |
| ** Description: Whether controller is routing listen-mode events to |
| ** secure elements or a pipe is connected. |
| ** |
| ** Returns: Returns Secure element Handle ex:- 402, 4C0, 481 |
| ** |
| *******************************************************************************/ |
| tNFA_HANDLE SecureElement::getEseHandleFromGenericId(jint eseId) { |
| uint16_t handle = NFA_HANDLE_INVALID; |
| static const char fn[] = "SecureElement::getEseHandleFromGenericId"; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: enter; SE-Generic-ID = 0x%02X", fn, eseId); |
| |
| // Map the generic id to actual handle |
| if (eseId == ESE_ID) // ESE |
| { |
| handle = EE_HANDLE_0xF3; // 0x4C0; |
| } else if (eseId == UICC_ID) // UICC |
| { |
| handle = SecureElement::getInstance().EE_HANDLE_0xF4; // 0x402; |
| } else if ((nfcFL.nfccFL._NFCC_DYNAMIC_DUAL_UICC || |
| nfcFL.nfccFL._NFC_NXP_STAT_DUAL_UICC_WO_EXT_SWITCH) && |
| (eseId == UICC2_ID)) // UICC |
| { |
| handle = EE_HANDLE_0xF8; // 0x481; |
| } else if (eseId == DH_ID) // Host |
| { |
| handle = NFA_EE_HANDLE_DH; // 0x400; |
| } else if (eseId == EE_HANDLE_0xF3 || eseId == EE_HANDLE_0xF4) { |
| handle = eseId; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: exit; SE-Handle = 0x%03X", fn, handle); |
| return handle; |
| } |
| bool SecureElement::SecEle_Modeset(uint8_t type) { |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| bool retval = true; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("set EE mode = 0x%X", type); |
| #if (NXP_EXTNS == TRUE) |
| if ((nfaStat = SecElem_EeModeSet(EE_HANDLE_0xF3, type)) == NFA_STATUS_OK) { |
| #if 0 |
| if (eeItem.ee_status == NFC_NFCEE_STATUS_INACTIVE) |
| { |
| LOG(ERROR) << StringPrintf("NFA_EeModeSet enable or disable success; status=0x%X", nfaStat); |
| retval = true; |
| } |
| #endif |
| } else |
| #endif |
| { |
| retval = false; |
| LOG(ERROR) << StringPrintf("NFA_EeModeSet failed"); |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s stat = 0x%X", __func__, retval); |
| return retval; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getEeHandleList |
| ** |
| ** Description: Get default Secure Element handle. |
| ** isHCEEnabled: whether host routing is enabled or not. |
| ** |
| ** Returns: Returns Secure Element list and count. |
| ** |
| *******************************************************************************/ |
| void SecureElement::getEeHandleList(tNFA_HANDLE* list, uint8_t* count) { |
| tNFA_HANDLE handle; |
| int i; |
| static const char fn[] = "SecureElement::getEeHandleList"; |
| *count = 0; |
| for (i = 0; i < mActualNumEe; i++) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: %d = 0x%X", fn, i, mEeInfo[i].ee_handle); |
| if ((mEeInfo[i].ee_handle == 0x401) || |
| (mEeInfo[i].ee_interface[0] == NCI_NFCEE_INTERFACE_HCI_ACCESS) || |
| (mEeInfo[i].ee_status == NFC_NFCEE_STATUS_INACTIVE)) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: %u = 0x%X", fn, i, mEeInfo[i].ee_handle); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("0x%x: 0x%x 0x%x 0x%x", mEeInfo[i].ee_handle, |
| mEeInfo[i].num_interface, mEeInfo[i].ee_interface[0], |
| mEeInfo[i].ee_status); |
| continue; |
| } |
| |
| handle = mEeInfo[i].ee_handle & ~NFA_HANDLE_GROUP_EE; |
| list[*count] = handle; |
| *count = *count + 1; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Handle %d = 0x%X", fn, i, handle); |
| } |
| } |
| |
| bool SecureElement::sendEvent(uint8_t event) { |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| bool retval = true; |
| |
| nfaStat = NFA_HciSendEvent(mNfaHciHandle, mNewPipeId, event, 0x00, NULL, 0x00, |
| NULL, 0); |
| |
| if (nfaStat != NFA_STATUS_OK) retval = false; |
| |
| return retval; |
| } |
| #if (NXP_EXTNS == TRUE) |
| bool SecureElement::configureNfceeETSI12() { |
| static const char fn[] = "SecureElement::configureNfceeETSI12"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| bool retval = true; |
| |
| nfaStat = NFA_HciConfigureNfceeETSI12(); |
| |
| if (nfaStat != NFA_STATUS_OK) retval = false; |
| |
| return retval; |
| } |
| |
| bool SecureElement::checkPipeStatusAndRecreate() { |
| bool pipeCorrectStatus = false; |
| bool success = true; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| se_apdu_gate_info gateInfo = NO_APDU_GATE; |
| uint8_t xmitBuffer[] = {0x00, 0x00, 0x00, 0x00}; |
| uint8_t EVT_SEND_DATA = 0x10; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("checkPipeStatusAndRecreate: Enter"); |
| pipeCorrectStatus = NFA_IsPipeStatusNotCorrect(); |
| if (pipeCorrectStatus) { |
| gateInfo = getApduGateInfo(); |
| if (gateInfo == ETSI_12_APDU_GATE) { |
| pipeStatus = NFA_HCI_ANY_OK; |
| IsCmdsentOnOpenDwpSession = true; |
| SyncEventGuard guard(mPipeStatusCheckEvent); |
| |
| nfaStat = NFA_HciSendEvent(mNfaHciHandle, mNewPipeId, EVT_SEND_DATA, |
| sizeof(xmitBuffer), xmitBuffer, 0x00, NULL, 0); |
| if (nfaStat == NFA_STATUS_OK) { |
| mPipeStatusCheckEvent.wait(500); |
| } |
| IsCmdsentOnOpenDwpSession = false; |
| if (pipeStatus == NFA_HCI_ANY_E_PIPE_NOT_OPENED) { |
| SyncEventGuard guard(mPipeOpenedEvent); |
| nfaStat = NFA_HciOpenPipe(mNfaHciHandle, mNewPipeId); |
| if (nfaStat != NFA_STATUS_OK) { |
| LOG(ERROR) << StringPrintf( |
| "checkPipeStatusAndRecreate:fail open pipe; error=0x%X", nfaStat); |
| } |
| |
| if (!mPipeOpenedEvent.wait(500) || (mCommandStatus != NFA_STATUS_OK)) { |
| success = false; |
| } |
| } |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("checkPipeStatusAndRecreate: Exit status x%x", success); |
| return success; |
| } |
| /******************************************************************************* |
| ** |
| ** Function: getUiccGateAndPipeList |
| ** |
| ** Description: Get the UICC's gate and pipe list present |
| ** |
| ** Returns: Returns valid PipeId(success) or zero(Failure). |
| ** |
| *******************************************************************************/ |
| uint8_t SecureElement::getUiccGateAndPipeList(uint8_t uiccNo) { |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| uint8_t pipeId = 0; |
| static const char fn[] = "SecureElement::getUiccGateAndPipeList"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s : get gate, pipe list mNfaHandle = %x ", fn, mNfaHciHandle); |
| /*HCI initialised and secure element available*/ |
| if ((mNfaHciHandle != NFA_HANDLE_INVALID)) { |
| SyncEventGuard guard(mPipeListEvent); |
| nfaStat = NFA_HciGetGateAndPipeList(mNfaHciHandle); |
| if (nfaStat == NFA_STATUS_OK) { |
| mPipeListEvent.wait(); |
| if (mHciCfg.status == NFA_STATUS_OK) { |
| for (uint8_t xx = 0; xx < mHciCfg.num_uicc_created_pipes; xx++) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s : get gate, pipe list host = 0x%x gate = 0x%x", fn, |
| mHciCfg.pipe[xx].dest_host, |
| mHciCfg.uicc_created_pipe[xx].dest_gate); |
| if (mHciCfg.uicc_created_pipe[xx].dest_gate == |
| NFA_HCI_CONNECTIVITY_GATE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: found configured gate: 0x%02x pipe: 0x%02x", fn, |
| mNewSourceGate, mNewPipeId); |
| if ((uiccNo == (EE_HANDLE_0xF4 & ~NFA_HANDLE_GROUP_EE) && |
| mHciCfg.uicc_created_pipe[xx].pipe_id == |
| CONNECTIVITY_PIPE_ID_UICC1) || |
| (uiccNo == (EE_HANDLE_0xF8 & ~NFA_HANDLE_GROUP_EE) && |
| mHciCfg.uicc_created_pipe[xx].pipe_id == |
| CONNECTIVITY_PIPE_ID_UICC2)) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("Found the pipeId = %x", |
| mHciCfg.uicc_created_pipe[xx].pipe_id); |
| pipeId = mHciCfg.uicc_created_pipe[xx].pipe_id; |
| break; |
| } |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s : No GatePresent", fn); |
| } |
| } |
| } |
| } |
| } |
| return pipeId; |
| } |
| /******************************************************************************* |
| ** |
| ** Function: getHciHandleInfo |
| ** |
| ** Description: Get the NFA hci handle registered with JNI |
| ** |
| ** Returns: Returns valid PipeId(success) or zero(Failure). |
| ** |
| *******************************************************************************/ |
| tNFA_HANDLE SecureElement::getHciHandleInfo() { return mNfaHciHandle; } |
| /******************************************************************************* |
| ** |
| ** Function: eSE_ClearAllPipe_thread_handler |
| ** |
| ** Description: Upon receiving the Clear ALL pipes take lock and start |
| *polling |
| ** |
| ** Returns: void. |
| ** |
| *******************************************************************************/ |
| void* eSE_ClearAllPipe_thread_handler(void* data) { |
| static const char fn[] = "eSE_ClearAllPipe_thread_handler"; |
| uint8_t *host = NULL, nfcee_type = 0; |
| SecureElement& se = SecureElement::getInstance(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter:", fn); |
| if (NULL == data) { |
| LOG(ERROR) << StringPrintf("%s: Invalid argument", fn); |
| return NULL; |
| } |
| /*Nfc initialization not completed*/ |
| if (sNfcee_disc_state < UICC_SESSION_INTIALIZATION_DONE) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("eSE_ClearAllPipe_thread_handler PENDING return"); |
| sNfcee_disc_state = UICC_CLEAR_ALL_PIPE_NTF_RECEIVED; |
| return NULL; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "eSE_ClearAllPipe_thread_handler state NFCEE_STATE_DISCOVERED"); |
| /* Copying the host-id from the parent thread and freeing allocated space */ |
| host = (uint8_t*)data; |
| nfcee_type = *host; |
| free(data); |
| |
| SyncEventGuard guard(se.mNfceeInitCbEvent); |
| switch (nfcee_type) { |
| case 0x02: |
| case 0x80: |
| /* Poll for UICC1 session */ |
| android::checkforNfceeConfig(UICC1 | UICC2); |
| break; |
| case 0x81: |
| /* Poll for UICC2 session */ |
| android::checkforNfceeConfig(UICC1 | UICC2); |
| break; |
| default: |
| break; |
| } |
| se.mNfceeInitCbEvent.notifyOne(); |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: initializeEeHandle |
| ** |
| ** Description: Set NFCEE handle. |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| bool SecureElement::initializeEeHandle() { |
| if (NFA_GetNCIVersion() == NCI_VERSION_2_0) |
| EE_HANDLE_0xF4 = 0x480; |
| else |
| EE_HANDLE_0xF4 = 0x402; |
| return true; |
| } |
| /******************************************************************************* |
| ** |
| ** Function: eSE_ClearAllPipe_handler |
| ** |
| ** Description: Handler for Clear ALL pipes ntf recreate |
| ** APDU pipe for eSE |
| ** |
| ** Returns: void. |
| ** |
| *******************************************************************************/ |
| void SecureElement::eSE_ClearAllPipe_handler(uint8_t host) { |
| static const char fn[] = "SecureElement::eSE_ClearAllPipe_handler"; |
| pthread_t thread; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| uint8_t* host_id = (uint8_t*)malloc(sizeof(uint8_t)); |
| *host_id = host; |
| LOG(ERROR) << StringPrintf("%s; Enter", fn); |
| if (pthread_create(&thread, &attr, &eSE_ClearAllPipe_thread_handler, |
| (void*)host_id) < 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Thread creation failed"); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Thread creation success"); |
| } |
| pthread_attr_destroy(&attr); |
| } |
| #endif |
| |
| #if (NXP_EXTNS == TRUE) |
| /******************************************************************************* |
| ** |
| ** Function NfccStandByTimerOperation |
| ** |
| ** Description start/stops the standby timer |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void SecureElement::NfccStandByOperation(nfcc_standby_operation_t value) { |
| if (!nfcFL.nfcNxpEse) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s nfcNxpEse not available. Returning", __func__); |
| return; |
| } |
| static IntervalTimer |
| mNFCCStandbyModeTimer; // timer to enable standby mode for NFCC |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| bool stat = false; |
| mNfccStandbyMutex.lock(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "In SecureElement::NfccStandByOperation value = %d, state = %d", value, |
| standby_state); |
| switch (value) { |
| case STANDBY_TIMER_START: |
| standby_state = STANDBY_MODE_TIMER_ON; |
| if (nfccStandbytimeout > 0) { |
| mNFCCStandbyModeTimer.set(nfccStandbytimeout, |
| NFCC_StandbyModeTimerCallBack); |
| } |
| break; |
| case STANDBY_MODE_OFF: { |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| if (standby_state == STANDBY_MODE_SUSPEND) { |
| if ((mNfccPowerMode == 1) && !(dual_mode_current_state & SPI_ON)) { |
| nfaStat = setNfccPwrConfig(POWER_ALWAYS_ON | COMM_LINK_ACTIVE); |
| if (nfaStat != NFA_STATUS_OK) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: power link command failed", __func__); |
| break; |
| } else { |
| SecEle_Modeset(0x01); |
| } |
| } |
| } |
| } |
| } // this is to handle stop timer also. |
| FALLTHROUGH; |
| case STANDBY_TIMER_STOP: { |
| if (nfccStandbytimeout > 0) mNFCCStandbyModeTimer.kill(); |
| } |
| standby_state = STANDBY_MODE_OFF; |
| if (spiDwpSyncState & STATE_DWP_CLOSE) { |
| spiDwpSyncState ^= STATE_DWP_CLOSE; |
| } |
| break; |
| case STANDBY_MODE_ON: { |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY_PROP) { |
| if (standby_state == STANDBY_MODE_ON) |
| break; |
| else if (nfccStandbytimeout > 0) |
| mNFCCStandbyModeTimer.kill(); |
| } |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) |
| if (nfccStandbytimeout > 0) mNFCCStandbyModeTimer.kill(); |
| |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| /*To maintain dwp standby mode on case when spi is close later*/ |
| spiDwpSyncState = STATE_IDLE; |
| if (dual_mode_current_state & SPI_ON) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: SPI is ON-StandBy not allowed", __func__); |
| standby_state = STANDBY_MODE_ON; |
| /*To maintain wired session close state during SPI on*/ |
| spiDwpSyncState = STATE_DWP_CLOSE; |
| break; |
| } |
| nfaStat = setNfccPwrConfig(NFCC_DECIDES); |
| stat = SecureElement::getInstance().sendEvent( |
| SecureElement::EVT_END_OF_APDU_TRANSFER); |
| if (stat) { |
| standby_state = STANDBY_MODE_ON; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s sending standby mode command EVT_END_OF_APDU_TRANSFER " |
| "successful", |
| __func__); |
| } |
| } |
| } |
| } |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY == true) break; |
| FALLTHROUGH; |
| case STANDBY_TIMER_TIMEOUT: { |
| bool stat = false; |
| if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| /*Maintain suspend apdu state to send when spi is closed later*/ |
| spiDwpSyncState |= STATE_TIME_OUT; |
| /*Clear apdu state to activate DWP link once spi stand-alone triggered |
| */ |
| if (spiDwpSyncState & STATE_WK_ENBLE) { |
| spiDwpSyncState ^= STATE_WK_ENBLE; |
| } |
| } |
| if (dual_mode_current_state & SPI_ON) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: SPI is ON-StandBy not allowed", __func__); |
| standby_state = STANDBY_MODE_ON; |
| mNfccStandbyMutex.unlock(); |
| return; |
| } |
| } |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY == true) { |
| if (standby_state != STANDBY_MODE_TIMER_ON) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s the timer must be stopped by next atr/transceive, ignoring " |
| "timeout", |
| __func__); |
| break; |
| } |
| } |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY_PROP) |
| /*Send the EVT_END_OF_APDU_TRANSFER after the transceive timer timed |
| * out*/ |
| stat = SecureElement::getInstance().sendEvent( |
| SecureElement::EVT_END_OF_APDU_TRANSFER); |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| setNfccPwrConfig(POWER_ALWAYS_ON); |
| stat = SecureElement::getInstance().sendEvent( |
| SecureElement::EVT_SUSPEND_APDU_TRANSFER); |
| } |
| if (stat) { |
| standby_state = STANDBY_MODE_SUSPEND; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s sending standby command successful", __func__); |
| if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE && |
| nfcFL.eseFL._WIRED_MODE_STANDBY_PROP) |
| spiDwpSyncState = STATE_IDLE; |
| } |
| } break; |
| case STANDBY_GPIO_HIGH: { |
| jint ret_val = -1; |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| |
| /* Set the ESE VDD gpio to high to make sure P61 is powered, even if NFCC |
| * is in standby |
| */ |
| ret_val = NFC_EnableWired((void*)&status); |
| if (ret_val < 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("NFC_EnableWired failed"); |
| } else { |
| if (status != NFCSTATUS_SUCCESS) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("SE is being used by SPI"); |
| } |
| } |
| } break; |
| case STANDBY_GPIO_LOW: { |
| jint ret_val = -1; |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| /* Set the ESE VDD gpio to low to make sure P61 is reset. */ |
| ret_val = NFC_DisableWired((void*)&status); |
| if (ret_val < 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("NFC_DisableWired failed"); |
| } else { |
| if (status != NFCSTATUS_SUCCESS) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("SE is not being released by Pn54x driver"); |
| } |
| } |
| } break; |
| case STANDBY_ESE_PWR_RELEASE: { |
| int ret_val = -1; |
| tNFA_STATUS status = NFCSTATUS_FAILED; |
| /* Set the ESE VDD gpio to HIGH. */ |
| ret_val = NFC_ReleaseEsePwr((void*)&status); |
| if (ret_val < 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("NFC_ReleaseEsePwr: Failed"); |
| } |
| } break; |
| |
| case STANDBY_ESE_PWR_ACQUIRE: { |
| int ret_val = -1; |
| tNFA_STATUS status = NFCSTATUS_FAILED; |
| /* Set the ESE VDD gpio to low. */ |
| ret_val = NFC_AcquireEsePwr((void*)&status); |
| if (ret_val < 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("NFC_AcquireEsePwr: Failed"); |
| } |
| } break; |
| default: |
| LOG(ERROR) << StringPrintf("Wrong param"); |
| break; |
| } |
| mNfccStandbyMutex.unlock(); |
| } |
| /******************************************************************************* |
| ** |
| ** Function eSE_Chip_Reset |
| ** |
| ** Description Performs Chip Reset on eSE using ISO_RST pin. |
| ** |
| ** Returns Returns Status SUCCESS or FAILED. |
| ** |
| *******************************************************************************/ |
| NFCSTATUS SecureElement::eSE_Chip_Reset(void) { |
| jint ret_val = -1; |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("eSE_Chip_Reset"); |
| SecureElement::getInstance().SecEle_Modeset(0x00); |
| /* Reset P73 using ISO Reset Pin. */ |
| ret_val = NFC_eSEChipReset((void*)&status); |
| if (ret_val < 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Reset eSE failed"); |
| } else { |
| if (status != NFCSTATUS_SUCCESS) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("SE is not being released by Pn54x driver"); |
| } |
| } |
| SecureElement::getInstance().SecEle_Modeset(0x01); |
| return status; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: reconfigureEseHciInit |
| ** |
| ** Description: Reinitialize the HCI network for SecureElement |
| ** |
| ** Returns: Returns Status SUCCESS or FAILED. |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS SecureElement::reconfigureEseHciInit() { |
| tNFA_STATUS status = NFA_STATUS_FAILED; |
| if (!nfcFL.eseFL._JCOP_WA_ENABLE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "reconfigureEseHciInit JCOP_WA_ENABLE not found. Returning"); |
| return status; |
| } |
| |
| if (isActivatedInListenMode()) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "Denying HCI re-initialization due to SE listen mode active"); |
| return status; |
| } |
| |
| if (isRfFieldOn()) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "Denying HCI re-initialization due to SE in active RF field"); |
| return status; |
| } |
| if (android::isDiscoveryStarted() == true) { |
| android::startRfDiscovery(false); |
| } |
| status = android::ResetEseSession(); |
| if (status == NFA_STATUS_OK) { |
| SecEle_Modeset(0x00); |
| usleep(100 * 1000); |
| |
| SecEle_Modeset(0x01); |
| usleep(300 * 1000); |
| } |
| |
| android::startRfDiscovery(true); |
| return status; |
| } |
| |
| se_apdu_gate_info SecureElement::getApduGateInfo() { |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| se_apdu_gate_info ret = NO_APDU_GATE; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("getApduGateInfo : get gate, pipe list"); |
| /*HCI initialised and secure element available*/ |
| if ((mNfaHciHandle != NFA_HANDLE_INVALID) && |
| (mActiveEeHandle != NFA_HANDLE_INVALID)) { |
| SyncEventGuard guard(mPipeListEvent); |
| nfaStat = NFA_HciGetGateAndPipeList(mNfaHciHandle); |
| if (nfaStat == NFA_STATUS_OK) { |
| mPipeListEvent.wait(); |
| if (mHciCfg.status == NFA_STATUS_OK) { |
| for (uint8_t xx = 0; xx < mHciCfg.num_pipes; xx++) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "getApduGateInfo : get gate, pipe list host = 0x%x gate = 0x%x", |
| mHciCfg.pipe[xx].dest_host, mHciCfg.pipe[xx].dest_gate); |
| if ((mHciCfg.pipe[xx].dest_host == |
| (EE_HANDLE_0xF3 & ~NFA_HANDLE_GROUP_EE)) && |
| (mHciCfg.pipe[xx].dest_gate == NFA_HCI_ETSI12_APDU_GATE)) { |
| ret = ETSI_12_APDU_GATE; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "getApduGateInfo: found configured gate: 0x%02x pipe: 0x%02x", |
| mNewSourceGate, mNewPipeId); |
| break; |
| } else if ((mHciCfg.pipe[xx].dest_host == |
| (EE_HANDLE_0xF3 & ~NFA_HANDLE_GROUP_EE)) && |
| (mHciCfg.pipe[xx].dest_gate == 0xF0)) { |
| ret = PROPREITARY_APDU_GATE; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "propreitary ApduGatePresent: found configured gate: 0x%02x " |
| "pipe: 0x%02x", |
| mNewSourceGate, mNewPipeId); |
| break; |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("No ApduGatePresent"); |
| } |
| } |
| } |
| } |
| } |
| return ret; |
| } |
| |
| bool SecureElement::checkForWiredModeAccess() { |
| static const char fn[] = "checkForWiredModeAccess"; |
| bool status = true; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s; enter", fn); |
| |
| if (mIsExclusiveWiredMode) { |
| if (mIsWiredModeOpen) { |
| return status; |
| } |
| if (android::isp2pActivated() || isActivatedInListenMode() || |
| isRfFieldOn()) { |
| status = false; |
| return status; |
| } |
| } else { |
| if (mIsWiredModeBlocked) { |
| hold_wired_mode = true; |
| SyncEventGuard guard(mWiredModeHoldEvent); |
| mWiredModeHoldEvent.wait(); |
| status = true; |
| return status; |
| } else { |
| status = true; |
| return status; |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s; status:%d ", fn, status); |
| return status; |
| } |
| #endif |
| |
| int SecureElement::decodeBerTlvLength(uint8_t* data, int index, |
| int data_length) { |
| int decoded_length = -1; |
| int length = 0; |
| int temp = data[index] & 0xff; |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "decodeBerTlvLength index= %d data[index+0]=0x%x data[index+1]=0x%x " |
| "len=%d", |
| index, data[index], data[index + 1], data_length); |
| |
| if (temp < 0x80) { |
| decoded_length = temp; |
| } else if (temp == 0x81) { |
| if (index < data_length) { |
| length = data[index + 1] & 0xff; |
| if (length < 0x80) { |
| LOG(ERROR) << StringPrintf("Invalid TLV length encoding!"); |
| goto TheEnd; |
| } |
| if (data_length < length + index) { |
| LOG(ERROR) << StringPrintf("Not enough data provided!"); |
| goto TheEnd; |
| } |
| } else { |
| LOG(ERROR) << StringPrintf("Index %d out of range! [0..[%d", index, |
| data_length); |
| goto TheEnd; |
| } |
| decoded_length = length; |
| } else if (temp == 0x82) { |
| if ((index + 1) < data_length) { |
| length = ((data[index] & 0xff) << 8) | (data[index + 1] & 0xff); |
| } else { |
| LOG(ERROR) << StringPrintf("Index out of range! [0..[%d", data_length); |
| goto TheEnd; |
| } |
| index += 2; |
| if (length < 0x100) { |
| LOG(ERROR) << StringPrintf("Invalid TLV length encoding!"); |
| goto TheEnd; |
| } |
| if (data_length < length + index) { |
| LOG(ERROR) << StringPrintf("Not enough data provided!"); |
| goto TheEnd; |
| } |
| decoded_length = length; |
| } else if (temp == 0x83) { |
| if ((index + 2) < data_length) { |
| length = ((data[index] & 0xff) << 16) | ((data[index + 1] & 0xff) << 8) | |
| (data[index + 2] & 0xff); |
| } else { |
| LOG(ERROR) << StringPrintf("Index out of range! [0..[%d", data_length); |
| goto TheEnd; |
| } |
| index += 3; |
| if (length < 0x10000) { |
| LOG(ERROR) << StringPrintf("Invalid TLV length encoding!"); |
| goto TheEnd; |
| } |
| if (data_length < length + index) { |
| LOG(ERROR) << StringPrintf("Not enough data provided!"); |
| goto TheEnd; |
| } |
| decoded_length = length; |
| } else { |
| LOG(ERROR) << StringPrintf("Unsupported TLV length encoding!"); |
| } |
| TheEnd: |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("decoded_length = %d", decoded_length); |
| |
| return decoded_length; |
| } |
| #if (NXP_EXTNS == TRUE) |
| void cleanupStack(void* p) { return; } |
| |
| /******************************************************************************* |
| ** |
| ** Function: spiEventHandlerThread_cleanup_handler |
| ** |
| ** Description: Handler to cleanup before the spiEventHandler Thread exits |
| ** |
| ** |
| ** Returns: None . |
| ** |
| *******************************************************************************/ |
| static void spiEventHandlerThread_cleanup_handler(void* arg) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Inside", __func__); |
| /* Releasing if DWP/SPI mutex is in locked state */ |
| if (!android::mSPIDwpSyncMutex.tryLock()) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: SE access is ongoing", __func__); |
| } |
| android::mSPIDwpSyncMutex.unlock(); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: spiEventHandlerThread_exit_handler |
| ** |
| ** Description: Handler to receive the signal |
| ** (signal:SIG_SPI_EVENT_HANDLER=45 ) to exit |
| ** |
| ** Returns: None . |
| ** |
| *******************************************************************************/ |
| void spiEventHandlerThread_exit_handler(int sig) { |
| pthread_exit(0); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: spiEventHandlerThread |
| ** |
| ** Description: thread to trigger on SPI event |
| ** |
| ** Returns: None . |
| ** |
| *******************************************************************************/ |
| void* spiEventHandlerThread(void* arg) { |
| SecureElement& se = SecureElement::getInstance(); |
| |
| if (!nfcFL.nfcNxpEse) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: nfcNxpEse not available. Returning", __func__); |
| return NULL; |
| } |
| if (!nfcFL.eseFL._ESE_SVDD_SYNC && !nfcFL.eseFL._ESE_JCOP_DWNLD_PROTECTION && |
| !nfcFL.nfccFL._NFCC_SPI_FW_DOWNLOAD_SYNC && |
| !nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Not allowed. Returning", __func__); |
| return NULL; |
| } |
| (void)arg; |
| uint16_t usEvent = 0, usEvtLen = 0; |
| tNFC_STATUS stat; |
| |
| NFCSTATUS ese_status = NFA_STATUS_FAILED; |
| |
| struct sigaction actions; |
| static sigset_t mask; |
| memset(&actions, 0, sizeof(actions)); |
| sigemptyset(&actions.sa_mask); |
| sigaddset(&mask, SIG_SPI_EVENT_HANDLER); |
| actions.sa_flags = 0; |
| actions.sa_handler = spiEventHandlerThread_exit_handler; |
| sigaction(SIG_SPI_EVENT_HANDLER, &actions, NULL); |
| if (pthread_sigmask(SIG_UNBLOCK, &mask, NULL) != 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: spiEventHandlerThread pthread_sigmask %d", __func__, errno); |
| } |
| pthread_cleanup_push(spiEventHandlerThread_cleanup_handler, NULL); |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); |
| while (android::nfcManager_isNfcActive() && |
| !android::nfcManager_isNfcDisabling() && |
| (android::nfcManager_getNfcState() != NFC_OFF)) { |
| if (true == |
| gSPIEvtQueue |
| .isEmpty()) /* Wait for the event only if the queue is empty */ |
| { /* scope of the guard start */ |
| SyncEventGuard guard(sSPISignalHandlerEvent); |
| sSPISignalHandlerEvent.wait(); |
| LOG(ERROR) << StringPrintf("%s: Empty evt received", __FUNCTION__); |
| } /* scope of the guard end */ |
| /* Dequeue the received signal */ |
| gSPIEvtQueue.dequeue((uint8_t*)&usEvent, (uint16_t)SIGNAL_EVENT_SIZE, |
| usEvtLen); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: evt received %x len %x", __FUNCTION__, usEvent, usEvtLen); |
| |
| if (usEvent & P61_STATE_SPI_PRIO) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: SPI PRIO request Signal....\n", __func__); |
| hold_the_transceive = true; |
| setSPIState(true); |
| } else if (usEvent & P61_STATE_SPI_PRIO_END) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: SPI PRIO End Signal\n", __func__); |
| hold_the_transceive = false; |
| if (!se.mIsWiredModeOpen) spiDwpSyncState = STATE_DWP_CLOSE; |
| setSPIState(false); |
| SyncEventGuard guard(sSPIPrioSessionEndEvent); |
| sSPIPrioSessionEndEvent.notifyOne(); |
| } else if (usEvent & P61_STATE_SPI) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: SPI OPEN request Signal....\n", __func__); |
| setSPIState(true); |
| } else if (usEvent & P61_STATE_SPI_END) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: SPI End Signal\n", __func__); |
| hold_the_transceive = false; |
| if (!se.mIsWiredModeOpen) spiDwpSyncState = STATE_DWP_CLOSE; |
| setSPIState(false); |
| } |
| |
| if ((usEvent & P61_STATE_SPI_SVDD_SYNC_START) || |
| (usEvent & P61_STATE_DWP_SVDD_SYNC_START)) { |
| if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| if ((usEvent & P61_STATE_SPI_PRIO) || (usEvent & P61_STATE_SPI)) { |
| stat = nfaVSC_ForceDwpOnOff(true); |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| if (android::nfcManager_getNfcState() != NFC_OFF) |
| NFC_RelForceDwpOnOffWait((void*)&stat); |
| } |
| } else if ((usEvent & P61_STATE_SPI_PRIO_END) || |
| (usEvent & P61_STATE_SPI_END)) { |
| /* Locking the eSE(DWP/SPI) access, will be released after SVDD SYNC |
| * OFF command callback ioctl returns */ |
| android::mSPIDwpSyncMutex.lock(); |
| stat = nfaVSC_ForceDwpOnOff(false); |
| } |
| } |
| if (stat != NFA_STATUS_OK) { |
| NFC_RelSvddWait((void*)&stat); |
| android::mSPIDwpSyncMutex.unlock(); |
| } else if (nfcFL.eseFL._ESE_SVDD_SYNC) { |
| nfaVSC_SVDDSyncOnOff(true); |
| } |
| } else if (nfcFL.eseFL._ESE_SVDD_SYNC && |
| ((usEvent & P61_STATE_SPI_SVDD_SYNC_END) || |
| (usEvent & P61_STATE_DWP_SVDD_SYNC_END))) { |
| nfaVSC_SVDDSyncOnOff(false); |
| } |
| |
| else if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE && |
| ((usEvent & P61_STATE_SPI_PRIO) || (usEvent & P61_STATE_SPI))) { |
| /* Locking the eSE(DWP/SPI) access, will be released after Force DWP |
| * ON/OFF callback ioctl returns */ |
| android::mSPIDwpSyncMutex.lock(); |
| stat = nfaVSC_ForceDwpOnOff(true); |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| if (android::nfcManager_getNfcState() != NFC_OFF) { |
| NFC_RelForceDwpOnOffWait((void*)&stat); |
| } |
| } |
| /* Releasing the eSE access lock */ |
| android::mSPIDwpSyncMutex.unlock(); |
| } else if (nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE && |
| ((usEvent & P61_STATE_SPI_PRIO_END) || |
| (usEvent & P61_STATE_SPI_END))) { |
| nfaVSC_ForceDwpOnOff(false); |
| } |
| |
| if (nfcFL.eseFL._ESE_JCOP_DWNLD_PROTECTION) { |
| if (usEvent == JCP_DWNLD_INIT) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: JCOP OS download init request....=%d\n", __func__, usEvent); |
| if (android::nfcManager_checkNfcStateBusy() == false) { |
| if (android::isDiscoveryStarted() == true) { |
| android::startRfDiscovery(false); |
| } |
| NFC_SetP61Status((void*)&ese_status, JCP_DWNLD_START); |
| } |
| } else if (usEvent == JCP_DWP_DWNLD_COMPLETE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: JCOP OS download end request...=%d\n", __func__, usEvent); |
| if (android::isDiscoveryStarted() == false) { |
| android::startRfDiscovery(true); |
| } |
| } |
| } else if (nfcFL.nfccFL._NFCC_SPI_FW_DOWNLOAD_SYNC && |
| ((usEvent & P61_STATE_SPI_PRIO_END) || |
| (usEvent & P61_STATE_SPI_END))) { |
| if (android::nfcManager_isNfcActive() && |
| !android::nfcManager_isNfcDisabling() && |
| (android::nfcManager_getNfcState() != NFC_OFF)) { |
| android::requestFwDownload(); |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Event handled EXIT %x %d %d %d", __func__, usEvent, |
| android::nfcManager_isNfcActive(), android::nfcManager_isNfcDisabling(), |
| android::nfcManager_getNfcState()); |
| usEvent = 0x00; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); |
| pthread_cleanup_pop(1); |
| return NULL; |
| } |
| |
| bool createSPIEvtHandlerThread() { |
| if (!nfcFL.nfcNxpEse) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: nfcNxpEse not available. Returning", __func__); |
| return false; |
| } |
| if (!nfcFL.eseFL._ESE_SVDD_SYNC && !nfcFL.eseFL._ESE_JCOP_DWNLD_PROTECTION && |
| !nfcFL.nfccFL._NFCC_SPI_FW_DOWNLOAD_SYNC && |
| !nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Not allowed. Returning", __func__); |
| return false; |
| } |
| |
| bool stat = true; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); |
| if (pthread_create(&spiEvtHandler_thread, &attr, spiEventHandlerThread, |
| NULL) != 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("Unable to create the thread"); |
| stat = false; |
| } |
| pthread_attr_destroy(&attr); |
| return stat; |
| } |
| |
| void releaseSPIEvtHandlerThread() { |
| if (!nfcFL.nfcNxpEse) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: nfcNxpEse not available. Returning", __func__); |
| return; |
| } |
| if (!nfcFL.eseFL._ESE_SVDD_SYNC && !nfcFL.eseFL._ESE_JCOP_DWNLD_PROTECTION && |
| !nfcFL.nfccFL._NFCC_SPI_FW_DOWNLOAD_SYNC && |
| !nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Not allowed. Returning", __func__); |
| return; |
| } |
| |
| uint16_t usEvent = 0; |
| uint16_t usEvtLen = 0; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("releaseSPIEvtHandlerThread"); |
| while (!gSPIEvtQueue |
| .isEmpty()) /* Wait for the event only if the queue is empty */ |
| { /* scope of the guard start */ |
| /* Dequeue the received signal */ |
| gSPIEvtQueue.dequeue((uint8_t*)&usEvent, (uint16_t)SIGNAL_EVENT_SIZE, |
| usEvtLen); |
| LOG(ERROR) << StringPrintf("%s: Clearing queue ", __func__); |
| } /* scope of the guard end */ |
| { |
| SyncEventGuard guard(SecureElement::getInstance().mModeSetNtf); |
| SecureElement::getInstance().mModeSetNtf.notifyOne(); |
| } |
| /* Notifying/Signalling the signal handler thread to exit */ |
| if (pthread_kill(spiEvtHandler_thread, SIG_SPI_EVENT_HANDLER) != 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("Killed spiEvtHandler_thread error status:%d", errno); |
| } else { |
| pthread_join(spiEvtHandler_thread, NULL); |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("Exit releaseSPIEvtHandlerThread"); |
| } |
| /******************************************************************************* |
| ** |
| ** Function: nfaVSC_SVDDSyncOnOffCallback |
| ** |
| ** Description: callback to process the svdd protection response from FW |
| ** |
| ** |
| ** Returns: void. |
| ** |
| *******************************************************************************/ |
| static void nfaVSC_SVDDSyncOnOffCallback(uint8_t event, uint16_t param_len, |
| uint8_t* p_param) { |
| if (!nfcFL.nfcNxpEse || !nfcFL.eseFL._ESE_SVDD_SYNC) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: nfcNxpEse or ESE_SVDD_SYNC not available. Returning", __func__); |
| return; |
| } |
| |
| (void)event; |
| tNFC_STATUS nfaStat = NFA_STATUS_OK; |
| char fn[] = "nfaVSC_SVDDProtectionCallback"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s param_len = %d ", __func__, param_len); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s status = 0x%X ", __func__, p_param[3]); |
| SyncEventGuard guard(sSPISVDDSyncOnOffEvent); |
| sSPISVDDSyncOnOffEvent.notifyOne(); |
| if (NFC_RelSvddWait((void*)&nfaStat) != 0) { |
| LOG(ERROR) << StringPrintf("%s: NFC_RelSvddWait failed ret = %d", fn, |
| nfaStat); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: nfaVSC_SVDDSyncOnOff |
| ** |
| ** Description: starts and stops the svdd protection in FW |
| ** |
| ** |
| ** Returns: void. |
| ** |
| *******************************************************************************/ |
| static void nfaVSC_SVDDSyncOnOff(bool type) { |
| if (!nfcFL.nfcNxpEse || !nfcFL.eseFL._ESE_SVDD_SYNC) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: nfcNxpEse or ESE_SVDD_SYNC not available. Returning", __func__); |
| return; |
| } |
| |
| SecureElement& se = SecureElement::getInstance(); |
| if (se.mIsWiredModeOpen) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("nfaVSC_SVDDSyncOnOff wiredModeOpen"); |
| if (type == false) android::mSPIDwpSyncMutex.unlock(); |
| tNFC_STATUS nfaStat = NFA_STATUS_OK; |
| if (NFC_RelSvddWait((void*)&nfaStat) != 0) { |
| LOG(ERROR) << StringPrintf("%s: NFC_RelSvddWait failed ret = %d", |
| __func__, nfaStat); |
| } |
| return; |
| } |
| |
| if (!android::nfcManager_isNfcActive() || |
| android::nfcManager_isNfcDisabling() || |
| (android::nfcManager_getNfcState() == NFC_OFF)) { |
| LOG(ERROR) << StringPrintf("%s: NFC is no longer active.", __func__); |
| android::mSPIDwpSyncMutex.unlock(); |
| tNFC_STATUS nfaStat = NFA_STATUS_OK; |
| if (NFC_RelSvddWait((void*)&nfaStat) != 0) { |
| LOG(ERROR) << StringPrintf("%s: NFC_RelSvddWait failed ret = %d", |
| __func__, nfaStat); |
| } |
| return; |
| } |
| |
| tNFC_STATUS stat; |
| uint8_t param = 0x00; |
| if (type == true) { |
| param = 0x01; // SVDD protection on |
| } |
| stat = NFA_SendVsCommand(0x31, 0x01, ¶m, nfaVSC_SVDDSyncOnOffCallback); |
| if (NFA_STATUS_OK == stat) { |
| SyncEventGuard guard(sSPISVDDSyncOnOffEvent); |
| sSPISVDDSyncOnOffEvent.wait(50); |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_SendVsCommand pass stat = %d", __func__, stat); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: NFA_SendVsCommand failed stat = %d", __func__, stat); |
| } |
| if (type == false) android::mSPIDwpSyncMutex.unlock(); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: nfaVSC_ForceDwpOnOff |
| ** |
| ** Description: starts and stops the dwp channel |
| ** |
| ** |
| ** Returns: void. |
| ** |
| *******************************************************************************/ |
| static tNFA_STATUS nfaVSC_ForceDwpOnOff(bool type) { |
| if (!nfcFL.nfcNxpEse || !nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: nfcNxpEse or DWP_SPI_SYNC_ENABLE not available." |
| " Returning", |
| __func__); |
| return NFA_STATUS_OK; |
| } |
| |
| tNFC_STATUS stat = NFA_STATUS_FAILED; |
| uint8_t xmitBuffer[] = {0x00, 0x00, 0x00, 0x00}; |
| uint8_t EVT_SEND_DATA = 0x10; |
| uint8_t EVT_END_OF_APDU_TRANSFER = 0x21; |
| SecureElement& se = SecureElement::getInstance(); |
| |
| /*Do not set powerLink and modeSet if wiredMode is open, except in case of |
| * standby timeout. In case of wiredMode standby timeout, and SPI open/close, |
| * send necessary powerLink and modeSet commands for SPI communications*/ |
| if (!(spiDwpSyncState & STATE_TIME_OUT) && (se.mIsWiredModeOpen)) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: DWP wired mode is On", __func__); |
| return NFA_STATUS_OK; |
| } |
| |
| if (!android::nfcManager_isNfcActive() || |
| android::nfcManager_isNfcDisabling() || |
| (android::nfcManager_getNfcState() == NFC_OFF)) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFC is not activated", __FUNCTION__); |
| return NFA_STATUS_OK; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "nfaVSC_ForceDwpOnOff: syncstate = %d, type = %d", spiDwpSyncState, type); |
| if ((type == true) && !(spiDwpSyncState & STATE_WK_ENBLE)) { |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| stat = SecureElement::getInstance().setNfccPwrConfig( |
| SecureElement::getInstance().POWER_ALWAYS_ON | |
| SecureElement::getInstance().COMM_LINK_ACTIVE); |
| if (stat != NFA_STATUS_OK) return stat; |
| if (!SecureElement::getInstance().SecEle_Modeset(0x1)) |
| return NFA_STATUS_FAILED; |
| spiDwpSyncState |= STATE_WK_ENBLE; |
| } else { |
| spiDwpSyncState |= STATE_WK_ENBLE; |
| memset(xmitBuffer, 0, sizeof(xmitBuffer)); |
| stat = NFA_HciSendEvent(NFA_HANDLE_GROUP_HCI, 0x19, EVT_SEND_DATA, |
| sizeof(xmitBuffer), xmitBuffer, 0, NULL, 0); |
| if (stat == NFA_STATUS_OK) { |
| spiDwpSyncState |= STATE_WK_WAIT_RSP; |
| SyncEventGuard guard(sSPIForceEnableDWPEvent); |
| sSPIForceEnableDWPEvent.wait(50); |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HciSendEvent failed stat = %d type = %d", |
| __func__, stat, type); |
| } |
| } |
| } else if (type == false) { |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| /*Just stand by timer expired*/ |
| if (spiDwpSyncState & STATE_TIME_OUT) { |
| /*Clear APDU state to activate DWP link once spi standalone is |
| * triggered*/ |
| if (spiDwpSyncState & STATE_WK_ENBLE) { |
| spiDwpSyncState ^= STATE_WK_ENBLE; |
| } |
| stat = SecureElement::getInstance().setNfccPwrConfig( |
| SecureElement::getInstance().POWER_ALWAYS_ON); |
| if (stat != NFA_STATUS_OK) return stat; |
| stat = SecureElement::getInstance().sendEvent( |
| SecureElement::EVT_SUSPEND_APDU_TRANSFER); |
| if (stat) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s sending standby mode command successful", __func__); |
| } else { |
| return stat; |
| } |
| standby_state = STANDBY_MODE_SUSPEND; |
| /* DWP is still in standby timeout state */ |
| spiDwpSyncState = STATE_IDLE | STATE_TIME_OUT; |
| return NFA_STATUS_OK; |
| } |
| /*If DWP session is closed*/ |
| stat = SecureElement::getInstance().setNfccPwrConfig( |
| SecureElement::getInstance().NFCC_DECIDES); |
| if (stat != NFA_STATUS_OK) { |
| spiDwpSyncState = STATE_IDLE; |
| return stat; |
| } |
| } |
| |
| if (spiDwpSyncState & STATE_DWP_CLOSE) { |
| stat = |
| NFA_HciSendEvent(NFA_HANDLE_GROUP_HCI, 0x19, EVT_END_OF_APDU_TRANSFER, |
| 0x00, NULL, 0x00, NULL, 0); |
| if (NFA_STATUS_OK != stat) |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: NFA_HciSendEvent failed stat = %d, type = %d", |
| __func__, stat, type); |
| } |
| spiDwpSyncState = STATE_IDLE; |
| } |
| |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "nfaVSC_ForceDwpOnOff: syncstate = %d, type = %d", spiDwpSyncState, type); |
| return NFA_STATUS_OK; |
| } |
| |
| bool SecureElement::enableDwp(void) { |
| if (!nfcFL.nfcNxpEse || !nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: nfcNxpEse or DWP_SPI_SYNC_ENABLE not available." |
| " Returning", |
| __func__); |
| return false; |
| } |
| bool stat = false; |
| static const char fn[] = "SecureElement::enableDwp"; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("enter %s", fn); |
| |
| mActiveEeHandle = getDefaultEeHandle(); |
| if (mActiveEeHandle == EE_HANDLE_0xF3) { |
| stat = connectEE(); |
| } |
| mIsPiping = false; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("exit %s.. stat = %d", fn, stat); |
| return stat; |
| } |
| |
| void spi_prio_signal_handler(int signum, siginfo_t* info, void* unused) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Inside the Signal Handler %d\n", __func__, SIG_NFC); |
| if (nfcFL.chipType == pn557) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: for pn557/pn81T, signal_handler not supported. Returning\n", |
| __func__); |
| return; |
| } |
| |
| uint16_t usEvent = 0; |
| if (signum == SIG_NFC && (android::nfcManager_isNfcActive() != false && |
| !(android::nfcManager_isNfcDisabling()) && |
| (android::nfcManager_getNfcState() != NFC_OFF))) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Signal is SIG_NFC\n", __func__); |
| if (nfcFL.eseFL._ESE_SVDD_SYNC || nfcFL.eseFL._ESE_JCOP_DWNLD_PROTECTION || |
| nfcFL.nfccFL._NFCC_SPI_FW_DOWNLOAD_SYNC || |
| nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE) { |
| usEvent = info->si_int; |
| gSPIEvtQueue.enqueue((uint8_t*)&usEvent, (uint16_t)SIGNAL_EVENT_SIZE); |
| SyncEventGuard guard(sSPISignalHandlerEvent); |
| sSPISignalHandlerEvent.notifyOne(); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: enablePassiveListen |
| ** |
| ** Description: Enable or disable Passive A/B listen |
| ** |
| ** Returns: True if ok. |
| ** |
| *******************************************************************************/ |
| uint16_t SecureElement::enablePassiveListen(uint8_t event) { |
| if (!nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION not available." |
| " Returning", |
| __func__); |
| return NFA_STATUS_FAILED; |
| } |
| |
| tNFA_STATUS status = NFA_STATUS_FAILED; |
| |
| mPassiveListenMutex.lock(); |
| |
| if (event == 0x00 && mPassiveListenEnabled == true) { |
| if (android::isDiscoveryStarted() == true) { |
| android::startRfDiscovery(false); |
| } |
| status = NFA_DisablePassiveListening(); |
| if (status == NFA_STATUS_OK) { |
| SyncEventGuard g(mPassiveListenEvt); |
| mPassiveListenEvt.wait(100); |
| } |
| resetRfFieldStatus(); |
| setDwpTranseiveState(false, NFCC_RF_FIELD_EVT); |
| mPassiveListenEnabled = false; |
| |
| if (android::isDiscoveryStarted() == false) { |
| android::startRfDiscovery(true); |
| } |
| } else if (event == 0x01 && mPassiveListenEnabled == false) { |
| if (android::isDiscoveryStarted() == true) { |
| android::startRfDiscovery(false); |
| } |
| status = NFA_EnableListening(); |
| if (status == NFA_STATUS_OK) { |
| SyncEventGuard g(mPassiveListenEvt); |
| mPassiveListenEvt.wait(100); |
| } |
| mPassiveListenTimer.set(mPassiveListenTimeout, |
| passiveListenDisablecallBack); |
| mPassiveListenEnabled = true; |
| if (android::isDiscoveryStarted() == false) { |
| android::startRfDiscovery(true); |
| } |
| } |
| mPassiveListenMutex.unlock(); |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(" enablePassiveListen exit"); |
| return 0x00; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: passiveListenEnableThread |
| ** |
| ** Description: thread to trigger passive Listen Enable |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| void* passiveListenEnableThread(void* arg) { |
| if (!nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION not available." |
| " Returning", |
| __func__); |
| return NULL; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf(" passiveListenEnableThread %d", *((uint8_t*)arg)); |
| if (*((uint8_t*)arg)) { |
| SecureElement::getInstance().enablePassiveListen(0x01); |
| } else { |
| SecureElement::getInstance().enablePassiveListen(0x00); |
| } |
| pthread_exit(NULL); |
| return NULL; |
| } |
| |
| uint16_t SecureElement::startThread(uint8_t thread_arg) { |
| passiveListenState = thread_arg; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| mPassiveListenCnt = 0x00; |
| if (pthread_create(&passiveListenEnable_thread, &attr, |
| passiveListenEnableThread, |
| (void*)&passiveListenState) != 0) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("Unable to create the thread"); |
| } |
| pthread_attr_destroy(&attr); |
| return 0x00; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: passiveListenDisablecallBack |
| ** |
| ** Description: Enable or disable Passive A/B listen |
| ** |
| ** Returns: None |
| ** |
| *******************************************************************************/ |
| static void passiveListenDisablecallBack(union sigval) { |
| if (!nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION not available." |
| " Returning", |
| __func__); |
| return; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf(" passiveListenDisablecallBack enter"); |
| |
| if (SecureElement::getInstance().isRfFieldOn() == true) { |
| if (SecureElement::getInstance().isActivatedInListenMode()) { |
| // do nothing , |
| return; |
| } else if ((SecureElement::getInstance().isActivatedInListenMode() == |
| false) && |
| (SecureElement::getInstance().mPassiveListenCnt < 0x02)) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf(" passiveListenEnableThread timer restart"); |
| SecureElement::getInstance().mPassiveListenTimer.set( |
| SecureElement::getInstance().mPassiveListenTimeout, |
| passiveListenDisablecallBack); |
| SecureElement::getInstance().mPassiveListenCnt++; |
| return; |
| } |
| } |
| SecureElement::getInstance().enablePassiveListen(0x00); |
| } |
| |
| #endif |
| |
| #if (NXP_EXTNS == TRUE) |
| /******************************************************************************* |
| ** |
| ** Function: setSPIState |
| ** |
| ** Description: Update current SPI state based on Signals |
| ** |
| ** Returns: None . |
| ** |
| *******************************************************************************/ |
| static void setSPIState(bool mState) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s: Enter setSPIState \n", __func__); |
| /*Check if the state is already dual mode*/ |
| bool inDualModeAlready = (dual_mode_current_state == SPI_DWPCL_BOTH_ACTIVE); |
| if (mState) { |
| dual_mode_current_state |= SPI_ON; |
| } else { |
| if (dual_mode_current_state & SPI_ON) { |
| dual_mode_current_state ^= SPI_ON; |
| if (inDualModeAlready) { |
| SyncEventGuard guard(mDualModeEvent); |
| mDualModeEvent.notifyOne(); |
| } |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s: Exit setSPIState = %d\n", __func__, dual_mode_current_state); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: SecElem_EeModeSet |
| ** |
| ** Description: Perform SE mode set ON/OFF based on mode type |
| ** |
| ** Returns: NFA_STATUS_OK/NFA_STATUS_FAILED. |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS SecureElement::SecElem_EeModeSet(uint16_t handle, uint8_t mode) { |
| tNFA_STATUS stat = NFA_STATUS_FAILED; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s:Enter mode = %d", __func__, mode); |
| |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._JCOP_WA_ENABLE && |
| ((mode == NFA_EE_MD_DEACTIVATE) && |
| (active_ese_reset_control & |
| (TRANS_WIRED_ONGOING | TRANS_CL_ONGOING)))) { |
| active_ese_reset_control |= RESET_BLOCKED; |
| SyncEventGuard guard(sSecElem.mResetEvent); |
| sSecElem.mResetEvent.wait(); |
| } |
| } |
| if ((dual_mode_current_state & SPI_ON) && (handle == EE_HANDLE_0xF3) && |
| (mode == NFA_EE_MD_DEACTIVATE)) |
| return NFA_STATUS_OK; |
| |
| if (nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| if ((handle == EE_HANDLE_0xF3) && (mode == NFA_EE_MD_ACTIVATE)) { |
| SyncEvent* pEeSetModeEvent; |
| if (NFA_GetNCIVersion() == NCI_VERSION_2_0) { |
| pEeSetModeEvent = &mEeSetModeEvent; |
| } else { |
| pEeSetModeEvent = &mModeSetNtf; |
| } |
| SyncEventGuard guard(*pEeSetModeEvent); |
| stat = NFA_EeModeSet(handle, mode); |
| if (stat == NFA_STATUS_OK && !android::nfcManager_isNfcDisabling() && |
| (android::nfcManager_getNfcState() != NFC_OFF)) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("Waiting for Mode Set Ntf"); |
| /*ModeSetNtf wait timeout is increased for the synchronization with |
| *dual mode involving with RF and triple mode*/ |
| if (pEeSetModeEvent->wait(DWP_LINK_ACTV_TIMEOUT) == false) { |
| LOG(ERROR) << StringPrintf("%s: timeout waiting for setModeNtf", |
| __func__); |
| stat = NFA_STATUS_FAILED; |
| } |
| } |
| } else { |
| SyncEventGuard guard(mEeSetModeEvent); |
| stat = NFA_EeModeSet(handle, mode); |
| if (stat == NFA_STATUS_OK && !android::nfcManager_isNfcDisabling() && |
| (android::nfcManager_getNfcState() != NFC_OFF)) { |
| /*EeSetModeEvent wait timeout is increased for the synchronization with |
| * dual mode involving with RF and triple mode*/ |
| if (mEeSetModeEvent.wait(DWP_LINK_ACTV_TIMEOUT) == false) { |
| LOG(ERROR) << StringPrintf("%s: timeout waiting for setModeEvt", |
| __func__); |
| stat = NFA_STATUS_FAILED; |
| } |
| } else { |
| // do nothing |
| } |
| } |
| } else { |
| SyncEventGuard guard(mEeSetModeEvent); |
| stat = NFA_EeModeSet(handle, mode); |
| if (stat == NFA_STATUS_OK && !android::nfcManager_isNfcDisabling() && |
| (android::nfcManager_getNfcState() != NFC_OFF)) { |
| mEeSetModeEvent.wait(); |
| } else { |
| // do nothing |
| } |
| } |
| if (nfcFL.nfcNxpEse) { |
| if (nfcFL.eseFL._JCOP_WA_ENABLE && |
| (active_ese_reset_control & RESET_BLOCKED)) { |
| SyncEventGuard guard(sSecElem.mResetOngoingEvent); |
| sSecElem.mResetOngoingEvent.notifyOne(); |
| } |
| } |
| return stat; |
| } |
| /********************************************************************************** |
| ** |
| ** Function: getEeStatus |
| ** |
| ** Description: get the status of EE |
| ** |
| ** Returns: EE status |
| ** |
| **********************************************************************************/ |
| uint16_t SecureElement::getEeStatus(uint16_t eehandle) { |
| int i; |
| uint16_t ee_status = NFA_EE_STATUS_REMOVED; |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s num_nfcee_present = %d", __func__, mNfceeData_t.mNfceePresent); |
| |
| for (i = 0; i < mNfceeData_t.mNfceePresent; i++) { |
| if (mNfceeData_t.mNfceeHandle[i] == eehandle) { |
| ee_status = mNfceeData_t.mNfceeStatus[i]; |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s EE is detected 0x%02x status = 0x%02x", |
| __func__, eehandle, ee_status); |
| break; |
| } |
| } |
| return ee_status; |
| } |
| #if (NXP_EXTNS == TRUE) |
| /********************************************************************************** |
| ** |
| ** Function: getUiccStatus |
| ** |
| ** Description: get the status of EE |
| ** |
| ** Returns: UICC Status |
| ** |
| **********************************************************************************/ |
| uicc_stat_t SecureElement::getUiccStatus(uint8_t selected_uicc) { |
| uint16_t ee_stat = NFA_EE_STATUS_REMOVED; |
| |
| if (nfcFL.nfccFL._NFC_NXP_STAT_DUAL_UICC_WO_EXT_SWITCH) { |
| if (selected_uicc == 0x01) |
| ee_stat = getEeStatus(EE_HANDLE_0xF4); |
| else if (selected_uicc == 0x02) |
| ee_stat = getEeStatus(EE_HANDLE_0xF8); |
| } |
| if (nfcFL.nfccFL._NFC_NXP_STAT_DUAL_UICC_EXT_SWITCH) |
| ee_stat = getEeStatus(EE_HANDLE_0xF4); |
| |
| uicc_stat_t uicc_stat = UICC_STATUS_UNKNOWN; |
| |
| if (selected_uicc == 0x01) { |
| switch (ee_stat) { |
| case 0x00: |
| uicc_stat = UICC_01_SELECTED_ENABLED; |
| break; |
| case 0x01: |
| uicc_stat = UICC_01_SELECTED_DISABLED; |
| break; |
| case 0x02: |
| uicc_stat = UICC_01_REMOVED; |
| break; |
| } |
| } else if (selected_uicc == 0x02) { |
| switch (ee_stat) { |
| case 0x00: |
| uicc_stat = UICC_02_SELECTED_ENABLED; |
| break; |
| case 0x01: |
| uicc_stat = UICC_02_SELECTED_DISABLED; |
| break; |
| case 0x02: |
| uicc_stat = UICC_02_REMOVED; |
| break; |
| } |
| } |
| return uicc_stat; |
| } |
| |
| /********************************************************************************** |
| ** |
| ** Function: updateNfceeDiscoverInfo |
| ** |
| ** Description: get the status of EE |
| ** |
| ** Returns: Number of new NFCEEs discovered |
| ** |
| **********************************************************************************/ |
| uint8_t SecureElement::updateNfceeDiscoverInfo() { |
| uint8_t numEe = nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED; |
| tNFA_EE_INFO mEeInfo[numEe]; |
| tNFA_STATUS nfaStat; |
| |
| if ((nfaStat = NFA_AllEeGetInfo(&numEe, mEeInfo)) != NFA_STATUS_OK) { |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( |
| "%s failed to get info, error = 0x%X ", __func__, nfaStat); |
| mActualNumEe = 0; |
| } |
| for (int xx = 0; xx < numEe; xx++) { |
| if (mEeInfo[xx].ee_handle == EE_HANDLE_0xF3) { |
| if (!(nfcee_swp_discovery_status & SWP2_ESE)) { |
| nfcee_swp_discovery_status |= SWP2_ESE; |
| gSeDiscoverycount++; |
| } |
| } else if (mEeInfo[xx].ee_handle == EE_HANDLE_0xF4) { |
| if (!(nfcee_swp_discovery_status & SWP1_UICC1)) { |
| nfcee_swp_discovery_status |= SWP1_UICC1; |
| gSeDiscoverycount++; |
| } |
| } else if (mEeInfo[xx].ee_handle == EE_HANDLE_0xF8) { |
| if (!(nfcee_swp_discovery_status & SWP1A_UICC2)) { |
| nfcee_swp_discovery_status |= SWP1A_UICC2; |
| gSeDiscoverycount++; |
| } |
| } else if (mEeInfo[xx].ee_handle == EE_HANDLE_HCI) { |
| if (!(nfcee_swp_discovery_status & HCI_ACESS)) { |
| nfcee_swp_discovery_status |= HCI_ACESS; |
| gSeDiscoverycount++; |
| } |
| } else if (mEeInfo[xx].ee_handle == EE_HANDLE_NDEFEE) { |
| if (!(nfcee_swp_discovery_status & T4T_NDEFEE)) { |
| nfcee_swp_discovery_status |= T4T_NDEFEE; |
| gSeDiscoverycount++; |
| } |
| } else { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s INVALID HANDLE ", __func__); |
| } |
| } |
| return gSeDiscoverycount; |
| } |
| |
| #endif |
| #if (NXP_EXTNS == TRUE) |
| /******************************************************************************* |
| ** |
| ** Function: SecElem_sendEvt_Abort |
| ** |
| ** Description: Perform interface level reset by sending EVT_ABORT event |
| ** |
| ** Returns: NFA_STATUS_OK/NFA_STATUS_FAILED. |
| ** |
| *******************************************************************************/ |
| |
| tNFA_STATUS SecureElement::SecElem_sendEvt_Abort() { |
| if (!nfcFL.nfcNxpEse) { |
| LOG(ERROR) << StringPrintf("%s nfcNxpEse not available. Returning", |
| __func__); |
| return NFA_STATUS_FAILED; |
| } |
| static const char fn[] = "SecureElement::SecElem_sendEvt_Abort"; |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| int32_t timeoutMillisec = 10000; |
| uint8_t atr_len = 0x10; |
| uint8_t recvBuffer[MAX_RESPONSE_SIZE]; |
| mAbortEventWaitOk = false; |
| |
| if (nfcFL.nfccFL._NFCEE_REMOVED_NTF_RECOVERY && |
| (RoutingManager::getInstance().is_ee_recovery_ongoing())) { |
| SyncEventGuard guard(mEEdatapacketEvent); |
| if (mEEdatapacketEvent.wait(android::gMaxEERecoveryTimeout) == false) { |
| return nfaStat; |
| } |
| } |
| |
| SyncEventGuard guard(mAbortEvent); |
| nfaStat = NFA_HciSendEvent(mNfaHciHandle, mNewPipeId, EVT_ABORT, 0, NULL, |
| atr_len, recvBuffer, timeoutMillisec); |
| if (nfaStat == NFA_STATUS_OK) { |
| mAbortEvent.wait(); |
| } |
| if (mAbortEventWaitOk == false) { |
| LOG(ERROR) << StringPrintf("%s (EVT_ABORT)Wait reposne timeout", fn); |
| return NFA_STATUS_FAILED; |
| } |
| return nfaStat; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: setDwpTranseiveState |
| ** |
| ** Description: Update current DWP CL state based on CL activation status |
| ** |
| ** Returns: None . |
| ** |
| *******************************************************************************/ |
| |
| void SecureElement::setDwpTranseiveState(bool block, tNFCC_EVTS_NTF action) { |
| if (!nfcFL.nfcNxpEse) { |
| LOG(ERROR) << StringPrintf("%s nfcNxpEse not available. Returning", |
| __func__); |
| return; |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("%s block = %d action = %d ", __func__, block, action); |
| |
| switch (action) { |
| case NFCC_RF_FIELD_EVT: |
| if (!block) { |
| SyncEventGuard guard(mRfFieldOffEvent); |
| mRfFieldOffEvent.notifyOne(); |
| } |
| FALLTHROUGH; |
| case NFCC_DEACTIVATED_NTF: |
| case NFCC_CE_DATA_EVT: |
| if (block) { |
| mIsWiredModeBlocked = true; |
| if (action == NFCC_RF_FIELD_EVT) { |
| if (nfcFL.nfcNxpEse && |
| nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION && |
| (meseUiccConcurrentAccess == false)) { |
| if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME != |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| SecureElement::getInstance().mRfFieldEventTimer.set( |
| SecureElement::getInstance().mRfFieldEventTimeout, |
| rfFeildEventTimeoutCallback); |
| } |
| } else if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME == |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| SecureElement::getInstance().mRfFieldEventTimer.set( |
| SecureElement::getInstance().mRfFieldEventTimeout, |
| rfFeildEventTimeoutCallback); |
| } |
| } |
| } else { |
| mIsWiredModeBlocked = false; |
| |
| if (nfcFL.nfcNxpEse && |
| nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION && |
| (meseUiccConcurrentAccess == false)) { |
| if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME != |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| SecureElement::getInstance().mRfFieldEventTimer.kill(); |
| } |
| } else if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME == |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| SecureElement::getInstance().mRfFieldEventTimer.kill(); |
| } |
| if (hold_wired_mode) { |
| SyncEventGuard guard(mWiredModeHoldEvent); |
| mWiredModeHoldEvent.notifyOne(); |
| hold_wired_mode = false; |
| } |
| } |
| break; |
| case NFCC_ACTIVATED_NTF: |
| case NFCC_ACTION_NTF: |
| case NFCC_RF_TIMEOUT_EVT: |
| if (nfcFL.nfcNxpEse && |
| nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION && |
| (meseUiccConcurrentAccess == false)) { |
| if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME != |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| SecureElement::getInstance().mRfFieldEventTimer.kill(); |
| } |
| } else if (nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME == |
| nfcFL.eseFL._ESE_WIRED_MODE_RESUME) { |
| SecureElement::getInstance().mRfFieldEventTimer.kill(); |
| } |
| if (!block) { |
| mIsWiredModeBlocked = false; |
| if (hold_wired_mode) { |
| SyncEventGuard guard(mWiredModeHoldEvent); |
| mWiredModeHoldEvent.notifyOne(); |
| hold_wired_mode = false; |
| } |
| } else { |
| mIsWiredModeBlocked = true; |
| } |
| } |
| DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s Exit", __func__); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function rfFeildEventTimeoutCallback |
| ** |
| ** Description Call back funtion to resume wired mode after RF field event |
| *timeout |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| static void rfFeildEventTimeoutCallback(union sigval) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("rfFeildEventTimeoutCallback Enter"); |
| SecureElement::getInstance().setDwpTranseiveState(false, NFCC_RF_FIELD_EVT); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function getLastRfFiledToggleTime |
| ** |
| ** Description Provides the last RF filed toggile timer |
| ** |
| ** Returns timespec |
| ** |
| *******************************************************************************/ |
| struct timespec SecureElement::getLastRfFiledToggleTime(void) { |
| return mLastRfFieldToggle; |
| } |
| #endif |
| |
| /******************************************************************************* |
| ** |
| ** Function setNfccPwrConfig |
| ** |
| ** Description sends the link cntrl command to eSE with the value passed |
| ** |
| ** Returns status |
| ** |
| *******************************************************************************/ |
| tNFA_STATUS SecureElement::setNfccPwrConfig(uint8_t value) { |
| if (!nfcFL.eseFL._WIRED_MODE_STANDBY) { |
| DLOG_IF(INFO, nfc_debug_enabled) |
| << StringPrintf("WIRED_MODE_STANDBY not enabled. Returning"); |
| return NFA_STATUS_FAILED; |
| } |
| |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| static uint8_t cur_value = 0xFF; |
| |
| /*if(cur_value == value) |
| { |
| mPwrCmdstatus = NFA_STATUS_OK; |
| } |
| else*/ |
| if (!android::nfcManager_isNfcActive() || |
| android::nfcManager_isNfcDisabling() || |
| (android::nfcManager_getNfcState() == NFC_OFF)) { |
| LOG(ERROR) << StringPrintf("%s: NFC is no longer active.", __func__); |
| return NFA_STATUS_OK; |
| } else { |
| if ((dual_mode_current_state & SPI_ON) && (value == NFCC_DECIDES)) { |
| DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf( |
| "%s: SPI session is open. Host controls power-link configuration to eSE", __func__); |
| return NFA_STATUS_FAILED; |
| } |
| cur_value = value; |
| SyncEventGuard guard(mPwrLinkCtrlEvent); |
| tNFC_INTF_REQ_SRC reqSrc = NFC_INTF_REQ_SRC_DWP; |
| if ((value == 0x03) && dual_mode_current_state & SPI_ON) { |
| reqSrc = NFC_INTF_REQ_SRC_SPI; |
| } |
| nfaStat = NFA_SendPowerLinkCommand((uint8_t)EE_HANDLE_0xF3, value, reqSrc); |
| if (nfaStat == NFA_STATUS_OK && !android::nfcManager_isNfcDisabling()) |
| if (mPwrLinkCtrlEvent.wait(DWP_LINK_ACTV_TIMEOUT) == false) { |
| DLOG_IF(ERROR, nfc_debug_enabled) |
| << StringPrintf("%s: DWP_LINK_ACTV_TIMEOUT..", __func__); |
| mPwrCmdstatus = NFA_STATUS_FAILED; |
| } |
| } |
| return mPwrCmdstatus; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function getGateAndPipeInfo |
| ** |
| ** Description Retrieves already configured gate and pipe ID |
| ** |
| ** Returns Gate and pipe id list |
| ** |
| *******************************************************************************/ |
| tNFA_HCI_GET_GATE_PIPE_LIST SecureElement::getGateAndPipeInfo() { |
| tNFA_STATUS nfaStat = NFA_STATUS_FAILED; |
| SyncEventGuard guard(SecureElement::getInstance().mPipeListEvent); |
| SecureElement::getInstance().mNfaHciHandle = NFA_HANDLE_GROUP_HCI; |
| nfaStat = |
| NFA_HciGetGateAndPipeList(SecureElement::getInstance().mNfaHciHandle); |
| if (nfaStat == NFA_STATUS_OK) { |
| SecureElement::getInstance().mPipeListEvent.wait(); |
| } |
| return mHciCfg; |
| } |
| #endif |