blob: 1328dbaef8bc334cf31e9d13eb9f40f2ca161e68 [file] [log] [blame]
/*
* Copyright (C) 2013 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.
*/
/*
* Manage the listen-mode routing table.
*/
/******************************************************************************
*
* The original Work has been changed by NXP.
*
* 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.
*
* Copyright 2018-2019 NXP
*
******************************************************************************/
#include <android-base/stringprintf.h>
#include <base/logging.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
#include "JavaClassConstants.h"
#include "RoutingManager.h"
#include "nfa_ce_api.h"
#include "nfa_ee_api.h"
#include "nfc_config.h"
#if (NXP_EXTNS == TRUE)
#include "MposManager.h"
#include "NativeJniExtns.h"
#include "SecureElement.h"
#endif
using android::base::StringPrintf;
extern bool gActivated;
extern SyncEvent gDeactivatedEvent;
extern bool nfc_debug_enabled;
const JNINativeMethod RoutingManager::sMethods[] = {
{"doGetDefaultRouteDestination", "()I",
(void*)RoutingManager::
com_android_nfc_cardemulation_doGetDefaultRouteDestination},
{"doGetDefaultOffHostRouteDestination", "()I",
(void*)RoutingManager::
com_android_nfc_cardemulation_doGetDefaultOffHostRouteDestination},
{"doGetOffHostUiccDestination", "()[B",
(void*)RoutingManager::
com_android_nfc_cardemulation_doGetOffHostUiccDestination},
{"doGetOffHostEseDestination", "()[B",
(void*)RoutingManager::
com_android_nfc_cardemulation_doGetOffHostEseDestination},
{"doGetAidMatchingMode", "()I",
(void*)
RoutingManager::com_android_nfc_cardemulation_doGetAidMatchingMode},
{"doGetDefaultIsoDepRouteDestination", "()I",
(void*)RoutingManager::
com_android_nfc_cardemulation_doGetDefaultIsoDepRouteDestination}};
static const int MAX_NUM_EE = 5;
// SCBR from host works only when App is in foreground
static const uint8_t SYS_CODE_PWR_STATE_HOST = 0x01;
#if (NXP_EXTNS != TRUE)
static const uint16_t DEFAULT_SYS_CODE = 0xFEFE;
#else
static RouteInfo_t gRouteInfo;
extern jint nfcManager_getUiccRoute(jint uicc_slot);
extern jint nfcManager_getUiccId(jint uicc_slot);
extern uint16_t sCurrentSelectedUICCSlot;
extern bool isDynamicUiccEnabled;
#endif
static const uint8_t AID_ROUTE_QUAL_PREFIX = 0x10;
RoutingManager::RoutingManager()
: mNativeData(NULL) {
static const char fn[] = "RoutingManager::RoutingManager()";
mDefaultOffHostRoute =
NfcConfig::getUnsigned(NAME_DEFAULT_OFFHOST_ROUTE, 0x00);
if (NfcConfig::hasKey(NAME_OFFHOST_ROUTE_UICC)) {
mOffHostRouteUicc = NfcConfig::getBytes(NAME_OFFHOST_ROUTE_UICC);
}
if (NfcConfig::hasKey(NAME_OFFHOST_ROUTE_ESE)) {
mOffHostRouteEse = NfcConfig::getBytes(NAME_OFFHOST_ROUTE_ESE);
}
mDefaultFelicaRoute = NfcConfig::getUnsigned(NAME_DEFAULT_NFCF_ROUTE, 0x00);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: Active SE for Nfc-F is 0x%02X", fn, mDefaultFelicaRoute);
mDefaultEe = NfcConfig::getUnsigned(NAME_DEFAULT_ROUTE, 0x00);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: default route is 0x%02X", fn, mDefaultEe);
mAidMatchingMode =
NfcConfig::getUnsigned(NAME_AID_MATCHING_MODE, AID_MATCHING_EXACT_ONLY);
mDefaultSysCodeRoute =
NfcConfig::getUnsigned(NAME_DEFAULT_SYS_CODE_ROUTE, 0xC0);
mDefaultSysCodePowerstate =
NfcConfig::getUnsigned(NAME_DEFAULT_SYS_CODE_PWR_STATE, 0x19);
#if (NXP_EXTNS != TRUE)
mDefaultSysCode = DEFAULT_SYS_CODE;
#else
mDefaultGsmaPowerState = 0;
sRoutingBuffLen = 0;
sRoutingBuff = NULL;
mDefaultSysCode = 0x00;
mHostListnTechMask = 0;
mUiccListnTechMask = 0;
mFwdFuntnEnable = 0;
mDefaultIso7816SeID = 0;
mDefaultIso7816Powerstate = 0;
mDefaultTechASeID = 0;
mCeRouteStrictDisable = 0;
mTechSupportedByEse = 0;
mTechSupportedByUicc1 = 0;
mTechSupportedByUicc2 = 0;
mDefaultTechFPowerstate = 0;
memset (mProtoTableEntries, 0, sizeof(mProtoTableEntries));
memset (mTechTableEntries, 0, sizeof(mTechTableEntries));
memset(mLmrtEntries, 0, sizeof(LmrtEntry_t));
#endif
if (NfcConfig::hasKey(NAME_DEFAULT_SYS_CODE)) {
std::vector<uint8_t> pSysCode = NfcConfig::getBytes(NAME_DEFAULT_SYS_CODE);
if (pSysCode.size() == 0x02) {
mDefaultSysCode = ((pSysCode[0] << 8) | ((int)pSysCode[1] << 0));
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: DEFAULT_SYS_CODE: 0x%02X", __func__, mDefaultSysCode);
}
}
mSecureNfcEnabled = false;
memset(&mCbEventData, 0, sizeof(mCbEventData));
memset(&mEeInfo, 0, sizeof(mEeInfo));
mReceivedEeInfo = false;
mSeTechMask = 0x00;
mIsScbrSupported = false;
mNfcFOnDhHandle = NFA_HANDLE_INVALID;
mDefaultIsoDepRoute = NfcConfig::getUnsigned(NAME_DEFAULT_ISODEP_ROUTE, 0x0);
mOffHostAidRoutingPowerState =
NfcConfig::getUnsigned(NAME_OFFHOST_AID_ROUTE_PWR_STATE, 0x01);
}
RoutingManager::~RoutingManager() {}
bool RoutingManager::initialize(nfc_jni_native_data* native) {
static const char fn[] = "RoutingManager::initialize()";
mNativeData = native;
tNFA_STATUS nfaStat;
{
SyncEventGuard guard(mEeRegisterEvent);
DLOG_IF(INFO, nfc_debug_enabled) << fn << ": try ee register";
tNFA_STATUS nfaStat = NFA_EeRegister(nfaEeCallback);
if (nfaStat != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: fail ee register; error=0x%X", fn,
nfaStat);
return false;
}
mEeRegisterEvent.wait();
}
#if (NXP_EXTNS == TRUE)
memset(&gRouteInfo, 0x00, sizeof(RouteInfo_t));
mHostListnTechMask = NfcConfig::getUnsigned(NAME_HOST_LISTEN_TECH_MASK, 0x03);
LOG(INFO) << StringPrintf("%s: mHostListnTechMask=0x%X", fn,mHostListnTechMask);
mFwdFuntnEnable = NfcConfig::getUnsigned(NAME_FORWARD_FUNCTIONALITY_ENABLE, 0x00);
LOG(INFO) << StringPrintf("%s: mFwdFuntnEnable=0x%X", fn,mFwdFuntnEnable);
mDefaultTechFPowerstate = NfcConfig::getUnsigned(NAME_DEFAULT_FELICA_CLT_PWR_STATE, 0x3F);
mDefaultEe = NfcConfig::getUnsigned(NAME_NXP_DEFAULT_SE, 0x01);
mUiccListnTechMask = NfcConfig::getUnsigned(NAME_UICC_LISTEN_TECH_MASK, 0x07);
mDefaultIso7816SeID = NfcConfig::getUnsigned(NAME_DEFAULT_AID_ROUTE, NFA_HANDLE_INVALID);
mDefaultIso7816Powerstate = NfcConfig::getUnsigned(NAME_DEFAULT_AID_PWR_STATE, 0xFF);
mDefaultGsmaPowerState = NfcConfig::getUnsigned(NAME_DEFUALT_GSMA_PWR_STATE, 0x00);
mDefaultFelicaRoute = NfcConfig::getUnsigned(NAME_DEFAULT_FELICA_CLT_ROUTE, 0x00);
mDefaultOffHostRoute = NfcConfig::getUnsigned(NAME_DEFAULT_OFFHOST_ROUTE, 0x00);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: mDefaultGsmaPowerState %02x)", fn, mDefaultGsmaPowerState);
LOG(INFO) << StringPrintf("%s: >>>> mDefaultIso7816SeID=0x%X", fn, mDefaultIso7816SeID);
LOG(INFO) << StringPrintf("%s: >>>> mDefaultIso7816Powerstate=0x%X", fn, mDefaultIso7816Powerstate);
LOG(INFO) << StringPrintf("%s: >>>> mDefaultFelicaRoute=0x%X", fn, mDefaultFelicaRoute);
LOG(INFO) << StringPrintf("%s: >>>> mDefaultEe=0x%X", fn, mDefaultEe);
LOG(INFO) << StringPrintf("%s: >>>> mDefaultOffHostRoute=0x%X", fn, mDefaultOffHostRoute);
#endif
if ((mDefaultOffHostRoute != 0) || (mDefaultFelicaRoute != 0)) {
// Wait for EE info if needed
SyncEventGuard guard(mEeInfoEvent);
if (!mReceivedEeInfo) {
LOG(INFO) << fn << "Waiting for EE info";
mEeInfoEvent.wait();
}
}
#if (NXP_EXTNS != TRUE)
mSeTechMask = updateEeTechRouteSetting();
#endif
#if (NXP_EXTNS == TRUE)
if (mHostListnTechMask) {
#endif
// Tell the host-routing to only listen on Nfc-A
nfaStat = NFA_CeSetIsoDepListenTech(NFA_TECHNOLOGY_MASK_A);
if (nfaStat != NFA_STATUS_OK)
LOG(ERROR) << StringPrintf("Failed to configure CE IsoDep technologies");
// Register a wild-card for AIDs routed to the host
nfaStat = NFA_CeRegisterAidOnDH(NULL, 0, stackCallback);
if (nfaStat != NFA_STATUS_OK)
LOG(ERROR) << fn << "Failed to register wildcard AID for DH";
#if (NXP_EXTNS == TRUE)
}
#endif
updateDefaultRoute();
#if (NXP_EXTNS != TRUE)
updateDefaultProtocolRoute();
#endif
return true;
}
RoutingManager& RoutingManager::getInstance() {
static RoutingManager manager;
return manager;
}
void RoutingManager::enableRoutingToHost() {
static const char fn[] = "RoutingManager::enableRoutingToHost()";
tNFA_STATUS nfaStat;
SyncEventGuard guard(mRoutingEvent);
// Default routing for T3T protocol
if (!mIsScbrSupported && mDefaultEe == NFC_DH_ID) {
nfaStat = NFA_EeSetDefaultProtoRouting(NFC_DH_ID, NFA_PROTOCOL_MASK_T3T, 0,
0, 0, 0, 0);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default proto routing for T3T";
}
// Default routing for IsoDep protocol
tNFA_PROTOCOL_MASK protoMask = NFA_PROTOCOL_MASK_ISO_DEP;
if (mDefaultIsoDepRoute == NFC_DH_ID) {
nfaStat = NFA_EeSetDefaultProtoRouting(
NFC_DH_ID, protoMask, 0, 0, mSecureNfcEnabled ? 0 : protoMask, 0, 0);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default proto routing for IsoDep";
}
// Route Nfc-A to host if we don't have a SE
tNFA_TECHNOLOGY_MASK techMask = NFA_TECHNOLOGY_MASK_A;
if ((mSeTechMask & NFA_TECHNOLOGY_MASK_A) == 0) {
nfaStat = NFA_EeSetDefaultTechRouting(
NFC_DH_ID, techMask, 0, 0, mSecureNfcEnabled ? 0 : techMask,
mSecureNfcEnabled ? 0 : techMask, mSecureNfcEnabled ? 0 : techMask);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default tech routing for Nfc-A";
}
// Route Nfc-F to host if we don't have a SE
techMask = NFA_TECHNOLOGY_MASK_F;
if ((mSeTechMask & NFA_TECHNOLOGY_MASK_F) == 0) {
nfaStat = NFA_EeSetDefaultTechRouting(
NFC_DH_ID, techMask, 0, 0, mSecureNfcEnabled ? 0 : techMask,
mSecureNfcEnabled ? 0 : techMask, mSecureNfcEnabled ? 0 : techMask);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default tech routing for Nfc-F";
}
}
void RoutingManager::disableRoutingToHost() {
static const char fn[] = "RoutingManager::disableRoutingToHost()";
tNFA_STATUS nfaStat;
SyncEventGuard guard(mRoutingEvent);
// Default routing for IsoDep protocol
if (mDefaultIsoDepRoute == NFC_DH_ID) {
nfaStat =
NFA_EeClearDefaultProtoRouting(NFC_DH_ID, NFA_PROTOCOL_MASK_ISO_DEP);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default proto routing for IsoDep";
}
// Default routing for Nfc-A technology if we don't have a SE
if ((mSeTechMask & NFA_TECHNOLOGY_MASK_A) == 0) {
nfaStat = NFA_EeClearDefaultTechRouting(NFC_DH_ID, NFA_TECHNOLOGY_MASK_A);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default tech routing for Nfc-A";
}
// Default routing for Nfc-F technology if we don't have a SE
if ((mSeTechMask & NFA_TECHNOLOGY_MASK_F) == 0) {
nfaStat = NFA_EeClearDefaultTechRouting(NFC_DH_ID, NFA_TECHNOLOGY_MASK_F);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default tech routing for Nfc-F";
}
// Default routing for T3T protocol
if (!mIsScbrSupported && mDefaultEe == NFC_DH_ID) {
nfaStat = NFA_EeClearDefaultProtoRouting(NFC_DH_ID, NFA_PROTOCOL_MASK_T3T);
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default proto routing for T3T";
}
}
#if(NXP_EXTNS == TRUE)
bool RoutingManager::addAidRouting(const uint8_t* aid, uint8_t aidLen,
int route, int aidInfo, int power) {
#else
bool RoutingManager::addAidRouting(const uint8_t* aid, uint8_t aidLen,
int route, int aidInfo) {
#endif
static const char fn[] = "RoutingManager::addAidRouting";
uint8_t powerState = 0x01;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn);
#if(NXP_EXTNS == TRUE)
int seId = SecureElement::getInstance().getEseHandleFromGenericId(route);
if (seId == NFA_HANDLE_INVALID)
{
return false;
}
SyncEventGuard guard(mAidAddRemoveEvent);
if (!mSecureNfcEnabled) {
/*Map PWR state as per NCI2.0 if required*/
bool stat = checkAndUpdatePowerState(power);
if (route == SecureElement::DH_ID) {
power &= ~(PWR_SWTCH_OFF_MASK | PWR_BATT_OFF_MASK);
if (!stat) power &= HOST_PWR_STATE;
}
powerState = power;
}
tNFA_STATUS nfaStat =
NFA_EeAddAidRouting(seId, aidLen, (uint8_t*)aid, powerState, aidInfo);
#else
if (!mSecureNfcEnabled) {
powerState = (route != 0x00) ? mOffHostAidRoutingPowerState : 0x11;
}
tNFA_STATUS nfaStat =
NFA_EeAddAidRouting(route, aidLen, (uint8_t*)aid, powerState, aidInfo);
#endif
if (nfaStat == NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled) << fn << ": routed AID";
#if(NXP_EXTNS == TRUE)
mAidAddRemoveEvent.wait();
#endif
return true;
} else {
LOG(ERROR) << fn << ": failed to route AID";
return false;
}
}
bool RoutingManager::removeAidRouting(const uint8_t* aid, uint8_t aidLen) {
static const char fn[] = "RoutingManager::removeAidRouting";
DLOG_IF(INFO, nfc_debug_enabled) << fn << ": enter";
#if(NXP_EXTNS == TRUE)
SyncEventGuard guard(mAidAddRemoveEvent);
#endif
tNFA_STATUS nfaStat = NFA_EeRemoveAidRouting(aidLen, (uint8_t*)aid);
if (nfaStat == NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled) << fn << ": removed AID";
#if(NXP_EXTNS == TRUE)
mAidAddRemoveEvent.wait();
#endif
return true;
} else {
LOG(ERROR) << fn << ": failed to remove AID";
return false;
}
}
bool RoutingManager::commitRouting() {
static const char fn[] = "RoutingManager::commitRouting";
tNFA_STATUS nfaStat = 0;
DLOG_IF(INFO, nfc_debug_enabled) << fn;
{
SyncEventGuard guard(mEeUpdateEvent);
nfaStat = NFA_EeUpdateNow();
if (nfaStat == NFA_STATUS_OK) {
mEeUpdateEvent.wait(); // wait for NFA_EE_UPDATED_EVT
}
}
return (nfaStat == NFA_STATUS_OK);
}
void RoutingManager::onNfccShutdown() {
static const char fn[] = "RoutingManager:onNfccShutdown";
if (mDefaultOffHostRoute == 0x00) return;
tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
uint8_t actualNumEe = MAX_NUM_EE;
tNFA_EE_INFO eeInfo[MAX_NUM_EE];
memset(&eeInfo, 0, sizeof(eeInfo));
if ((nfaStat = NFA_EeGetInfo(&actualNumEe, eeInfo)) != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: fail get info; error=0x%X", fn, nfaStat);
return;
}
if (actualNumEe != 0) {
for (uint8_t xx = 0; xx < actualNumEe; xx++) {
if ((eeInfo[xx].num_interface != 0) &&
(eeInfo[xx].ee_interface[0] != NCI_NFCEE_INTERFACE_HCI_ACCESS) &&
(eeInfo[xx].ee_status == NFA_EE_STATUS_ACTIVE)) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: Handle: 0x%04x Change Status Active to Inactive", fn,
eeInfo[xx].ee_handle);
SyncEventGuard guard(mEeSetModeEvent);
if ((nfaStat = NFA_EeModeSet(eeInfo[xx].ee_handle,
NFA_EE_MD_DEACTIVATE)) == NFA_STATUS_OK) {
mEeSetModeEvent.wait(); // wait for NFA_EE_MODE_SET_EVT
} else {
LOG(ERROR) << fn << "Failed to set EE inactive";
}
}
}
} else {
DLOG_IF(INFO, nfc_debug_enabled) << fn << ": No active EEs found";
}
}
void RoutingManager::notifyActivated(uint8_t technology) {
JNIEnv* e = NULL;
ScopedAttach attach(mNativeData->vm, &e);
if (e == NULL) {
LOG(ERROR) << "jni env is null";
return;
}
e->CallVoidMethod(mNativeData->manager,
android::gCachedNfcManagerNotifyHostEmuActivated,
(int)technology);
if (e->ExceptionCheck()) {
e->ExceptionClear();
LOG(ERROR) << "fail notify";
}
}
void RoutingManager::notifyDeactivated(uint8_t technology) {
#if (NXP_EXTNS == TRUE)
SecureElement::getInstance().notifyListenModeState (false);
#endif
mRxDataBuffer.clear();
JNIEnv* e = NULL;
ScopedAttach attach(mNativeData->vm, &e);
if (e == NULL) {
LOG(ERROR) << "jni env is null";
return;
}
e->CallVoidMethod(mNativeData->manager,
android::gCachedNfcManagerNotifyHostEmuDeactivated,
(int)technology);
if (e->ExceptionCheck()) {
e->ExceptionClear();
LOG(ERROR) << StringPrintf("fail notify");
}
}
void RoutingManager::handleData(uint8_t technology, const uint8_t* data,
uint32_t dataLen, tNFA_STATUS status) {
if (status == NFC_STATUS_CONTINUE) {
if (dataLen > 0) {
mRxDataBuffer.insert(mRxDataBuffer.end(), &data[0],
&data[dataLen]); // append data; more to come
}
return; // expect another NFA_CE_DATA_EVT to come
} else if (status == NFA_STATUS_OK) {
if (dataLen > 0) {
mRxDataBuffer.insert(mRxDataBuffer.end(), &data[0],
&data[dataLen]); // append data
}
// entire data packet has been received; no more NFA_CE_DATA_EVT
} else if (status == NFA_STATUS_FAILED) {
LOG(ERROR) << "RoutingManager::handleData: read data fail";
goto TheEnd;
}
{
JNIEnv* e = NULL;
ScopedAttach attach(mNativeData->vm, &e);
if (e == NULL) {
LOG(ERROR) << "jni env is null";
goto TheEnd;
}
ScopedLocalRef<jobject> dataJavaArray(
e, e->NewByteArray(mRxDataBuffer.size()));
if (dataJavaArray.get() == NULL) {
LOG(ERROR) << "fail allocate array";
goto TheEnd;
}
e->SetByteArrayRegion((jbyteArray)dataJavaArray.get(), 0,
mRxDataBuffer.size(), (jbyte*)(&mRxDataBuffer[0]));
if (e->ExceptionCheck()) {
e->ExceptionClear();
LOG(ERROR) << "fail fill array";
goto TheEnd;
}
e->CallVoidMethod(mNativeData->manager,
android::gCachedNfcManagerNotifyHostEmuData,
(int)technology, dataJavaArray.get());
if (e->ExceptionCheck()) {
e->ExceptionClear();
LOG(ERROR) << "fail notify";
}
}
TheEnd:
mRxDataBuffer.clear();
}
void RoutingManager::stackCallback(uint8_t event,
tNFA_CONN_EVT_DATA* eventData) {
static const char fn[] = "RoutingManager::stackCallback";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: event=0x%X", fn, event);
RoutingManager& routingManager = RoutingManager::getInstance();
switch (event) {
case NFA_CE_REGISTERED_EVT: {
tNFA_CE_REGISTERED& ce_registered = eventData->ce_registered;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_CE_REGISTERED_EVT; status=0x%X; h=0x%X", fn,
ce_registered.status, ce_registered.handle);
} break;
case NFA_CE_DEREGISTERED_EVT: {
tNFA_CE_DEREGISTERED& ce_deregistered = eventData->ce_deregistered;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_CE_DEREGISTERED_EVT; h=0x%X", fn, ce_deregistered.handle);
} break;
case NFA_CE_ACTIVATED_EVT: {
routingManager.notifyActivated(NFA_TECHNOLOGY_MASK_A);
} break;
case NFA_DEACTIVATED_EVT:
case NFA_CE_DEACTIVATED_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_DEACTIVATED_EVT, NFA_CE_DEACTIVATED_EVT", fn);
routingManager.notifyDeactivated(NFA_TECHNOLOGY_MASK_A);
SyncEventGuard g(gDeactivatedEvent);
gActivated = false; // guard this variable from multi-threaded access
gDeactivatedEvent.notifyOne();
} break;
case NFA_CE_DATA_EVT: {
tNFA_CE_DATA& ce_data = eventData->ce_data;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_CE_DATA_EVT; stat=0x%X; h=0x%X; data len=%u",
fn, ce_data.status, ce_data.handle, ce_data.len);
getInstance().handleData(NFA_TECHNOLOGY_MASK_A, ce_data.p_data,
ce_data.len, ce_data.status);
} break;
}
}
void RoutingManager::updateRoutingTable() {
#if(NXP_EXTNS != TRUE)
updateEeTechRouteSetting();
updateDefaultProtocolRoute();
#endif
updateDefaultRoute();
}
void RoutingManager::updateDefaultProtocolRoute() {
static const char fn[] = "RoutingManager::updateDefaultProtocolRoute";
// Default Routing for ISO-DEP
tNFA_PROTOCOL_MASK protoMask = NFA_PROTOCOL_MASK_ISO_DEP;
tNFA_STATUS nfaStat;
if (mDefaultIsoDepRoute != NFC_DH_ID) {
nfaStat = NFA_EeClearDefaultProtoRouting(mDefaultIsoDepRoute, protoMask);
nfaStat = NFA_EeSetDefaultProtoRouting(
mDefaultIsoDepRoute, protoMask, mSecureNfcEnabled ? 0 : protoMask, 0,
mSecureNfcEnabled ? 0 : protoMask, mSecureNfcEnabled ? 0 : protoMask,
mSecureNfcEnabled ? 0 : protoMask);
} else {
nfaStat = NFA_EeClearDefaultProtoRouting(NFC_DH_ID, protoMask);
nfaStat = NFA_EeSetDefaultProtoRouting(
NFC_DH_ID, protoMask, 0, 0, mSecureNfcEnabled ? 0 : protoMask, 0, 0);
}
if (nfaStat == NFA_STATUS_OK)
DLOG_IF(INFO, nfc_debug_enabled)
<< fn << ": Succeed to register default ISO-DEP route";
else
LOG(ERROR) << fn << ": failed to register default ISO-DEP route";
// Default routing for T3T protocol
if (!mIsScbrSupported) {
SyncEventGuard guard(mRoutingEvent);
tNFA_PROTOCOL_MASK protoMask = NFA_PROTOCOL_MASK_T3T;
if (mDefaultEe == NFC_DH_ID) {
nfaStat =
NFA_EeSetDefaultProtoRouting(NFC_DH_ID, protoMask, 0, 0, 0, 0, 0);
} else {
nfaStat = NFA_EeClearDefaultProtoRouting(mDefaultEe, protoMask);
nfaStat = NFA_EeSetDefaultProtoRouting(
mDefaultEe, protoMask, 0, 0, mSecureNfcEnabled ? 0 : protoMask,
mSecureNfcEnabled ? 0 : protoMask, mSecureNfcEnabled ? 0 : protoMask);
}
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait();
else
LOG(ERROR) << fn << "Fail to set default proto routing for T3T";
}
}
void RoutingManager::updateDefaultRoute() {
static const char fn[] = "RoutingManager::updateDefaultRoute";
if (NFC_GetNCIVersion() != NCI_VERSION_2_0) return;
#if (NXP_EXTNS == TRUE)
uint16_t routeLoc = ((mDefaultSysCodeRoute == 0x00) ? ROUTE_LOC_HOST_ID :
((mDefaultSysCodeRoute == 0x01 ) ? ROUTE_LOC_ESE_ID : getUiccRouteLocId(mDefaultSysCodeRoute)));
/*Map PWR state as per NCI2.0 if required*/
bool stat = checkAndUpdatePowerState((int&)mDefaultSysCodePowerstate);
if (mDefaultSysCodeRoute == SecureElement::DH_ID) {
mDefaultSysCodePowerstate &= ~(PWR_SWTCH_OFF_MASK | PWR_BATT_OFF_MASK);
if (!stat) mDefaultSysCodePowerstate &= (HOST_PWR_STATE);
}
#endif
// Register System Code for routing
SyncEventGuard guard(mRoutingEvent);
#if (NXP_EXTNS == TRUE)
tNFA_STATUS nfaStat = NFA_EeAddSystemCodeRouting(
mDefaultSysCode, routeLoc,
mSecureNfcEnabled ? (mDefaultSysCodePowerstate & 0x01) : mDefaultSysCodePowerstate);
#else
tNFA_STATUS nfaStat = NFA_EeAddSystemCodeRouting(
mDefaultSysCode, mDefaultSysCodeRoute,
mSecureNfcEnabled ? 0x01 : mDefaultSysCodePowerstate);
#endif
if (nfaStat == NFA_STATUS_NOT_SUPPORTED) {
mIsScbrSupported = false;
LOG(ERROR) << fn << ": SCBR not supported";
} else if (nfaStat == NFA_STATUS_OK) {
mIsScbrSupported = true;
mRoutingEvent.wait();
DLOG_IF(INFO, nfc_debug_enabled)
<< fn << ": Succeed to register system code";
} else {
LOG(ERROR) << fn << ": Fail to register system code";
}
#if (NXP_EXTNS != TRUE)
// Register zero lengthy Aid for default Aid Routing
if (mDefaultEe != mDefaultIsoDepRoute) {
uint8_t powerState = 0x01;
if (!mSecureNfcEnabled)
powerState = (mDefaultEe != 0x00) ? mOffHostAidRoutingPowerState : 0x11;
nfaStat = NFA_EeAddAidRouting(mDefaultEe, 0, NULL, powerState,
AID_ROUTE_QUAL_PREFIX);
if (nfaStat == NFA_STATUS_OK)
DLOG_IF(INFO, nfc_debug_enabled)
<< fn << ": Succeed to register zero length AID";
else
LOG(ERROR) << fn << ": failed to register zero length AID";
}
#endif
}
tNFA_TECHNOLOGY_MASK RoutingManager::updateEeTechRouteSetting() {
static const char fn[] = "RoutingManager::updateEeTechRouteSetting";
tNFA_TECHNOLOGY_MASK allSeTechMask = 0x00;
#if(NXP_EXTNS == TRUE)
int handleDefaultOffHost = SecureElement::getInstance().getEseHandleFromGenericId(mDefaultOffHostRoute);
int handleDefaultFelicaRoute = SecureElement::getInstance().getEseHandleFromGenericId(mDefaultFelicaRoute);
#endif
if (mDefaultOffHostRoute == 0 && mDefaultFelicaRoute == 0)
return allSeTechMask;
DLOG_IF(INFO, nfc_debug_enabled)
<< fn << ": Number of EE is " << (int)mEeInfo.num_ee;
tNFA_STATUS nfaStat;
for (uint8_t i = 0; i < mEeInfo.num_ee; i++) {
tNFA_HANDLE eeHandle = mEeInfo.ee_disc_info[i].ee_handle;
tNFA_TECHNOLOGY_MASK seTechMask = 0;
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, i, eeHandle, mEeInfo.ee_disc_info[i].la_protocol,
mEeInfo.ee_disc_info[i].lb_protocol,
mEeInfo.ee_disc_info[i].lf_protocol,
mEeInfo.ee_disc_info[i].lbp_protocol);
if ((mDefaultOffHostRoute != 0) &&
#if(NXP_EXTNS != TRUE)
(eeHandle == (mDefaultOffHostRoute | NFA_HANDLE_GROUP_EE))) {
#else
(eeHandle == handleDefaultOffHost)) {
#endif
if (mEeInfo.ee_disc_info[i].la_protocol != 0)
seTechMask |= NFA_TECHNOLOGY_MASK_A;
if (mEeInfo.ee_disc_info[i].lb_protocol != 0)
seTechMask |= NFA_TECHNOLOGY_MASK_B;
}
if ((mDefaultFelicaRoute != 0) &&
#if(NXP_EXTNS != TRUE)
(eeHandle == (mDefaultFelicaRoute | NFA_HANDLE_GROUP_EE))) {
#else
(eeHandle == handleDefaultFelicaRoute)) {
#endif
if (mEeInfo.ee_disc_info[i].lf_protocol != 0)
seTechMask |= NFA_TECHNOLOGY_MASK_F;
}
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: seTechMask[%u]=0x%02x", fn, i, seTechMask);
if (seTechMask != 0x00) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"Configuring tech mask 0x%02x on EE 0x%04x", seTechMask, eeHandle);
nfaStat = NFA_CeConfigureUiccListenTech(eeHandle, seTechMask);
if (nfaStat != NFA_STATUS_OK)
LOG(ERROR) << fn << "Failed to configure UICC listen technologies.";
// clear previous before setting new power state
nfaStat = NFA_EeClearDefaultTechRouting(eeHandle, seTechMask);
if (nfaStat != NFA_STATUS_OK)
LOG(ERROR) << fn << "Failed to clear EE technology routing.";
nfaStat = NFA_EeSetDefaultTechRouting(
eeHandle, seTechMask, mSecureNfcEnabled ? 0 : seTechMask, 0,
mSecureNfcEnabled ? 0 : seTechMask,
mSecureNfcEnabled ? 0 : seTechMask,
mSecureNfcEnabled ? 0 : seTechMask);
if (nfaStat != NFA_STATUS_OK)
LOG(ERROR) << fn << "Failed to configure UICC technology routing.";
allSeTechMask |= seTechMask;
}
}
// Clear DH technology route on NFC-A
if ((allSeTechMask & NFA_TECHNOLOGY_MASK_A) != 0) {
nfaStat = NFA_EeClearDefaultTechRouting(NFC_DH_ID, NFA_TECHNOLOGY_MASK_A);
if (nfaStat != NFA_STATUS_OK)
LOG(ERROR) << "Failed to clear DH technology routing on NFC-A.";
}
// Clear DH technology route on NFC-F
if ((allSeTechMask & NFA_TECHNOLOGY_MASK_F) != 0) {
nfaStat = NFA_EeClearDefaultTechRouting(NFC_DH_ID, NFA_TECHNOLOGY_MASK_F);
if (nfaStat != NFA_STATUS_OK)
LOG(ERROR) << "Failed to clear DH technology routing on NFC-F.";
}
return allSeTechMask;
}
/*******************************************************************************
**
** Function: nfaEeCallback
**
** Description: Receive execution environment-related events from stack.
** event: Event code.
** eventData: Event data.
**
** Returns: None
**
*******************************************************************************/
void RoutingManager::nfaEeCallback(tNFA_EE_EVT event,
tNFA_EE_CBACK_DATA* eventData) {
static const char fn[] = "RoutingManager::nfaEeCallback";
RoutingManager& routingManager = RoutingManager::getInstance();
if (!eventData) {
LOG(ERROR) << "eventData is null";
return;
}
routingManager.mCbEventData = *eventData;
#if (NXP_EXTNS == TRUE)
SecureElement& se = SecureElement::getInstance();
#endif
switch (event) {
case NFA_EE_REGISTER_EVT: {
SyncEventGuard guard(routingManager.mEeRegisterEvent);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_REGISTER_EVT; status=%u", fn, eventData->ee_register);
routingManager.mEeRegisterEvent.notifyOne();
} break;
case NFA_EE_DEREGISTER_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_DEREGISTER_EVT; status=0x%X", fn, eventData->status);
routingManager.mReceivedEeInfo = false;
} break;
case NFA_EE_MODE_SET_EVT: {
SyncEventGuard guard(routingManager.mEeSetModeEvent);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_MODE_SET_EVT; status: 0x%04X handle: 0x%04X ", fn,
eventData->mode_set.status, eventData->mode_set.ee_handle);
routingManager.mEeSetModeEvent.notifyOne();
#if (NXP_EXTNS == TRUE)
se.mModeSetNtfstatus = eventData->mode_set.status;
se.notifyModeSet(eventData->mode_set.ee_handle, !(eventData->mode_set.status),eventData->mode_set.ee_status );
#endif
} break;
#if (NXP_EXTNS == TRUE)
case NFA_EE_PWR_LINK_CTRL_EVT:
{
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: NFA_EE_PWR_LINK_CTRL_EVT; status: 0x%04X ", fn,
eventData->pwr_lnk_ctrl.status);
se.mPwrCmdstatus = eventData->pwr_lnk_ctrl.status;
SyncEventGuard guard (se.mPwrLinkCtrlEvent);
se.mPwrLinkCtrlEvent.notifyOne();
}
break;
#endif
case NFA_EE_SET_TECH_CFG_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_SET_TECH_CFG_EVT; status=0x%X", fn, eventData->status);
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
} break;
case NFA_EE_CLEAR_TECH_CFG_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_CLEAR_TECH_CFG_EVT; status=0x%X", fn, eventData->status);
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
} break;
case NFA_EE_SET_PROTO_CFG_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_SET_PROTO_CFG_EVT; status=0x%X", fn, eventData->status);
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
} break;
case NFA_EE_CLEAR_PROTO_CFG_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_CLEAR_PROTO_CFG_EVT; status=0x%X", fn, eventData->status);
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
} break;
case NFA_EE_ACTION_EVT: {
tNFA_EE_ACTION& action = eventData->action;
if (action.trigger == NFC_EE_TRIG_SELECT)
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=select (0x%X)", fn,
action.ee_handle, action.trigger);
else if (action.trigger == NFC_EE_TRIG_APP_INIT) {
tNFC_APP_INIT& app_init = action.param.app_init;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=app-init "
"(0x%X); aid len=%u; data len=%u",
fn, action.ee_handle, action.trigger, app_init.len_aid,
app_init.len_data);
} else if (action.trigger == NFC_EE_TRIG_RF_PROTOCOL)
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=rf protocol (0x%X)", fn,
action.ee_handle, action.trigger);
else if (action.trigger == NFC_EE_TRIG_RF_TECHNOLOGY)
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=rf tech (0x%X)", fn,
action.ee_handle, action.trigger);
else
#if (NXP_EXTNS == TRUE)
{
#endif
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_ACTION_EVT; h=0x%X; unknown trigger (0x%X)", fn,
action.ee_handle, action.trigger);
#if (NXP_EXTNS == TRUE)
NativeJniExtns::getInstance().notifyNfcEvent("updateNfceeActionNtf",
(void*)&action);
}
#endif
} break;
case NFA_EE_DISCOVER_REQ_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_DISCOVER_REQ_EVT; status=0x%X; num ee=%u", __func__,
eventData->discover_req.status, eventData->discover_req.num_ee);
SyncEventGuard guard(routingManager.mEeInfoEvent);
memcpy(&routingManager.mEeInfo, &eventData->discover_req,
sizeof(routingManager.mEeInfo));
routingManager.mReceivedEeInfo = true;
routingManager.mEeInfoEvent.notifyOne();
} break;
case NFA_EE_NO_CB_ERR_EVT:
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_NO_CB_ERR_EVT status=%u", fn, eventData->status);
break;
case NFA_EE_ADD_AID_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_ADD_AID_EVT status=%u", fn, eventData->status);
#if(NXP_EXTNS == TRUE)
SyncEventGuard guard(routingManager.mAidAddRemoveEvent);
routingManager.mAidAddRemoveEvent.notifyOne();
#endif
} break;
case NFA_EE_ADD_SYSCODE_EVT: {
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_ADD_SYSCODE_EVT status=%u", fn, eventData->status);
} break;
case NFA_EE_REMOVE_SYSCODE_EVT: {
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_REMOVE_SYSCODE_EVT status=%u", fn, eventData->status);
} break;
case NFA_EE_REMOVE_AID_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_REMOVE_AID_EVT status=%u", fn, eventData->status);
#if(NXP_EXTNS == TRUE)
SyncEventGuard guard(routingManager.mAidAddRemoveEvent);
routingManager.mAidAddRemoveEvent.notifyOne();
#endif
} break;
case NFA_EE_NEW_EE_EVT: {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_EE_NEW_EE_EVT h=0x%X; status=%u", fn,
eventData->new_ee.ee_handle, eventData->new_ee.ee_status);
} break;
case NFA_EE_UPDATED_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_EE_UPDATED_EVT", fn);
SyncEventGuard guard(routingManager.mEeUpdateEvent);
routingManager.mEeUpdateEvent.notifyOne();
} break;
default:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: unknown event=%u ????", fn, event);
break;
}
}
int RoutingManager::registerT3tIdentifier(uint8_t* t3tId, uint8_t t3tIdLen) {
static const char fn[] = "RoutingManager::registerT3tIdentifier";
DLOG_IF(INFO, nfc_debug_enabled)
<< fn << ": Start to register NFC-F system on DH";
if (t3tIdLen != (2 + NCI_RF_F_UID_LEN + NCI_T3T_PMM_LEN)) {
LOG(ERROR) << fn << ": Invalid length of T3T Identifier";
return NFA_HANDLE_INVALID;
}
mNfcFOnDhHandle = NFA_HANDLE_INVALID;
uint16_t systemCode;
uint8_t nfcid2[NCI_RF_F_UID_LEN];
uint8_t t3tPmm[NCI_T3T_PMM_LEN];
systemCode = (((int)t3tId[0] << 8) | ((int)t3tId[1] << 0));
memcpy(nfcid2, t3tId + 2, NCI_RF_F_UID_LEN);
memcpy(t3tPmm, t3tId + 10, NCI_T3T_PMM_LEN);
{
SyncEventGuard guard(mRoutingEvent);
tNFA_STATUS nfaStat = NFA_CeRegisterFelicaSystemCodeOnDH(
systemCode, nfcid2, t3tPmm, nfcFCeCallback);
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
} else {
LOG(ERROR) << StringPrintf("%s: Fail to register NFC-F system on DH", fn);
return NFA_HANDLE_INVALID;
}
}
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Succeed to register NFC-F system on DH", fn);
// Register System Code for routing
if (mIsScbrSupported) {
SyncEventGuard guard(mRoutingEvent);
tNFA_STATUS nfaStat = NFA_EeAddSystemCodeRouting(systemCode, NCI_DH_ID,
SYS_CODE_PWR_STATE_HOST);
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
}
if ((nfaStat != NFA_STATUS_OK) || (mCbEventData.status != NFA_STATUS_OK)) {
LOG(ERROR) << StringPrintf("%s: Fail to register system code on DH", fn);
return NFA_HANDLE_INVALID;
}
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Succeed to register system code on DH", fn);
// add handle and system code pair to the map
mMapScbrHandle.emplace(mNfcFOnDhHandle, systemCode);
} else {
LOG(ERROR) << StringPrintf("%s: SCBR Not supported", fn);
}
return mNfcFOnDhHandle;
}
void RoutingManager::deregisterT3tIdentifier(int handle) {
static const char fn[] = "RoutingManager::deregisterT3tIdentifier";
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Start to deregister NFC-F system on DH", fn);
{
SyncEventGuard guard(mRoutingEvent);
tNFA_STATUS nfaStat = NFA_CeDeregisterFelicaSystemCodeOnDH(handle);
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: Succeeded in deregistering NFC-F system on DH", fn);
} else {
LOG(ERROR) << StringPrintf("%s: Fail to deregister NFC-F system on DH",
fn);
}
}
if (mIsScbrSupported) {
map<int, uint16_t>::iterator it = mMapScbrHandle.find(handle);
// find system code for given handle
if (it != mMapScbrHandle.end()) {
uint16_t systemCode = it->second;
mMapScbrHandle.erase(handle);
if (systemCode != 0) {
SyncEventGuard guard(mRoutingEvent);
tNFA_STATUS nfaStat = NFA_EeRemoveSystemCodeRouting(systemCode);
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: Succeeded in deregistering system Code on DH", fn);
} else {
LOG(ERROR) << StringPrintf("%s: Fail to deregister system Code on DH",
fn);
}
}
}
}
}
void RoutingManager::nfcFCeCallback(uint8_t event,
tNFA_CONN_EVT_DATA* eventData) {
static const char fn[] = "RoutingManager::nfcFCeCallback";
RoutingManager& routingManager = RoutingManager::getInstance();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: 0x%x", __func__, event);
switch (event) {
case NFA_CE_REGISTERED_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: registerd event notified", fn);
routingManager.mNfcFOnDhHandle = eventData->ce_registered.handle;
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
} break;
case NFA_CE_DEREGISTERED_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: deregisterd event notified", fn);
SyncEventGuard guard(routingManager.mRoutingEvent);
routingManager.mRoutingEvent.notifyOne();
} break;
case NFA_CE_ACTIVATED_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: activated event notified", fn);
routingManager.notifyActivated(NFA_TECHNOLOGY_MASK_F);
} break;
case NFA_CE_DEACTIVATED_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: deactivated event notified", fn);
routingManager.notifyDeactivated(NFA_TECHNOLOGY_MASK_F);
} break;
case NFA_CE_DATA_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: data event notified", fn);
tNFA_CE_DATA& ce_data = eventData->ce_data;
routingManager.handleData(NFA_TECHNOLOGY_MASK_F, ce_data.p_data,
ce_data.len, ce_data.status);
} break;
default: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: unknown event=%u ????", fn, event);
} break;
}
}
bool RoutingManager::setNfcSecure(bool enable) {
mSecureNfcEnabled = enable;
DLOG_IF(INFO, true) << "setNfcSecure NfcService " << enable;
return true;
}
void RoutingManager::deinitialize() {
onNfccShutdown();
NFA_EeDeregister(nfaEeCallback);
}
int RoutingManager::registerJniFunctions(JNIEnv* e) {
static const char fn[] = "RoutingManager::registerJniFunctions";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", fn);
return jniRegisterNativeMethods(
e, "com/android/nfc/cardemulation/AidRoutingManager", sMethods,
NELEM(sMethods));
}
jbyteArray
RoutingManager::com_android_nfc_cardemulation_doGetOffHostUiccDestination(
JNIEnv* e) {
std::vector<uint8_t> uicc = getInstance().mOffHostRouteUicc;
if (uicc.size() == 0) {
return NULL;
}
CHECK(e);
jbyteArray uiccJavaArray = e->NewByteArray(uicc.size());
CHECK(uiccJavaArray);
e->SetByteArrayRegion(uiccJavaArray, 0, uicc.size(), (jbyte*)&uicc[0]);
return uiccJavaArray;
}
jbyteArray
RoutingManager::com_android_nfc_cardemulation_doGetOffHostEseDestination(
JNIEnv* e) {
std::vector<uint8_t> ese = getInstance().mOffHostRouteEse;
if (ese.size() == 0) {
return NULL;
}
CHECK(e);
jbyteArray eseJavaArray = e->NewByteArray(ese.size());
CHECK(eseJavaArray);
e->SetByteArrayRegion(eseJavaArray, 0, ese.size(), (jbyte*)&ese[0]);
return eseJavaArray;
}
int RoutingManager::com_android_nfc_cardemulation_doGetDefaultRouteDestination(
JNIEnv*) {
return getInstance().mDefaultEe;
}
int RoutingManager::
com_android_nfc_cardemulation_doGetDefaultOffHostRouteDestination(JNIEnv*) {
return getInstance().mDefaultOffHostRoute;
}
int RoutingManager::com_android_nfc_cardemulation_doGetAidMatchingMode(
JNIEnv*) {
return getInstance().mAidMatchingMode;
}
int RoutingManager::
com_android_nfc_cardemulation_doGetDefaultIsoDepRouteDestination(JNIEnv*) {
return RoutingManager::getInstance().mDefaultIsoDepRoute;
}
#if(NXP_EXTNS == TRUE)
/*******************************************************************************
**
** Function: getUiccRoute
**
** Description: returns EE Id corresponding to slot number
**
** Returns: route location
**
*******************************************************************************/
static jint getUiccRoute(jint uicc_slot)
{
LOG(ERROR) << StringPrintf("%s: Enter slot num = %d", __func__,uicc_slot);
if((uicc_slot == 0x00) || (uicc_slot == 0x01))
{
return SecureElement::getInstance().EE_HANDLE_0xF4;
}
else if(uicc_slot == 0x02)
{
return (RoutingManager::getInstance().getUicc2selected());
}
else
{
return 0xFF;
}
}
void RoutingManager::registerProtoRouteEnrty(tNFA_HANDLE ee_handle,
tNFA_PROTOCOL_MASK protocols_switch_on,
tNFA_PROTOCOL_MASK protocols_switch_off,
tNFA_PROTOCOL_MASK protocols_battery_off,
tNFA_PROTOCOL_MASK protocols_screen_lock,
tNFA_PROTOCOL_MASK protocols_screen_off,
tNFA_PROTOCOL_MASK protocols_screen_off_lock
)
{
tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
{
SyncEventGuard guard(mRoutingEvent);
nfaStat = NFA_EeSetDefaultProtoRouting(
ee_handle, protocols_switch_on,
mSecureNfcEnabled ? 0 :protocols_switch_off,
mSecureNfcEnabled ? 0 :protocols_battery_off,
mSecureNfcEnabled ? 0 :protocols_screen_lock,
mSecureNfcEnabled ? 0 :protocols_screen_off,
mSecureNfcEnabled ? 0 :protocols_screen_off_lock);
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("tech routing SUCCESS");
} else {
DLOG_IF(ERROR, nfc_debug_enabled)
<< StringPrintf("Fail to set default tech routing");
}
}
}
/*******************************************************************************
**
** Function: configureEeRegister
**
** Description: EE register & de-register can be done.
**
** Returns: None
**
*******************************************************************************/
void RoutingManager::configureEeRegister(bool eeReg)
{
static const char fn [] = "RoutingManager::configureEeRegister";
tNFA_STATUS nfaStat;
if(eeReg)
{
SyncEventGuard guard (mEeRegisterEvent);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: try ee register", fn);
nfaStat = NFA_EeRegister (nfaEeCallback);
if (nfaStat != NFA_STATUS_OK)
{
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("%s: fail ee register; error=0x%X", fn, nfaStat);
}
mEeRegisterEvent.wait ();
} else {
NFA_EeDeregister (nfaEeCallback);
}
}
void RoutingManager::configureOffHostNfceeTechMask(void)
{
//static const char fn [] = "RoutingManager::configureOffHostNfceeTechMask";
tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
uint8_t seId = 0x00;
uint8_t count = 0x00;
tNFA_HANDLE preferredHandle = SecureElement::getInstance().EE_HANDLE_0xF4;
tNFA_HANDLE defaultHandle = NFA_HANDLE_INVALID;
tNFA_HANDLE ee_handleList[nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED];
//ALOGV("%s: enter", fn);
if (mDefaultEe & SecureElement::ESE_ID) //eSE
{
preferredHandle = ROUTE_LOC_ESE_ID;
}
else if (mDefaultEe & SecureElement::UICC_ID) //UICC
{
preferredHandle = SecureElement::getInstance().EE_HANDLE_0xF4;
}
else if (isDynamicUiccEnabled &&
(mDefaultEe & SecureElement::UICC2_ID)) //UICC
{
preferredHandle = getUicc2selected();
}
SecureElement::getInstance().getEeHandleList(ee_handleList, &count);
for (uint8_t i = 0; ((count != 0 ) && (i < count)); i++)
{
seId = SecureElement::getInstance().getGenericEseId(ee_handleList[i]);
defaultHandle = SecureElement::getInstance().getEseHandleFromGenericId(seId);
//ALOGV("%s: ee_handleList[%d] : 0x%X", fn, i,ee_handleList[i]);
if (preferredHandle == defaultHandle)
{
break;
}
defaultHandle = NFA_HANDLE_INVALID;
}
if((defaultHandle != NFA_HANDLE_INVALID) && (0 != mUiccListnTechMask))
{
{
//SyncEventGuard guard (SecureElement::getInstance().mUiccListenEvent);
nfaStat = NFA_CeConfigureUiccListenTech (defaultHandle, 0x00);
if (nfaStat == NFA_STATUS_OK)
{
//SecureElement::getInstance().mUiccListenEvent.wait ();
}
else
LOG(ERROR) << StringPrintf("fail to start UICC listen");
}
{
//SyncEventGuard guard (SecureElement::getInstance().mUiccListenEvent);
nfaStat = NFA_CeConfigureUiccListenTech (defaultHandle, (mUiccListnTechMask & 0x07));
if(nfaStat == NFA_STATUS_OK)
{
//SecureElement::getInstance().mUiccListenEvent.wait ();
}
else
LOG(ERROR) << StringPrintf("fail to start UICC listen");
}
}
//ALOGV("%s: exit", fn);
}
bool RoutingManager::setRoutingEntry(int type, int value, int route, int power)
{
static const char fn [] = "RoutingManager::setRoutingEntry";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter, >>>>>>>> type:0x%x value =0x%x route:%x power:0x%x", fn, type, value ,route, power);
unsigned long max_tech_mask = 0x03;
unsigned long uiccListenTech = 0;
if (!isDynamicUiccEnabled) {
if(nfcManager_getUiccRoute(sCurrentSelectedUICCSlot)!=0xFF) {
max_tech_mask = SecureElement::getInstance().getSETechnology(nfcManager_getUiccRoute(sCurrentSelectedUICCSlot));
} else {
max_tech_mask = SecureElement::getInstance().getSETechnology(SecureElement::getInstance().EE_HANDLE_0xF4);
}
} else {
max_tech_mask = SecureElement::getInstance().getSETechnology(SecureElement::getInstance().EE_HANDLE_0xF4);
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter,max_tech_mask :%lx", fn, max_tech_mask);
tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
tNFA_HANDLE ee_handle = NFA_HANDLE_INVALID;
uint8_t switch_on_mask = 0x00;
uint8_t switch_off_mask = 0x00;
uint8_t battery_off_mask = 0x00;
uint8_t screen_lock_mask = 0x00;
uint8_t screen_off_mask = 0x00;
uint8_t screen_off_lock_mask = 0x00;
uint8_t protocol_mask = 0x00;
ee_handle = ((route == 0x00) ? ROUTE_LOC_HOST_ID : ((route == 0x01) ? ROUTE_LOC_ESE_ID : getUiccRouteLocId(route)));
if(ee_handle == NFA_HANDLE_INVALID )
{
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter, handle:%x invalid", fn, ee_handle);
return nfaStat;
}
tNFA_HANDLE ActDevHandle = NFA_HANDLE_INVALID;
uint8_t count,seId=0;
uint8_t isSeIDPresent = 0;
tNFA_HANDLE ee_handleList[SecureElement::MAX_NUM_EE];
SecureElement::getInstance().getEeHandleList(ee_handleList, &count);
for (int i = 0; ((count != 0 ) && (i < count)); i++)
{
seId = SecureElement::getInstance().getGenericEseId(ee_handleList[i]);
ActDevHandle = SecureElement::getInstance().getEseHandleFromGenericId(seId);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter, ee_handleList[%d]:%x", fn, i,ee_handleList[i]);
if ((ee_handle != 0x400) &&
(ee_handle == ActDevHandle))
{
isSeIDPresent =1;
break;
}
}
/*Map PWR state as per NCI2.0 if required*/
bool stat = checkAndUpdatePowerState(power);
if ((ee_handle == ROUTE_LOC_HOST_ID) &&
(NFA_SET_PROTOCOL_ROUTING == type)) {
power &= ~(PWR_SWTCH_OFF_MASK | PWR_BATT_OFF_MASK);
if (!stat) power &= (HOST_PWR_STATE);
isSeIDPresent = 1;
}
max_tech_mask = SecureElement::getInstance().getSETechnology(ee_handle);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter,max_tech_mask :%lx", fn, max_tech_mask);
if(NFA_SET_TECHNOLOGY_ROUTING == type)
{
/* Masking with available SE Technologies */
value &= max_tech_mask;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter >>>> max_tech_mask :%lx value :0x%x", fn, max_tech_mask, value);
switch_on_mask = (power & 0x01) ? value : 0;
switch_off_mask = (power & 0x02) ? value : 0;
battery_off_mask = (power & 0x04) ? value : 0;
screen_off_mask = (power & 0x08) ? value : 0;
screen_lock_mask = (power & 0x10) ? value : 0;
screen_off_lock_mask = (power & 0x20) ? value : 0;
if((max_tech_mask != 0x01) && (max_tech_mask == 0x02)) // type B only
{
switch_on_mask &= ~NFA_TECHNOLOGY_MASK_A;
switch_off_mask &= ~NFA_TECHNOLOGY_MASK_A;
battery_off_mask &= ~NFA_TECHNOLOGY_MASK_A;
screen_off_mask &= ~NFA_TECHNOLOGY_MASK_A;
screen_lock_mask &= ~NFA_TECHNOLOGY_MASK_A;
screen_off_lock_mask &= ~NFA_TECHNOLOGY_MASK_A;
}
else if((max_tech_mask == 0x01) && (max_tech_mask != 0x02)) // type A only
{
switch_on_mask &= ~NFA_TECHNOLOGY_MASK_B;
switch_off_mask &= ~NFA_TECHNOLOGY_MASK_B;
battery_off_mask &= ~NFA_TECHNOLOGY_MASK_B;
screen_off_mask &= ~NFA_TECHNOLOGY_MASK_B;
screen_lock_mask &= ~NFA_TECHNOLOGY_MASK_B;
screen_off_lock_mask &= ~NFA_TECHNOLOGY_MASK_B;
}
if((mHostListnTechMask) && (mFwdFuntnEnable == true))
{
if((max_tech_mask != 0x01) && (max_tech_mask == 0x02))
{
{
SyncEventGuard guard (mRoutingEvent);
if(mCeRouteStrictDisable == 0x01)
{
nfaStat = NFA_EeSetDefaultTechRouting (0x400,
NFA_TECHNOLOGY_MASK_A,
0,
0,
mSecureNfcEnabled ? 0 : NFA_TECHNOLOGY_MASK_A,
0,
0 );
}else{
nfaStat = NFA_EeSetDefaultTechRouting (0x400,
NFA_TECHNOLOGY_MASK_A,
0, 0, 0, 0,0 );
}
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait ();
else
{
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("Fail to set tech routing");
}
}
}
else if((max_tech_mask == 0x01) && (max_tech_mask != 0x02))
{
{
SyncEventGuard guard (mRoutingEvent);
if(mCeRouteStrictDisable == 0x01)
{
nfaStat = NFA_EeSetDefaultTechRouting (0x400,
NFA_TECHNOLOGY_MASK_B,
0,
0,
mSecureNfcEnabled ? 0 : NFA_TECHNOLOGY_MASK_B,
0,
0);
}else{
nfaStat = NFA_EeSetDefaultTechRouting (0x400,
NFA_TECHNOLOGY_MASK_B,
0, 0, 0, 0, 0);
}
if (nfaStat == NFA_STATUS_OK)
mRoutingEvent.wait ();
else
{
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("Fail to set tech routing");
}
}
}
}
{
SyncEventGuard guard (mRoutingEvent);
nfaStat = NFA_EeSetDefaultTechRouting (ee_handle, switch_on_mask,
mSecureNfcEnabled ? 0 : switch_off_mask,
mSecureNfcEnabled ? 0 : battery_off_mask,
mSecureNfcEnabled ? 0 : screen_lock_mask,
mSecureNfcEnabled ? 0 : screen_off_mask,
mSecureNfcEnabled ? 0 : screen_off_lock_mask);
if(nfaStat == NFA_STATUS_OK){
mRoutingEvent.wait ();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("tech routing SUCCESS");
}
else{
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("Fail to set default tech routing");
}
}
}else if(NFA_SET_PROTOCOL_ROUTING == type && isSeIDPresent == 1)
{
value &= ~(0xF0);
while(value)
{
if( value & 0x01)
{
protocol_mask = NFA_PROTOCOL_MASK_ISO_DEP;
value &= ~(0x01);
}
else if( value & 0x02)
{
protocol_mask = NFA_PROTOCOL_MASK_NFC_DEP;
value &= ~(0x02);
}
else if( value & 0x04)
{
protocol_mask = NFA_PROTOCOL_MASK_T3T;
value &= ~(0x04);
}
else if( value & 0x08)
{
protocol_mask = NFC_PROTOCOL_MASK_ISO7816;
value &= ~(0x08);
}
if(protocol_mask)
{
switch_on_mask = (power & 0x01) ? protocol_mask : 0;
switch_off_mask = (power & 0x02) ? protocol_mask : 0;
battery_off_mask = (power & 0x04) ? protocol_mask : 0;
screen_lock_mask = (power & 0x10) ? protocol_mask : 0;
screen_off_mask = (power & 0x08) ? protocol_mask : 0;
screen_off_lock_mask = (power & 0x20) ? protocol_mask : 0;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter >>>> ee_handle:%x %x %x %x %x %x %x", fn, ee_handle,
switch_on_mask,
switch_off_mask,
battery_off_mask,
screen_lock_mask,
screen_off_mask,
screen_off_lock_mask);
registerProtoRouteEnrty(ee_handle, switch_on_mask, switch_off_mask,
battery_off_mask, screen_lock_mask, screen_off_mask, screen_off_lock_mask);
protocol_mask = 0;
}
}
}
uiccListenTech = NfcConfig::getUnsigned(NAME_UICC_LISTEN_TECH_MASK, 0x07);
if((ActDevHandle != NFA_HANDLE_INVALID) && (0 != uiccListenTech))
{
{
//SyncEventGuard guard (SecureElement::getInstance().mUiccListenEvent);
nfaStat = NFA_CeConfigureUiccListenTech (ActDevHandle, (uiccListenTech & 0x07));
if(nfaStat == NFA_STATUS_OK)
{
//SecureElement::getInstance().mUiccListenEvent.wait ();
}
else
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("fail to start UICC listen");
}
}
return nfaStat;
}
bool RoutingManager::clearAidTable ()
{
static const char fn [] = "RoutingManager::clearAidTable";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn);
SyncEventGuard guard(RoutingManager::getInstance().mAidAddRemoveEvent);
tNFA_STATUS nfaStat = NFA_EeRemoveAidRouting(NFA_REMOVE_ALL_AID_LEN, (uint8_t*) NFA_REMOVE_ALL_AID);
if (nfaStat == NFA_STATUS_OK)
{
RoutingManager::getInstance().mAidAddRemoveEvent.wait();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: removed AID", fn);
return true;
} else
{
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("%s: failed to remove AID", fn);
return false;
}
}
bool RoutingManager::clearRoutingEntry(int type)
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Enter . Clear Routing Type = %d", __func__, type);
tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
tNFA_HANDLE ee_handleList[nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED];
uint8_t i, count;
SyncEventGuard guard(mRoutingEvent);
SecureElement::getInstance().getEeHandleList(ee_handleList, &count);
if (count > nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED) {
count = nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED;
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf(
"Count is more than SecureElement::MAX_NUM_EE,Forcing to "
"SecureElement::MAX_NUM_EE");
}
if(NFA_SET_TECHNOLOGY_ROUTING & type)
{
for (i = 0; i < count; i++) {
nfaStat = NFA_EeClearDefaultTechRouting(
ee_handleList[i], (NFA_TECHNOLOGY_MASK_A |
NFA_TECHNOLOGY_MASK_B | NFA_TECHNOLOGY_MASK_F));
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
}
}
nfaStat = NFA_EeClearDefaultTechRouting(
NFA_EE_HANDLE_DH, (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B |
NFA_TECHNOLOGY_MASK_F));
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
}
}
if(NFA_SET_PROTOCOL_ROUTING & type)
{
for (i = 0; i < count; i++) {
nfaStat = NFA_EeClearDefaultProtoRouting( ee_handleList[i],
(NFA_PROTOCOL_MASK_ISO_DEP | NFC_PROTOCOL_MASK_ISO7816));
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
}
}
nfaStat = NFA_EeClearDefaultProtoRouting( NFA_EE_HANDLE_DH,
(NFA_PROTOCOL_MASK_ISO_DEP | NFC_PROTOCOL_MASK_ISO7816));
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
}
}
if (NFA_SET_AID_ROUTING & type)
{
clearAidTable();
}
return ((nfaStat == NFA_STATUS_OK)? true: false);
}
/*
* In NCI2.0 Protocol 7816 routing is replaced with empty AID
* Routing entry Format :
* Type = [0x12]
* Length = 2 [0x02]
* Value = [Route_loc, Power_state]
* */
void RoutingManager::setEmptyAidEntry(int route) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter",__func__);
uint16_t routeLoc = NFA_HANDLE_INVALID;
uint32_t power;
uint8_t count,seId=0;
uint8_t isDefaultAidRoutePresent = 0;
unsigned long check_default_proto_se_id_req = 0;
tNFA_HANDLE ActDevHandle = NFA_HANDLE_INVALID;
static const char fn [] = "RoutingManager::checkProtoSeID";
tNFA_HANDLE ee_handleList[nfcFL.nfccFL._NFA_EE_MAX_EE_SUPPORTED];
mDefaultIso7816SeID = route;
if (mDefaultIso7816SeID == NFA_HANDLE_INVALID)
{
LOG(ERROR) << StringPrintf("%s: Invalid routeLoc. Return.", __func__);
return;
}
routeLoc = ((mDefaultIso7816SeID == 0x00) ? ROUTE_LOC_HOST_ID : ((mDefaultIso7816SeID == 0x01 ) ? ROUTE_LOC_ESE_ID : getUiccRouteLocId(mDefaultIso7816SeID)));
power = mCeRouteStrictDisable ? mDefaultIso7816Powerstate : (mDefaultIso7816Powerstate & POWER_STATE_MASK);
if (NfcConfig::hasKey(NAME_CHECK_DEFAULT_PROTO_SE_ID)) {
check_default_proto_se_id_req =
NfcConfig::getUnsigned(NAME_CHECK_DEFAULT_PROTO_SE_ID);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: CHECK_DEFAULT_PROTO_SE_ID - 0x%2lX routeLoc = 0x%x", fn,
check_default_proto_se_id_req, routeLoc);
} else {
LOG(ERROR) << StringPrintf(
"%s: CHECK_DEFAULT_PROTO_SE_ID not defined. Taking default value - "
"0x%2lX",
fn, check_default_proto_se_id_req);
}
if(check_default_proto_se_id_req == 0x01)
{
SecureElement::getInstance().getEeHandleList(ee_handleList, &count);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: count : %d", fn, count);
for (int i = 0; ((count != 0 ) && (i < count)); i++)
{
seId = SecureElement::getInstance().getGenericEseId(ee_handleList[i]);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: seId : %d", fn, seId);
ActDevHandle = SecureElement::getInstance().getEseHandleFromGenericId(seId);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: ActDevHandle : 0x%X", fn, ActDevHandle);
if (routeLoc == ActDevHandle)
{
isDefaultAidRoutePresent = 1;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Default AID route handle active");
}
if(isDefaultAidRoutePresent)
{
break;
}
}
if(!isDefaultAidRoutePresent)
{
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Default AidRoute not present");
mDefaultIso7816SeID = ROUTE_LOC_HOST_ID;
routeLoc = mDefaultIso7816SeID;
if(NFA_GetNCIVersion() != NCI_VERSION_2_0)
{
mDefaultIso7816Powerstate &= (PWR_SWTCH_ON_SCRN_UNLCK_MASK | PWR_SWTCH_ON_SCRN_LOCK_MASK);
power = mDefaultIso7816Powerstate;
}
}
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: route %x",__func__,routeLoc);
/*Map PWR state as per NCI2.0 if required*/
bool stat = checkAndUpdatePowerState((int&)power);
if(routeLoc == ROUTE_LOC_HOST_ID) {
power &= ~(PWR_SWTCH_OFF_MASK | PWR_BATT_OFF_MASK);
if (!stat) power &= (HOST_PWR_STATE);
}
if(mDefaultGsmaPowerState) {
/*Map PWR state as per NCI2.0 if required*/
checkAndUpdatePowerState((int&)mDefaultGsmaPowerState);
if(routeLoc == ROUTE_LOC_HOST_ID)
power = (mDefaultGsmaPowerState &
(~(PWR_SWTCH_OFF_MASK | PWR_BATT_OFF_MASK)));
else
power = mDefaultGsmaPowerState;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: gsma %x",__func__,power);
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: power %x",__func__,power);
if(power){
tNFA_STATUS nfaStat = NFA_EeAddAidRouting(
routeLoc, 0, NULL, mSecureNfcEnabled ? 0x01 : (uint8_t)power,
AID_ROUTE_QUAL_PREFIX);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Status :0x%2x", __func__, nfaStat);
}else{
LOG(ERROR) << StringPrintf("%s:Invalid Power State" ,__func__);
}
}
/* Forward Functionality is to handle either technology which is supported by UICC
* We are handling it by setting the alternate technology(A/B) to HOST
* */
void RoutingManager::processTechEntriesForFwdfunctionality(void)
{
//static const char fn [] = "RoutingManager::processTechEntriesForFwdfunctionality";
uint32_t techSupportedByUICC = mTechSupportedByUicc1;
if(!isDynamicUiccEnabled) {
techSupportedByUICC = (getUiccRoute(sCurrentSelectedUICCSlot) == SecureElement::getInstance().EE_HANDLE_0xF4)?
mTechSupportedByUicc1 : mTechSupportedByUicc2;
}
else {
techSupportedByUICC = (mDefaultTechASeID == SecureElement::getInstance().EE_HANDLE_0xF4)?
mTechSupportedByUicc1:mTechSupportedByUicc2;
}
//ALOGV("%s: enter", fn);
switch(mHostListnTechMask)
{
case 0x01://Host wants to listen ISO-DEP in A tech only then following cases will arises:-
//i.Tech A only UICC present(Dont route Tech B to HOST),
//ii.Tech B only UICC present(Route Tech A to HOST),
//iii.Tech AB UICC present(Dont route any tech to HOST)
if(((mTechTableEntries[TECH_B_IDX].routeLoc == SecureElement::getInstance().EE_HANDLE_0xF4) || (mTechTableEntries[TECH_B_IDX].routeLoc == getUicc2selected())) &&
((((techSupportedByUICC & NFA_TECHNOLOGY_MASK_B) == 0) && (techSupportedByUICC & NFA_TECHNOLOGY_MASK_A) != 0)))//Tech A only supported UICC
{
//Tech A will goto UICC according to previous table
//Disable Tech B entry as host wants to listen A only
mTechTableEntries[TECH_B_IDX].enable = false;
}
if(((mTechTableEntries[TECH_A_IDX].routeLoc == SecureElement::getInstance().EE_HANDLE_0xF4) || (mTechTableEntries[TECH_A_IDX].routeLoc == getUicc2selected())) &&
((((techSupportedByUICC & NFA_TECHNOLOGY_MASK_A) == 0) && (techSupportedByUICC & NFA_TECHNOLOGY_MASK_B) != 0)))//Tech B only supported UICC
{
//Tech B will goto UICC according to previous table
//Route Tech A to HOST as Host wants to listen A only
mTechTableEntries[TECH_A_IDX].routeLoc = ROUTE_LOC_HOST_ID;
/*Allow only (screen On+unlock) and (screen On+lock) power state when routing to HOST*/
mTechTableEntries[TECH_A_IDX].power = (mTechTableEntries[TECH_A_IDX].power & HOST_SCREEN_STATE_MASK);
mTechTableEntries[TECH_A_IDX].enable = true;
}
if((techSupportedByUICC & 0x03) == 0x03)//AB both supported UICC
{
//Do Nothing
//Tech A and Tech B will goto according to previous table
//HCE A only / HCE-B only functionality wont work in this case
}
break;
case 0x02://Host wants to listen ISO-DEP in B tech only then if Cases: Tech A only UICC present(Route Tech B to HOST), Tech B only UICC present(Dont route Tech A to HOST), Tech AB UICC present(Dont route any tech to HOST)
if(((mTechTableEntries[TECH_B_IDX].routeLoc == SecureElement::getInstance().EE_HANDLE_0xF4) || (mTechTableEntries[TECH_B_IDX].routeLoc == getUicc2selected())) &&
((((techSupportedByUICC & NFA_TECHNOLOGY_MASK_B) == 0) && (techSupportedByUICC & NFA_TECHNOLOGY_MASK_A) != 0)))//Tech A only supported UICC
{
//Tech A will goto UICC according to previous table
//Route Tech B to HOST as host wants to listen B only
mTechTableEntries[TECH_B_IDX].routeLoc = ROUTE_LOC_HOST_ID;
/*Allow only (screen On+unlock) and (screen On+lock) power state when routing to HOST*/
mTechTableEntries[TECH_B_IDX].power = (mTechTableEntries[TECH_A_IDX].power & HOST_SCREEN_STATE_MASK);
mTechTableEntries[TECH_B_IDX].enable = true;
}
if(((mTechTableEntries[TECH_A_IDX].routeLoc == SecureElement::getInstance().EE_HANDLE_0xF4) || (mTechTableEntries[TECH_A_IDX].routeLoc == getUicc2selected())) &&
((((techSupportedByUICC & NFA_TECHNOLOGY_MASK_A) == 0) && (techSupportedByUICC & NFA_TECHNOLOGY_MASK_B) != 0)))//Tech B only supported UICC
{
//Tech B will goto UICC according to previous table
//Disable Tech A to HOST as host wants to listen B only
mTechTableEntries[TECH_A_IDX].enable = false;
}
if((techSupportedByUICC & 0x03) == 0x03)//AB both supported UICC
{
//Do Nothing
//Tech A and Tech B will goto UICC
//HCE A only / HCE-B only functionality wont work in this case
}
break;
case 0x03:
case 0x07://Host wants to listen ISO-DEP in AB both tech then if Cases: Tech A only UICC present(Route Tech B to HOST), Tech B only UICC present(Route Tech A to HOST), Tech AB UICC present(Dont route any tech to HOST)
/*If selected EE is UICC and it supports Bonly , then Set Tech A to Host */
/*Host doesn't support Tech Routing, To enable FWD functionality enabling tech route to Host.*/
if(((mTechTableEntries[TECH_A_IDX].routeLoc == SecureElement::getInstance().EE_HANDLE_0xF4) || (mTechTableEntries[TECH_A_IDX].routeLoc == getUicc2selected())) &&
((((techSupportedByUICC & NFA_TECHNOLOGY_MASK_A) == 0) && (techSupportedByUICC & NFA_TECHNOLOGY_MASK_B) != 0)))
{
mTechTableEntries[TECH_A_IDX].routeLoc = ROUTE_LOC_HOST_ID;
/*Allow only (screen On+unlock) and (screen On+lock) power state when routing to HOST*/
mTechTableEntries[TECH_A_IDX].power = (mTechTableEntries[TECH_A_IDX].power & HOST_SCREEN_STATE_MASK);
mTechTableEntries[TECH_A_IDX].enable = true;
}
/*If selected EE is UICC and it supports Aonly , then Set Tech B to Host*/
if(((mTechTableEntries[TECH_B_IDX].routeLoc == SecureElement::getInstance().EE_HANDLE_0xF4) || (mTechTableEntries[TECH_B_IDX].routeLoc == getUicc2selected())) &&
((((techSupportedByUICC & NFA_TECHNOLOGY_MASK_B) == 0) && (techSupportedByUICC & NFA_TECHNOLOGY_MASK_A) != 0)))
{
mTechTableEntries[TECH_B_IDX].routeLoc = ROUTE_LOC_HOST_ID;
/*Allow only (screen On+unlock) and (screen On+lock) power state when routing to HOST*/
mTechTableEntries[TECH_B_IDX].power = (mTechTableEntries[TECH_A_IDX].power & HOST_SCREEN_STATE_MASK);
mTechTableEntries[TECH_B_IDX].enable = true;
}
if((techSupportedByUICC & 0x03) == 0x03)//AB both supported UICC
{
//Do Nothing
//Tech A and Tech B will goto UICC
//HCE A only / HCE-B only functionality wont work in this case
}
break;
}
dumpTables(3);
//ALOGV("%s: exit", fn);
}
void RoutingManager::dumpTables(int xx)
{
switch(xx)
{
case 1://print only proto table
LOG(ERROR) << StringPrintf("--------------------Proto Table Entries------------------" );
for (int xx = 0; xx < MAX_PROTO_ENTRIES; xx++) {
LOG(ERROR) << StringPrintf(
"|Index=%d|RouteLoc=0x%03X|Proto=0x%02X|Power=0x%02X|Enable=0x%"
"01X|",
xx, mProtoTableEntries[xx].routeLoc,
mProtoTableEntries[xx].protocol, mProtoTableEntries[xx].power,
mProtoTableEntries[xx].enable);
}
//ALOGV("---------------------------------------------------------" );
break;
case 2://print Lmrt proto table
LOG(ERROR) << StringPrintf("----------------------------------------Lmrt Proto Entries------------------------------------" );
for (int xx = 0; xx < MAX_ROUTE_LOC_ENTRIES; xx++) {
LOG(ERROR) << StringPrintf(
"|Index=%d|nfceeID=0x%03X|SWTCH-ON=0x%02X|SWTCH-OFF=0x%02X|BAT-"
"OFF=0x%02X|SCRN-LOCK=0x%02X|SCRN-OFF=0x%02X|SCRN-OFF_LOCK=0x%"
"02X",
xx, mLmrtEntries[xx].nfceeID, mLmrtEntries[xx].proto_switch_on,
mLmrtEntries[xx].proto_switch_off,
mLmrtEntries[xx].proto_battery_off,
mLmrtEntries[xx].proto_screen_lock,
mLmrtEntries[xx].proto_screen_off,
mLmrtEntries[xx].proto_screen_off_lock);
}
//ALOGV("----------------------------------------------------------------------------------------------" );
break;
case 3://print only tech table
LOG(ERROR) << StringPrintf("--------------------Tech Table Entries------------------" );
for(int xx=0;xx<MAX_TECH_ENTRIES;xx++)
{
LOG(ERROR) << StringPrintf("|Index=%d|RouteLoc=0x%03X|Tech=0x%02X|Power=0x%02X|Enable=0x%01X|",
xx,
mTechTableEntries[xx].routeLoc,
mTechTableEntries[xx].technology,
mTechTableEntries[xx].power,
mTechTableEntries[xx].enable);
}
//ALOGV("--------------------------------------------------------" );
break;
case 4://print Lmrt tech table
LOG(ERROR) << StringPrintf("-----------------------------------------Lmrt Tech Entries------------------------------------" );
for(int xx=0;xx<MAX_TECH_ENTRIES;xx++)
{
LOG(ERROR) << StringPrintf("|Index=%d|nfceeID=0x%03X|SWTCH-ON=0x%02X|SWTCH-OFF=0x%02X|BAT-OFF=0x%02X|SCRN-LOCK=0x%02X|SCRN-OFF=0x%02X|SCRN-OFF_LOCK=0x%02X",
xx,
mLmrtEntries[xx].nfceeID,
mLmrtEntries[xx].tech_switch_on,
mLmrtEntries[xx].tech_switch_off,
mLmrtEntries[xx].tech_battery_off,
mLmrtEntries[xx].tech_screen_lock,
mLmrtEntries[xx].tech_screen_off,
mLmrtEntries[xx].tech_screen_off_lock);
}
//ALOGV("----------------------------------------------------------------------------------------------" );
break;
}
}
/* Based on the features enabled :- nfcFL.nfccFL._NFCC_DYNAMIC_DUAL_UICC, nfcFL.nfccFL._NFC_NXP_STAT_DUAL_UICC_WO_EXT_SWITCH & NFC_NXP_STAT_DUAL_UICC_EXT_SWITCH,
* Calculate the UICC route location ID.
* For DynamicDualUicc,Route location is based on the user configuration(6th & 7th bit) of route
* For StaticDualUicc without External Switch(with DynamicDualUicc enabled), Route location is based on user selection from selectUicc() API
* For StaticDualUicc(With External Switch), Route location is always ROUTE_LOC_UICC1_ID
*/
uint16_t RoutingManager::getUiccRouteLocId(const int route)
{
LOG(ERROR) << StringPrintf(" getUiccRouteLocId route %X",
route);
if((route != 0x02 ) &&(route != 0x03))
return NFA_HANDLE_INVALID;
if(!isDynamicUiccEnabled)
return getUiccRoute(sCurrentSelectedUICCSlot);
else if(isDynamicUiccEnabled)
return ((route == 0x02 ) ? SecureElement::getInstance().EE_HANDLE_0xF4 : getUicc2selected());
else /*#if (NFC_NXP_STAT_DUAL_UICC_EXT_SWITCH == true)*/
return SecureElement::getInstance().EE_HANDLE_0xF4;
}
/*******************************************************************************
**
** Function: getUicc2selected
**
** Description: returns UICC2 selected in config file
**
** Returns: route location
**
*******************************************************************************/
uint32_t RoutingManager:: getUicc2selected()
{
LOG(ERROR) << StringPrintf(" getUicc2selected route");
return (SecureElement::getInstance().muicc2_selected == SecureElement::UICC2_ID)?
SecureElement::getInstance().EE_HANDLE_0xF8:
SecureElement::getInstance().EE_HANDLE_0xF9;
}
/*******************************************************************************
**
** Function: getRouting
**
** Description: Send GET_LISTEN_MODE_ROUTING command
**
** Returns: None
**
*******************************************************************************/
void RoutingManager::getRouting(uint16_t* routeLen, uint8_t* routingBuff) {
tNFA_STATUS nfcStat = NFA_STATUS_FAILED;
if (routingBuff == NULL || routeLen == NULL) return;
sRoutingBuff = routingBuff;
SyncEventGuard guard(sNfaGetRoutingEvent);
nfcStat = NFC_GetRouting();
if (nfcStat == NFA_STATUS_OK) {
if(sNfaGetRoutingEvent.wait(NFC_CMD_TIMEOUT) == false) {
LOG(ERROR) << StringPrintf("Routing Event has terminated");
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("status=0x0%x", nfcStat);
*routeLen = sRoutingBuffLen;
} else {
*routeLen = 0x00;
}
}
/*******************************************************************************
**
** Function: processGetRouting
**
** Description: Process the eventData(current routing info) received during
** getRouting
** eventData : eventData
** sRoutingBuff : Array containing processed data
**
** Returns: None
**
*******************************************************************************/
void RoutingManager::processGetRoutingRsp(tNFA_DM_CBACK_DATA* eventData) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s : Enter", __func__);
uint8_t xx = 0, numTLVs = 0, currPos = 0, curTLVLen = 0;
uint8_t sRoutingCurrent[256];
if (eventData == NULL) return;
numTLVs = *(eventData->get_routing.param_tlvs + 1);
/*Copying only routing Entries.
Skipping fields,
More : 1Byte
No of Routing Entries : 1Byte*/
memcpy(sRoutingCurrent, eventData->get_routing.param_tlvs + 2,
eventData->get_routing.tlv_size - 2);
while (xx < numTLVs) {
curTLVLen = *(sRoutingCurrent + currPos + 1);
/*Filtering out Routing Entry corresponding to PROTOCOL_NFC_DEP*/
if ((*(sRoutingCurrent + currPos) == PROTOCOL_BASED_ROUTING) &&
(*(sRoutingCurrent + currPos + (curTLVLen + 1)) ==
NFA_PROTOCOL_NFC_DEP)) {
currPos = currPos + curTLVLen + TYPE_LENGTH_SIZE;
} else {
memcpy(sRoutingBuff + sRoutingBuffLen, sRoutingCurrent + currPos,
curTLVLen + TYPE_LENGTH_SIZE);
currPos = currPos + curTLVLen + TYPE_LENGTH_SIZE;
sRoutingBuffLen = sRoutingBuffLen + curTLVLen + TYPE_LENGTH_SIZE;
}
xx++;
}
if (eventData->status != NFA_STATUS_CONTINUE) {
SyncEventGuard guard(sNfaGetRoutingEvent);
sNfaGetRoutingEvent.notifyOne();
}
}
/*******************************************************************************
**
** Function: checkAndUpdatePowerState
**
** Description: Maps the proprietary power states to NCI2.0 power state
** Input power : Proprietary power input
**
** Returns: If JNI_EXTNS present(true), otherwise (false)
**
*******************************************************************************/
bool RoutingManager::checkAndUpdatePowerState(int& power) {
bool status = false;
uint8_t tempPower = (uint8_t)(power & POWER_STATE_MASK);
NativeJniExtns& jniExtns = NativeJniExtns::getInstance();
if (jniExtns.isExtensionPresent()) {
NativeJniExtns::getInstance().notifyNfcEvent("updateRoutingPowerState",
(void*)&tempPower);
status = true;
} else {
status = false;
}
power = tempPower;
return status;
}
#endif