blob: 3b5d137e250803349f3daaf6070bac29412aa117 [file] [log] [blame]
/*
* 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.
*
* 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 <cutils/properties.h>
#include <errno.h>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>
#include <semaphore.h>
#include "HciEventManager.h"
#include "JavaClassConstants.h"
#include "NfcAdaptation.h"
#include "NfcJniUtil.h"
#include "NfcSelfTest.h"
#include "NfcTag.h"
#include "PeerToPeer.h"
#include "Pn544Interop.h"
#include "PowerSwitch.h"
#include "RoutingManager.h"
#include "SyncEvent.h"
#include "nfc_config.h"
#if(NXP_EXTNS == TRUE)
#include "MposManager.h"
#include "SecureElement.h"
#include "DwpChannel.h"
#include "NativeJniExtns.h"
#endif
#include "ce_api.h"
#include "nfa_api.h"
#include "nfa_ee_api.h"
#include "nfa_p2p_api.h"
#include "nfc_brcm_defs.h"
#include "phNxpExtns.h"
#include "rw_api.h"
using android::base::StringPrintf;
#if(NXP_EXTNS == TRUE)
#define RDR_PASS_THRU_MODE_DISABLE (0x0)
#define RDR_PASS_THRU_MODE_ENABLE (0x1)
#define RDR_PASS_THRU_MODE_XCV (0x2)
#define RDR_PASS_THRU_ENABLE_TIMEOUT (1030)
#define RDR_PASS_THRU_DISABLE_TIMEOUT (1030)
#define RDR_PASS_THRU_XCV_TIMEOUT (1100)
#define RDR_PASS_THRU_MOD_TYPE_A (0x0)
#define RDR_PASS_THRU_MOD_TYPE_B (0x1)
#define RDR_PASS_THRU_MOD_TYPE_V (0x2)
#define RDR_PASS_THRU_MOD_TYPE_LIMIT (0x3)
#define CMD_HDR_SIZE_XCV (0x3)
#define SECURE_ELEMENT_UICC_SLOT_DEFAULT (0x01)
bool isDynamicUiccEnabled;
#endif
extern tNFA_DM_DISC_FREQ_CFG* p_nfa_dm_rf_disc_freq_cfg; // defined in stack
namespace android {
extern bool gIsTagDeactivating;
extern bool gIsSelectingRfInterface;
extern void nativeNfcTag_doTransceiveStatus(tNFA_STATUS status, uint8_t* buf,
uint32_t buflen);
extern void nativeNfcTag_notifyRfTimeout();
extern void nativeNfcTag_doConnectStatus(jboolean is_connect_ok);
extern void nativeNfcTag_doDeactivateStatus(int status);
extern void nativeNfcTag_doWriteStatus(jboolean is_write_ok);
extern jboolean nativeNfcTag_doDisconnect(JNIEnv*, jobject);
extern void nativeNfcTag_doCheckNdefResult(tNFA_STATUS status,
uint32_t max_size,
uint32_t current_size,
uint8_t flags);
extern void nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status);
extern void nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status);
extern void nativeNfcTag_formatStatus(bool is_ok);
extern void nativeNfcTag_resetPresenceCheck();
extern void nativeNfcTag_doReadCompleted(tNFA_STATUS status);
extern void nativeNfcTag_setRfInterface(tNFA_INTF_TYPE rfInterface);
extern void nativeNfcTag_abortWaits();
extern void nativeLlcpConnectionlessSocket_abortWait();
extern void nativeNfcTag_registerNdefTypeHandler();
extern void nativeNfcTag_acquireRfInterfaceMutexLock();
extern void nativeNfcTag_releaseRfInterfaceMutexLock();
extern void nativeLlcpConnectionlessSocket_receiveData(uint8_t* data,
uint32_t len,
uint32_t remote_sap);
#if(NXP_EXTNS == TRUE)
extern tNFA_STATUS Nxp_doResonantFrequency(bool modeOn);
void handleWiredmode(bool isShutdown);
int nfcManager_doPartialInitialize(JNIEnv* e, jobject o);
int nfcManager_doPartialDeInitialize(JNIEnv* e, jobject o);
extern tNFA_STATUS NxpNfc_Write_Cmd_Common(uint8_t retlen, uint8_t* buffer);
extern void NxpPropCmd_OnResponseCallback(uint8_t event, uint16_t param_len,
uint8_t * p_param);
extern tNFA_STATUS NxpPropCmd_send(uint8_t * pData4Tx, uint8_t dataLen,
uint8_t * rsp_len, uint8_t * rsp_buf,
uint32_t rspTimeout, tHAL_NFC_ENTRY * halMgr);
extern tNFA_STATUS send_flush_ram_to_flash();
extern bool gIsWaiting4Deact2SleepNtf;
extern bool gGotDeact2IdleNtf;
#endif
} // namespace android
/*****************************************************************************
**
** public variables and functions
**
*****************************************************************************/
bool gActivated = false;
SyncEvent gDeactivatedEvent;
SyncEvent sNfaSetPowerSubState;
bool legacy_mfc_reader = true;
SyncEvent sChangeDiscTechEvent;
#if(NXP_EXTNS == TRUE)
/*Structure to store discovery parameters*/
typedef struct discovery_Parameters
{
int technologies_mask;
bool enable_lptd;
bool reader_mode;
bool enable_p2p;
bool enable_host_routing;
bool restart;
}discovery_Parameters_t;
discovery_Parameters_t mDiscParams;
jint nfcManager_getUiccId(jint uicc_slot);
jint nfcManager_getUiccRoute(jint uicc_slot);
uint16_t sCurrentSelectedUICCSlot = SECURE_ELEMENT_UICC_SLOT_DEFAULT;
#endif
namespace android {
jmethodID gCachedNfcManagerNotifyNdefMessageListeners;
jmethodID gCachedNfcManagerNotifyTransactionListeners;
jmethodID gCachedNfcManagerNotifyLlcpLinkActivation;
jmethodID gCachedNfcManagerNotifyLlcpLinkDeactivated;
jmethodID gCachedNfcManagerNotifyLlcpFirstPacketReceived;
jmethodID gCachedNfcManagerNotifyHostEmuActivated;
jmethodID gCachedNfcManagerNotifyHostEmuData;
jmethodID gCachedNfcManagerNotifyHostEmuDeactivated;
jmethodID gCachedNfcManagerNotifyRfFieldActivated;
jmethodID gCachedNfcManagerNotifyRfFieldDeactivated;
const char* gNativeP2pDeviceClassName =
"com/android/nfc/dhimpl/NativeP2pDevice";
const char* gNativeLlcpServiceSocketClassName =
"com/android/nfc/dhimpl/NativeLlcpServiceSocket";
const char* gNativeLlcpConnectionlessSocketClassName =
"com/android/nfc/dhimpl/NativeLlcpConnectionlessSocket";
const char* gNativeLlcpSocketClassName =
"com/android/nfc/dhimpl/NativeLlcpSocket";
const char* gNativeNfcTagClassName = "com/android/nfc/dhimpl/NativeNfcTag";
const char* gNativeNfcManagerClassName =
"com/android/nfc/dhimpl/NativeNfcManager";
#if (NXP_EXTNS == TRUE)
const char* gNativeNfcSecureElementClassName =
"com/android/nfc/dhimpl/NativeNfcSecureElement";
const char* gNativeNfcMposManagerClassName =
"com/android/nfc/dhimpl/NativeNfcMposManager";
void enableLastRfDiscovery();
void storeLastDiscoveryParams(int technologies_mask, bool enable_lptd,
bool reader_mode, bool enable_host_routing ,bool enable_p2p, bool restart);
#endif
jmethodID gCachedNfcManagerNotifySeListenActivated;
jmethodID gCachedNfcManagerNotifySeListenDeactivated;
jmethodID gCachedNfcManagerNotifySeInitialized;
void doStartupConfig();
void startStopPolling(bool isStartPolling);
void startRfDiscovery(bool isStart);
bool isDiscoveryStarted();
} // namespace android
/*****************************************************************************
**
** private variables and functions
**
*****************************************************************************/
namespace android {
static jint sLastError = ERROR_BUFFER_TOO_SMALL;
static SyncEvent sNfaEnableEvent; // event for NFA_Enable()
static SyncEvent sNfaDisableEvent; // event for NFA_Disable()
static SyncEvent sNfaEnableDisablePollingEvent; // event for
// NFA_EnablePolling(),
// NFA_DisablePolling()
static SyncEvent sNfaSetConfigEvent; // event for Set_Config....
static SyncEvent sNfaGetConfigEvent; // event for Get_Config....
#if(NXP_EXTNS == TRUE)
static SyncEvent sNfaTransitConfigEvent; // event for NFA_SetTransitConfig()
#endif
static bool sIsNfaEnabled = false;
static bool sDiscoveryEnabled = false; // is polling or listening
static bool sPollingEnabled = false; // is polling for tag?
static bool sIsDisabling = false;
static bool sRfEnabled = false; // whether RF discovery is enabled
static bool sSeRfActive = false; // whether RF with SE is likely active
static bool sReaderModeEnabled =
false; // whether we're only reading tags, not allowing P2p/card emu
static bool sP2pEnabled = false;
static bool sP2pActive = false; // whether p2p was last active
static bool sAbortConnlessWait = false;
static jint sLfT3tMax = 0;
static bool sRoutingInitialized = false;
#define CONFIG_UPDATE_TECH_MASK (1 << 1)
#define DEFAULT_TECH_MASK \
(NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B | NFA_TECHNOLOGY_MASK_F | \
NFA_TECHNOLOGY_MASK_V | NFA_TECHNOLOGY_MASK_B_PRIME | \
NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE | \
NFA_TECHNOLOGY_MASK_KOVIO)
#define DEFAULT_DISCOVERY_DURATION 500
#define READER_MODE_DISCOVERY_DURATION 200
#if(NXP_EXTNS == TRUE)
#define DUAL_UICC_FEATURE_NOT_AVAILABLE 0xED;
#define STATUS_UNKNOWN_ERROR 0xEF;
enum { UICC_CONFIGURED, UICC_NOT_CONFIGURED };
typedef enum dual_uicc_error_states {
DUAL_UICC_ERROR_NFCC_BUSY = 0x02,
DUAL_UICC_ERROR_SELECT_FAILED,
DUAL_UICC_ERROR_NFC_TURNING_OFF,
DUAL_UICC_ERROR_INVALID_SLOT,
DUAL_UICC_ERROR_STATUS_UNKNOWN
} dual_uicc_error_state_t;
typedef enum {
FDSTATUS_SUCCESS = 0,
FDSTATUS_ERROR_NFC_IS_OFF,
FDSTATUS_ERROR_NFC_BUSY_IN_MPOS,
FDSTATUS_ERROR_UNKNOWN
} field_detect_status_t;
#endif
static void nfaConnectionCallback(uint8_t event, tNFA_CONN_EVT_DATA* eventData);
static void nfaDeviceManagementCallback(uint8_t event,
tNFA_DM_CBACK_DATA* eventData);
static bool isPeerToPeer(tNFA_ACTIVATED& activated);
static bool isListenMode(tNFA_ACTIVATED& activated);
#if (NXP_EXTNS==TRUE)
static void nfcManager_changeDiscoveryTech(JNIEnv* e, jobject o, jint pollTech, jint listenTech);
#endif
#if (NXP_EXTNS==FALSE)
static void enableDisableLptd(bool enable);
#endif
static tNFA_STATUS stopPolling_rfDiscoveryDisabled();
static tNFA_STATUS startPolling_rfDiscoveryDisabled(
tNFA_TECHNOLOGY_MASK tech_mask);
static void nfcManager_doSetScreenState(JNIEnv* e, jobject o,
jint screen_state_mask);
#if(NXP_EXTNS == TRUE)
static jint nfcManager_getFwVersion(JNIEnv* e, jobject o);
static jbyteArray nfcManager_readerPassThruMode(JNIEnv *e, jobject o,
jbyte rqst,
jbyte modulationTyp);
static jbyteArray nfcManager_transceiveAppData(JNIEnv *e, jobject o,
jbyteArray data);
static bool nfcManager_isNfccBusy(JNIEnv*, jobject);
static int nfcManager_setTransitConfig(JNIEnv* e, jobject o, jstring config);
static std::string ConvertJavaStrToStdString(JNIEnv * env, jstring s);
static jint nfcManager_getAidTableSize (JNIEnv*, jobject );
static jint nfcManager_getRemainingAidTableSize (JNIEnv* , jobject );
static int nfcManager_doSelectUicc(JNIEnv* e, jobject o, jint uiccSlot);
static int nfcManager_doGetSelectedUicc(JNIEnv* e, jobject o);
static int nfcManager_staticDualUicc_Precondition(int uiccSlot);
static int nfcManager_setPreferredSimSlot(JNIEnv* e, jobject o, jint uiccSlot);
#endif
static uint16_t sCurrentConfigLen;
static uint8_t sConfig[256];
static int NFA_SCREEN_POLLING_TAG_MASK = 0x10;
static bool gIsDtaEnabled = false;
#if (NXP_EXTNS==TRUE)
static bool gsNfaPartialEnabled = false;
#endif
#if (NXP_EXTNS==TRUE)
static int prevScreenState = NFA_SCREEN_STATE_UNKNOWN;
#else
static int prevScreenState = NFA_SCREEN_STATE_OFF_UNLOCKED;
#endif
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
bool nfc_debug_enabled;
namespace {
void initializeGlobalDebugEnabledFlag() {
nfc_debug_enabled =
(NfcConfig::getUnsigned(NAME_NFC_DEBUG_ENABLED, 1) != 0) ? true : false;
char valueStr[PROPERTY_VALUE_MAX] = {0};
int len = property_get("nfc.debug_enabled", valueStr, "");
if (len > 0) {
unsigned debug_enabled = 1;
// let Android property override .conf variable
sscanf(valueStr, "%u", &debug_enabled);
nfc_debug_enabled = (debug_enabled == 0) ? false : true;
}
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: level=%u", __func__, nfc_debug_enabled);
}
void initializeMfcReaderOption() {
legacy_mfc_reader =
(NfcConfig::getUnsigned(NAME_LEGACY_MIFARE_READER, 1) != 0) ? true : false;
DLOG_IF(INFO, nfc_debug_enabled)
<< __func__ <<": mifare reader option=" << legacy_mfc_reader;
}
} // namespace
/*******************************************************************************
**
** Function: getNative
**
** Description: Get native data
**
** Returns: Native data structure.
**
*******************************************************************************/
nfc_jni_native_data* getNative(JNIEnv* e, jobject o) {
static struct nfc_jni_native_data* sCachedNat = NULL;
if (e) {
sCachedNat = nfc_jni_get_nat(e, o);
}
return sCachedNat;
}
/*******************************************************************************
**
** Function: handleRfDiscoveryEvent
**
** Description: Handle RF-discovery events from the stack.
** discoveredDevice: Discovered device.
**
** Returns: None
**
*******************************************************************************/
static void handleRfDiscoveryEvent(tNFC_RESULT_DEVT* discoveredDevice) {
if (discoveredDevice->more == NCI_DISCOVER_NTF_MORE) {
#if(NXP_EXTNS == TRUE)
// there is more discovery notification coming
NfcTag::getInstance ().mNumDiscNtf++;
#endif
return;
}
#if(NXP_EXTNS == TRUE)
NfcTag::getInstance ().mNumDiscNtf++;
if(NfcTag::getInstance ().mNumDiscNtf > 1) {
NfcTag::getInstance().mIsMultiProtocolTag = true;
}
#endif
bool isP2p = NfcTag::getInstance().isP2pDiscovered();
if (!sReaderModeEnabled && isP2p) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Select peer device", __FUNCTION__);
NfcTag::getInstance().selectP2p();
}
else {
NfcTag::getInstance ().mNumDiscNtf--;
NfcTag::getInstance().selectFirstTag();
}
}
/*******************************************************************************
**
** Function: nfaConnectionCallback
**
** Description: Receive connection-related events from stack.
** connEvent: Event code.
** eventData: Event data.
**
** Returns: None
**
*******************************************************************************/
static void nfaConnectionCallback(uint8_t connEvent,
tNFA_CONN_EVT_DATA* eventData) {
tNFA_STATUS status = NFA_STATUS_FAILED;
#if (NXP_EXTNS == TRUE)
static uint8_t prev_more_val = 0x00;
uint8_t cur_more_val = 0x00;
#endif
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: event= %u", __func__, connEvent);
#if (NXP_EXTNS == TRUE)
NativeJniExtns::getInstance().notifyNfcEvent(
"nfaConnectionCallback", (void*)&connEvent, (void*)&eventData);
#endif
switch (connEvent) {
case NFA_POLL_ENABLED_EVT: // whether polling successfully started
{
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_POLL_ENABLED_EVT: status = %u", __func__, eventData->status);
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
sNfaEnableDisablePollingEvent.notifyOne();
} break;
case NFA_POLL_DISABLED_EVT: // Listening/Polling stopped
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_POLL_DISABLED_EVT: status = %u", __func__,
eventData->status);
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
sNfaEnableDisablePollingEvent.notifyOne();
} break;
case NFA_RF_DISCOVERY_STARTED_EVT: // RF Discovery started
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_RF_DISCOVERY_STARTED_EVT: status = %u",
__func__, eventData->status);
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
sNfaEnableDisablePollingEvent.notifyOne();
} break;
case NFA_RF_DISCOVERY_STOPPED_EVT: // RF Discovery stopped event
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_RF_DISCOVERY_STOPPED_EVT: status = %u",
__func__, eventData->status);
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
sNfaEnableDisablePollingEvent.notifyOne();
} break;
case NFA_DISC_RESULT_EVT: // NFC link/protocol discovery notificaiton
status = eventData->disc_result.status;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_DISC_RESULT_EVT: status = %d", __func__, status);
#if (NXP_EXTNS == TRUE)
cur_more_val = eventData->disc_result.discovery_ntf.more;
if((cur_more_val == 0x01) && (prev_more_val != 0x02)) {
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf(
"%s: NFA_DISC_RESULT_EVT: Failed", __func__);
status = NFA_STATUS_FAILED;
} else {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_DISC_RESULT_EVT: Success", __func__);
status = NFA_STATUS_OK;
prev_more_val = cur_more_val;
}
#endif
if (status != NFA_STATUS_OK) {
#if (NXP_EXTNS == TRUE)
NfcTag::getInstance ().mNumDiscNtf = 0;
#endif
LOG(ERROR) << StringPrintf("%s: NFA_DISC_RESULT_EVT error: status = %d",
__func__, status);
} else {
NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
handleRfDiscoveryEvent(&eventData->disc_result.discovery_ntf);
}
break;
case NFA_SELECT_RESULT_EVT: // NFC link/protocol discovery select response
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_SELECT_RESULT_EVT: status = %d, gIsSelectingRfInterface = "
"%d, "
"sIsDisabling=%d",
__func__, eventData->status, gIsSelectingRfInterface, sIsDisabling);
if (sIsDisabling) break;
if (eventData->status != NFA_STATUS_OK) {
if (gIsSelectingRfInterface) {
nativeNfcTag_doConnectStatus(false);
}
#if (NXP_EXTNS == TRUE)
NfcTag::getInstance().mTechListIndex = 0;
#endif
LOG(ERROR) << StringPrintf(
"%s: NFA_SELECT_RESULT_EVT error: status = %d", __func__,
eventData->status);
NFA_Deactivate(FALSE);
}
break;
case NFA_DEACTIVATE_FAIL_EVT:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_DEACTIVATE_FAIL_EVT: status = %d", __func__,
eventData->status);
break;
case NFA_ACTIVATED_EVT: // NFC link/protocol activated
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_ACTIVATED_EVT: gIsSelectingRfInterface=%d, sIsDisabling=%d",
__func__, gIsSelectingRfInterface, sIsDisabling);
#if (NXP_EXTNS == TRUE)
if(NFC_PROTOCOL_T5T == NfcTag::getInstance ().mTechLibNfcTypes[0x00]
&& NfcTag::getInstance ().mNumDiscNtf){
/* T5T doesn't support multiproto detection logic */
NfcTag::getInstance ().mNumDiscNtf = 0x00;
}
#endif
if ((eventData->activated.activate_ntf.protocol !=
NFA_PROTOCOL_NFC_DEP) &&
(!isListenMode(eventData->activated))) {
nativeNfcTag_setRfInterface(
(tNFA_INTF_TYPE)eventData->activated.activate_ntf.intf_param.type);
}
if (EXTNS_GetConnectFlag() == TRUE) {
NfcTag::getInstance().setActivationState();
nativeNfcTag_doConnectStatus(true);
break;
}
#if(NXP_EXTNS == TRUE)
if(nfcFL.nfcNxpEse) {
if(nfcFL.eseFL._ESE_ETSI_READER_ENABLE) {
/*
* Handle Reader over SWP START_READER_EVENT
* */
if(eventData->activated.activate_ntf.intf_param.type == NCI_INTERFACE_UICC_DIRECT ||
eventData->activated.activate_ntf.intf_param.type == NCI_INTERFACE_ESE_DIRECT)
{
MposManager::getInstance().setEtsiReaederState(STATE_SE_RDR_MODE_ACTIVATED);
MposManager::getInstance().notifyEEReaderEvent(ETSI_READER_ACTIVATED);
break;
}
}
}
#endif
NfcTag::getInstance().setActive(true);
if (sIsDisabling || !sIsNfaEnabled) break;
gActivated = true;
NfcTag::getInstance().setActivationState();
if (gIsSelectingRfInterface) {
nativeNfcTag_doConnectStatus(true);
break;
}
nativeNfcTag_resetPresenceCheck();
if (!isListenMode(eventData->activated) &&
(prevScreenState == NFA_SCREEN_STATE_OFF_LOCKED ||
prevScreenState == NFA_SCREEN_STATE_OFF_UNLOCKED)) {
NFA_Deactivate(FALSE);
}
if (isPeerToPeer(eventData->activated)) {
if (sReaderModeEnabled) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: ignoring peer target in reader mode.", __func__);
NFA_Deactivate(FALSE);
break;
}
sP2pActive = true;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_ACTIVATED_EVT; is p2p", __func__);
if (NFC_GetNCIVersion() == NCI_VERSION_1_0) {
// Disable RF field events in case of p2p
uint8_t nfa_disable_rf_events[] = {0x00};
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Disabling RF field events", __func__);
status = NFA_SetConfig(NCI_PARAM_ID_RF_FIELD_INFO,
sizeof(nfa_disable_rf_events),
&nfa_disable_rf_events[0]);
if (status == NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Disabled RF field events", __func__);
} else {
LOG(ERROR) << StringPrintf("%s: Failed to disable RF field events",
__func__);
}
}
} else if (pn544InteropIsBusy() == false) {
NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
#if (NXP_EXTNS == TRUE)
if(NfcTag::getInstance ().mNumDiscNtf) {
NFA_Deactivate (true);
}
#endif
// We know it is not activating for P2P. If it activated in
// listen mode then it is likely for an SE transaction.
// Send the RF Event.
if (isListenMode(eventData->activated)) {
#if(NXP_EXTNS == TRUE)
SecureElement::getInstance().notifyListenModeState (true);
#endif
sSeRfActive = true;
}
}
break;
case NFA_DEACTIVATED_EVT: // NFC link/protocol deactivated
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_DEACTIVATED_EVT Type: %u, gIsTagDeactivating: %d",
__func__, eventData->deactivated.type, gIsTagDeactivating);
#if (NXP_EXTNS == TRUE)
if(gIsWaiting4Deact2SleepNtf) {
if(eventData->deactivated.type == NFA_DEACTIVATE_TYPE_IDLE) {
gGotDeact2IdleNtf = true;
} else if(eventData->deactivated.type == NFA_DEACTIVATE_TYPE_SLEEP) {
gIsWaiting4Deact2SleepNtf = false;
}
}
#endif
NfcTag::getInstance().setDeactivationState(eventData->deactivated);
#if (NXP_EXTNS == TRUE)
if(NfcTag::getInstance ().mNumDiscNtf) {
NfcTag::getInstance ().mNumDiscNtf--;
NfcTag::getInstance().selectNextTag();
}
#endif
if (eventData->deactivated.type != NFA_DEACTIVATE_TYPE_SLEEP) {
{
SyncEventGuard g(gDeactivatedEvent);
gActivated = false; // guard this variable from multi-threaded access
gDeactivatedEvent.notifyOne();
}
#if (NXP_EXTNS == TRUE)
NfcTag::getInstance ().mNumDiscNtf = 0;
NfcTag::getInstance ().mTechListIndex =0;
#endif
nativeNfcTag_resetPresenceCheck();
#if (NXP_EXTNS == TRUE)
if (gIsSelectingRfInterface == false) {
NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
nativeNfcTag_abortWaits();
}
#else
NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
nativeNfcTag_abortWaits();
#endif
NfcTag::getInstance().abort();
#if (NXP_EXTNS == TRUE)
NfcTag::getInstance().mIsMultiProtocolTag = false;
#endif
} else if (gIsTagDeactivating) {
NfcTag::getInstance().setActive(false);
nativeNfcTag_doDeactivateStatus(0);
} else if (EXTNS_GetDeactivateFlag() == TRUE) {
NfcTag::getInstance().setActive(false);
nativeNfcTag_doDeactivateStatus(0);
}
// If RF is activated for what we think is a Secure Element transaction
// and it is deactivated to either IDLE or DISCOVERY mode, notify w/event.
if ((eventData->deactivated.type == NFA_DEACTIVATE_TYPE_IDLE) ||
(eventData->deactivated.type == NFA_DEACTIVATE_TYPE_DISCOVERY)) {
if (sSeRfActive) {
sSeRfActive = false;
#if(NXP_EXTNS == TRUE)
SecureElement::getInstance().notifyListenModeState (false);
#endif
} else if (sP2pActive) {
sP2pActive = false;
// Make sure RF field events are re-enabled
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_DEACTIVATED_EVT; is p2p", __func__);
if (NFC_GetNCIVersion() == NCI_VERSION_1_0) {
// Disable RF field events in case of p2p
uint8_t nfa_enable_rf_events[] = {0x01};
if (!sIsDisabling && sIsNfaEnabled) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Enabling RF field events", __func__);
status = NFA_SetConfig(NCI_PARAM_ID_RF_FIELD_INFO,
sizeof(nfa_enable_rf_events),
&nfa_enable_rf_events[0]);
if (status == NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Enabled RF field events", __func__);
} else {
LOG(ERROR) << StringPrintf(
"%s: Failed to enable RF field events", __func__);
}
}
}
}
}
break;
case NFA_TLV_DETECT_EVT: // TLV Detection complete
status = eventData->tlv_detect.status;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_TLV_DETECT_EVT: status = %d, protocol = %d, num_tlvs = %d, "
"num_bytes = %d",
__func__, status, eventData->tlv_detect.protocol,
eventData->tlv_detect.num_tlvs, eventData->tlv_detect.num_bytes);
if (status != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: NFA_TLV_DETECT_EVT error: status = %d",
__func__, status);
}
break;
case NFA_NDEF_DETECT_EVT: // NDEF Detection complete;
// if status is failure, it means the tag does not contain any or valid
// NDEF data; pass the failure status to the NFC Service;
status = eventData->ndef_detect.status;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_NDEF_DETECT_EVT: status = 0x%X, protocol = %u, "
"max_size = %u, cur_size = %u, flags = 0x%X",
__func__, status, eventData->ndef_detect.protocol,
eventData->ndef_detect.max_size, eventData->ndef_detect.cur_size,
eventData->ndef_detect.flags);
NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
nativeNfcTag_doCheckNdefResult(status, eventData->ndef_detect.max_size,
eventData->ndef_detect.cur_size,
eventData->ndef_detect.flags);
break;
case NFA_DATA_EVT: // Data message received (for non-NDEF reads)
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_DATA_EVT: status = 0x%X, len = %d", __func__,
eventData->status, eventData->data.len);
nativeNfcTag_doTransceiveStatus(eventData->status, eventData->data.p_data,
eventData->data.len);
break;
case NFA_RW_INTF_ERROR_EVT:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFC_RW_INTF_ERROR_EVT", __func__);
nativeNfcTag_notifyRfTimeout();
nativeNfcTag_doReadCompleted(NFA_STATUS_TIMEOUT);
break;
case NFA_SELECT_CPLT_EVT: // Select completed
status = eventData->status;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_SELECT_CPLT_EVT: status = %d", __func__, status);
if (status != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: NFA_SELECT_CPLT_EVT error: status = %d",
__func__, status);
}
break;
case NFA_READ_CPLT_EVT: // NDEF-read or tag-specific-read completed
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_READ_CPLT_EVT: status = 0x%X", __func__, eventData->status);
nativeNfcTag_doReadCompleted(eventData->status);
NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
break;
case NFA_WRITE_CPLT_EVT: // Write completed
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_WRITE_CPLT_EVT: status = %d", __func__, eventData->status);
nativeNfcTag_doWriteStatus(eventData->status == NFA_STATUS_OK);
break;
case NFA_SET_TAG_RO_EVT: // Tag set as Read only
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_SET_TAG_RO_EVT: status = %d", __func__, eventData->status);
nativeNfcTag_doMakeReadonlyResult(eventData->status);
break;
case NFA_CE_NDEF_WRITE_START_EVT: // NDEF write started
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_CE_NDEF_WRITE_START_EVT: status: %d",
__func__, eventData->status);
if (eventData->status != NFA_STATUS_OK)
LOG(ERROR) << StringPrintf(
"%s: NFA_CE_NDEF_WRITE_START_EVT error: status = %d", __func__,
eventData->status);
break;
case NFA_CE_NDEF_WRITE_CPLT_EVT: // NDEF write completed
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: FA_CE_NDEF_WRITE_CPLT_EVT: len = %u", __func__,
eventData->ndef_write_cplt.len);
break;
case NFA_LLCP_ACTIVATED_EVT: // LLCP link is activated
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_LLCP_ACTIVATED_EVT: is_initiator: %d remote_wks: %d, "
"remote_lsc: %d, remote_link_miu: %d, local_link_miu: %d",
__func__, eventData->llcp_activated.is_initiator,
eventData->llcp_activated.remote_wks,
eventData->llcp_activated.remote_lsc,
eventData->llcp_activated.remote_link_miu,
eventData->llcp_activated.local_link_miu);
PeerToPeer::getInstance().llcpActivatedHandler(getNative(0, 0),
eventData->llcp_activated);
break;
case NFA_LLCP_DEACTIVATED_EVT: // LLCP link is deactivated
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_LLCP_DEACTIVATED_EVT", __func__);
PeerToPeer::getInstance().llcpDeactivatedHandler(
getNative(0, 0), eventData->llcp_deactivated);
break;
case NFA_LLCP_FIRST_PACKET_RECEIVED_EVT: // Received first packet over llcp
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_LLCP_FIRST_PACKET_RECEIVED_EVT", __func__);
PeerToPeer::getInstance().llcpFirstPacketHandler(getNative(0, 0));
break;
case NFA_PRESENCE_CHECK_EVT:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_PRESENCE_CHECK_EVT", __func__);
nativeNfcTag_doPresenceCheckResult(eventData->status);
break;
case NFA_FORMAT_CPLT_EVT:
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_FORMAT_CPLT_EVT: status=0x%X", __func__, eventData->status);
nativeNfcTag_formatStatus(eventData->status == NFA_STATUS_OK);
break;
case NFA_I93_CMD_CPLT_EVT:
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_I93_CMD_CPLT_EVT: status=0x%X", __func__, eventData->status);
break;
case NFA_CE_UICC_LISTEN_CONFIGURED_EVT:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_CE_UICC_LISTEN_CONFIGURED_EVT : status=0x%X",
__func__, eventData->status);
break;
#if (NXP_EXTNS == TRUE)
case NFA_LISTEN_ENABLED_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_LISTEN_ENABLED_EVT : status=0x%X", __func__,
eventData->status);
SyncEventGuard guard(sChangeDiscTechEvent);
sChangeDiscTechEvent.notifyOne();
break;
}
#endif
case NFA_SET_P2P_LISTEN_TECH_EVT:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_SET_P2P_LISTEN_TECH_EVT", __func__);
PeerToPeer::getInstance().connectionEventHandler(connEvent, eventData);
break;
default:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: unknown event ????", __func__);
break;
}
}
/*******************************************************************************
**
** Function: nfcManager_initNativeStruc
**
** Description: Initialize variables.
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_initNativeStruc(JNIEnv* e, jobject o) {
initializeGlobalDebugEnabledFlag();
initializeMfcReaderOption();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
nfc_jni_native_data* nat =
(nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data));
if (nat == NULL) {
LOG(ERROR) << StringPrintf("%s: fail allocate native data", __func__);
return JNI_FALSE;
}
memset(nat, 0, sizeof(*nat));
e->GetJavaVM(&(nat->vm));
nat->env_version = e->GetVersion();
nat->manager = e->NewGlobalRef(o);
ScopedLocalRef<jclass> cls(e, e->GetObjectClass(o));
jfieldID f = e->GetFieldID(cls.get(), "mNative", "J");
e->SetLongField(o, f, (jlong)nat);
#if(NXP_EXTNS == TRUE)
MposManager::initMposNativeStruct(e, o);
#endif
/* Initialize native cached references */
gCachedNfcManagerNotifyNdefMessageListeners =
e->GetMethodID(cls.get(), "notifyNdefMessageListeners",
"(Lcom/android/nfc/dhimpl/NativeNfcTag;)V");
gCachedNfcManagerNotifyLlcpLinkActivation =
e->GetMethodID(cls.get(), "notifyLlcpLinkActivation",
"(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
gCachedNfcManagerNotifyLlcpLinkDeactivated =
e->GetMethodID(cls.get(), "notifyLlcpLinkDeactivated",
"(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
gCachedNfcManagerNotifyLlcpFirstPacketReceived =
e->GetMethodID(cls.get(), "notifyLlcpLinkFirstPacketReceived",
"(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
gCachedNfcManagerNotifyHostEmuActivated =
e->GetMethodID(cls.get(), "notifyHostEmuActivated", "(I)V");
gCachedNfcManagerNotifyHostEmuData =
e->GetMethodID(cls.get(), "notifyHostEmuData", "(I[B)V");
gCachedNfcManagerNotifyHostEmuDeactivated =
e->GetMethodID(cls.get(), "notifyHostEmuDeactivated", "(I)V");
gCachedNfcManagerNotifyRfFieldActivated =
e->GetMethodID(cls.get(), "notifyRfFieldActivated", "()V");
gCachedNfcManagerNotifyRfFieldDeactivated =
e->GetMethodID(cls.get(), "notifyRfFieldDeactivated", "()V");
gCachedNfcManagerNotifySeListenActivated =
e->GetMethodID(cls.get(),"notifySeListenActivated", "()V");
gCachedNfcManagerNotifySeListenDeactivated =
e->GetMethodID(cls.get(),"notifySeListenDeactivated", "()V");
gCachedNfcManagerNotifyTransactionListeners = e->GetMethodID(
cls.get(), "notifyTransactionListeners", "([B[BLjava/lang/String;)V");
gCachedNfcManagerNotifySeInitialized =
e->GetMethodID(cls.get(),"notifySeInitialized", "()V");
if (nfc_jni_cache_object(e, gNativeNfcTagClassName, &(nat->cached_NfcTag)) ==
-1) {
LOG(ERROR) << StringPrintf("%s: fail cache NativeNfcTag", __func__);
return JNI_FALSE;
}
if (nfc_jni_cache_object(e, gNativeP2pDeviceClassName,
&(nat->cached_P2pDevice)) == -1) {
LOG(ERROR) << StringPrintf("%s: fail cache NativeP2pDevice", __func__);
return JNI_FALSE;
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return JNI_TRUE;
}
/*******************************************************************************
**
** Function: nfaDeviceManagementCallback
**
** Description: Receive device management events from stack.
** dmEvent: Device-management event ID.
** eventData: Data associated with event ID.
**
** Returns: None
**
*******************************************************************************/
void nfaDeviceManagementCallback(uint8_t dmEvent,
tNFA_DM_CBACK_DATA* eventData) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter; event=0x%X", __func__, dmEvent);
switch (dmEvent) {
case NFA_DM_ENABLE_EVT: /* Result of NFA_Enable */
{
SyncEventGuard guard(sNfaEnableEvent);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_DM_ENABLE_EVT; status=0x%X", __func__, eventData->status);
sIsNfaEnabled = eventData->status == NFA_STATUS_OK;
sIsDisabling = false;
sNfaEnableEvent.notifyOne();
} break;
case NFA_DM_DISABLE_EVT: /* Result of NFA_Disable */
{
SyncEventGuard guard(sNfaDisableEvent);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_DM_DISABLE_EVT", __func__);
sIsNfaEnabled = false;
sIsDisabling = false;
sNfaDisableEvent.notifyOne();
} break;
case NFA_DM_SET_CONFIG_EVT: // result of NFA_SetConfig
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_DM_SET_CONFIG_EVT", __func__);
{
SyncEventGuard guard(sNfaSetConfigEvent);
sNfaSetConfigEvent.notifyOne();
}
break;
case NFA_DM_GET_CONFIG_EVT: /* Result of NFA_GetConfig */
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_DM_GET_CONFIG_EVT", __func__);
{
SyncEventGuard guard(sNfaGetConfigEvent);
if (eventData->status == NFA_STATUS_OK &&
eventData->get_config.tlv_size <= sizeof(sConfig)) {
sCurrentConfigLen = eventData->get_config.tlv_size;
memcpy(sConfig, eventData->get_config.param_tlvs,
eventData->get_config.tlv_size);
} else {
LOG(ERROR) << StringPrintf("%s: NFA_DM_GET_CONFIG failed", __func__);
sCurrentConfigLen = 0;
}
sNfaGetConfigEvent.notifyOne();
}
break;
case NFA_DM_RF_FIELD_EVT:
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: NFA_DM_RF_FIELD_EVT; status=0x%X; field status=%u", __func__,
eventData->rf_field.status, eventData->rf_field.rf_field_status);
#if(NXP_EXTNS == TRUE)
SecureElement::getInstance().notifyRfFieldEvent (
eventData->rf_field.rf_field_status == NFA_DM_RF_FIELD_ON);
#endif
if (!sP2pActive && eventData->rf_field.status == NFA_STATUS_OK) {
struct nfc_jni_native_data* nat = getNative(NULL, NULL);
JNIEnv* e = NULL;
ScopedAttach attach(nat->vm, &e);
if (e == NULL) {
LOG(ERROR) << StringPrintf("jni env is null");
return;
}
if (eventData->rf_field.rf_field_status == NFA_DM_RF_FIELD_ON)
e->CallVoidMethod(nat->manager,
android::gCachedNfcManagerNotifyRfFieldActivated);
else
e->CallVoidMethod(nat->manager,
android::gCachedNfcManagerNotifyRfFieldDeactivated);
}
break;
case NFA_DM_NFCC_TRANSPORT_ERR_EVT:
case NFA_DM_NFCC_TIMEOUT_EVT: {
if (dmEvent == NFA_DM_NFCC_TIMEOUT_EVT)
LOG(ERROR) << StringPrintf("%s: NFA_DM_NFCC_TIMEOUT_EVT; abort",
__func__);
else if (dmEvent == NFA_DM_NFCC_TRANSPORT_ERR_EVT)
LOG(ERROR) << StringPrintf("%s: NFA_DM_NFCC_TRANSPORT_ERR_EVT; abort",
__func__);
nativeNfcTag_abortWaits();
NfcTag::getInstance().abort();
sAbortConnlessWait = true;
nativeLlcpConnectionlessSocket_abortWait();
{
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: aborting sNfaEnableDisablePollingEvent", __func__);
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
sNfaEnableDisablePollingEvent.notifyOne();
}
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: aborting sNfaEnableEvent", __func__);
SyncEventGuard guard(sNfaEnableEvent);
sNfaEnableEvent.notifyOne();
}
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: aborting sNfaDisableEvent", __func__);
SyncEventGuard guard(sNfaDisableEvent);
sNfaDisableEvent.notifyOne();
}
sDiscoveryEnabled = false;
sPollingEnabled = false;
PowerSwitch::getInstance().abort();
if (!sIsDisabling && sIsNfaEnabled) {
EXTNS_Close();
NFA_Disable(FALSE);
sIsDisabling = true;
} else {
sIsNfaEnabled = false;
sIsDisabling = false;
}
PowerSwitch::getInstance().initialize(PowerSwitch::UNKNOWN_LEVEL);
LOG(ERROR) << StringPrintf("%s: crash NFC service", __func__);
//////////////////////////////////////////////
// crash the NFC service process so it can restart automatically
abort();
//////////////////////////////////////////////
} break;
case NFA_DM_PWR_MODE_CHANGE_EVT:
PowerSwitch::getInstance().deviceManagementCallback(dmEvent, eventData);
break;
#if(NXP_EXTNS == TRUE)
case NFA_DM_SET_TRANSIT_CONFIG_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("NFA_DM_SET_TRANSIT_CONFIG EVT cback received");
SyncEventGuard guard(sNfaTransitConfigEvent);
sNfaTransitConfigEvent.notifyOne();
break;
}
case NFA_DM_GET_ROUTE_CONFIG_REVT: {
RoutingManager::getInstance().processGetRoutingRsp(eventData);
break;
}
#endif
case NFA_DM_SET_POWER_SUB_STATE_EVT: {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: NFA_DM_SET_POWER_SUB_STATE_EVT; status=0x%X",
__FUNCTION__, eventData->power_sub_state.status);
SyncEventGuard guard(sNfaSetPowerSubState);
sNfaSetPowerSubState.notifyOne();
} break;
default:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: unhandled event", __func__);
break;
}
}
#if(NXP_EXTNS == TRUE)
static jintArray nfcManager_getActiveSecureElementList(JNIEnv *e, jobject o)
{
(void)e;
(void)o;
return SecureElement::getInstance().getActiveSecureElementList(e);
}
#endif
/*******************************************************************************
**
** Function: nfcManager_sendRawFrame
**
** Description: Send a raw frame.
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_sendRawFrame(JNIEnv* e, jobject, jbyteArray data) {
#if (NXP_EXTNS == TRUE)
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: nfcManager_sendRawFrame", __func__);
size_t bufLen;
uint8_t* buf = NULL;
if (data !=NULL) {
ScopedByteArrayRO bytes(e, data);
buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
bufLen = bytes.size();
} else {
/*Fix for Felica on Host for Empty NCI packet handling*/
bufLen = 0x00;
}
#else
ScopedByteArrayRO bytes(e, data);
uint8_t* buf =
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
size_t bufLen = bytes.size();
#endif
tNFA_STATUS status = NFA_SendRawFrame(buf, bufLen, 0);
return (status == NFA_STATUS_OK);
}
#if(NXP_EXTNS == TRUE)
/*******************************************************************************
**
** Function: nfcManager_setRoutingEntry
**
** Description: Set the routing entry in routing table
** e: JVM environment.
** o: Java object.
** type: technology or protocol routing
** 0x01 - Technology
** 0x02 - Protocol
** value: technology /protocol value
** route: routing destination
** 0x00 : Device Host
** 0x01 : ESE
** 0x02 : UICC
** power: power state for the routing entry
*******************************************************************************/
static jboolean nfcManager_setRoutingEntry (JNIEnv*, jobject, jint type, jint value, jint route, jint power)
{
jboolean result = false;
result = RoutingManager::getInstance().setRoutingEntry(type, value, route, power);
return result;
}
/*******************************************************************************
**
** Function: nfcManager_clearRoutingEntry
**
** Description: Set the routing entry in routing table
** e: JVM environment.
** o: Java object.
** type:technology/protocol/aid clear routing
**
*******************************************************************************/
static jboolean nfcManager_clearRoutingEntry (JNIEnv*, jobject, jint type)
{
jboolean result = false;
//checkRecreatePipe(); TODO
result = RoutingManager::getInstance().clearRoutingEntry(type);
return result;
}
/*******************************************************************************
**
** Function: nfcManager_clearRoutingEntry
**
** Description: Set the routing entry in routing table
** e: JVM environment.
** o: Java object.
** type:technology/protocol/aid clear routing
**
*******************************************************************************/
static void nfcManager_setEmptyAidRoute (JNIEnv*, jobject, jint route)
{
RoutingManager::getInstance().setEmptyAidEntry(route);
return;
}
/*******************************************************************************
**
** Function: nfcFwUpdateStatusCallback
**
** Description: This callback shall be registered to libnfc-nci by
** nfcManager_doDownload
**
** Params: status: 1 -> FW update start, 2 -> FW update success,
** 3 -> FW update failed.
** Returns: void.
**
*******************************************************************************/
static void nfcFwUpdateStatusCallback(uint8_t status) {
LOG(INFO) << StringPrintf("nfcFwUpdateStatusCallback Enter status = %u", status);
NativeJniExtns::getInstance().notifyNfcEvent("nfcFwDwnldStatus", (void *)&status);
}
#endif
/*******************************************************************************
**
** Function: nfcManager_routeAid
**
** Description: Route an AID to an EE
** e: JVM environment.
** aid: aid to be added to routing table.
** route: aid route location. i.e. DH/eSE/UICC
** aidInfo: prefix or suffix aid.
**
** Returns: True if aid is accpted by NFA Layer.
**
*******************************************************************************/
#if (NXP_EXTNS == TRUE)
static jboolean nfcManager_routeAid(JNIEnv* e, jobject, jbyteArray aid,
jint route, jint aidInfo, jint power) {
#else
static jboolean nfcManager_routeAid(JNIEnv* e, jobject, jbyteArray aid,
jint route, jint aidInfo) {
#endif
uint8_t* buf;
size_t bufLen;
ScopedByteArrayRO bytes(e);
if (aid == NULL) {
buf = NULL;
bufLen = 0;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("nfcManager_routeAid: NULL");
} else {
bytes.reset(aid);
buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
bufLen = bytes.size();
}
#if (NXP_EXTNS == TRUE)
SecureElement& se = SecureElement::getInstance();
if ((!isDynamicUiccEnabled) &&
(route == se.UICC_ID || route == se.UICC2_ID)) { // UICC or UICC2 HANDLE
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("sCurrentSelectedUICCSlot: %d ::: route: %d",
sCurrentSelectedUICCSlot, route);
/* If current slot is 0x01 and UICC_ID is 0x02 then route location should be
* updated to UICC_ID(0x02) else if current slot is 0x02 and UICC_ID is 0x02
* then route location should be updated to UICC_ID2(0x04).
*/
route = (sCurrentSelectedUICCSlot != se.UICC_ID) ? se.UICC_ID : se.UICC2_ID;
}
return RoutingManager::getInstance().addAidRouting(buf, bufLen, route,
aidInfo, power);
#else
return RoutingManager::getInstance().addAidRouting(buf, bufLen, route,
aidInfo);
#endif
}
/*******************************************************************************
**
** Function: nfcManager_unrouteAid
**
** Description: Remove a AID routing
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_unrouteAid(JNIEnv* e, jobject, jbyteArray aid) {
uint8_t* buf;
size_t bufLen;
if (aid == NULL) {
buf = NULL;
bufLen = 0;
} else {
ScopedByteArrayRO bytes(e, aid);
buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
bufLen = bytes.size();
}
bool result = RoutingManager::getInstance().removeAidRouting(buf, bufLen);
return result;
}
/*******************************************************************************
**
** Function: nfcManager_commitRouting
**
** Description: Sends the AID routing table to the controller
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_commitRouting(JNIEnv* e, jobject) {
#if (NXP_EXTNS == TRUE)
bool status = false;
SecureElement& se = SecureElement::getInstance();
if (se.isRfFieldOn() || se.mActivatedInListenMode) {
/* Delay is required to avoid update routing during RF Field session*/
usleep(1000 * 1000);
}
if (sIsDisabling || !sIsNfaEnabled) {
return status;
}
if (sRfEnabled) {
/*Stop RF discovery to reconfigure*/
startRfDiscovery(false);
}
NativeJniExtns::getInstance().notifyNfcEvent(__func__);
LOG(ERROR) << StringPrintf("commitRouting here");
status = RoutingManager::getInstance().commitRouting();
NativeJniExtns::getInstance().notifyNfcEvent("checkIsodepRouting");
if (!sRfEnabled) {
/*Stop RF discovery to reconfigure*/
startRfDiscovery(true);
}
return status;
#else
return RoutingManager::getInstance().commitRouting();
#endif
}
/*******************************************************************************
**
** Function: nfcManager_doRegisterT3tIdentifier
**
** Description: Registers LF_T3T_IDENTIFIER for NFC-F.
** e: JVM environment.
** o: Java object.
** t3tIdentifier: LF_T3T_IDENTIFIER value (10 or 18 bytes)
**
** Returns: Handle retrieve from RoutingManager.
**
*******************************************************************************/
static jint nfcManager_doRegisterT3tIdentifier(JNIEnv* e, jobject,
jbyteArray t3tIdentifier) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
ScopedByteArrayRO bytes(e, t3tIdentifier);
uint8_t* buf =
const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
size_t bufLen = bytes.size();
int handle = RoutingManager::getInstance().registerT3tIdentifier(buf, bufLen);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: handle=%d", __func__, handle);
if (handle != NFA_HANDLE_INVALID)
RoutingManager::getInstance().commitRouting();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return handle;
}
/*******************************************************************************
**
** Function: nfcManager_doDeregisterT3tIdentifier
**
** Description: Deregisters LF_T3T_IDENTIFIER for NFC-F.
** e: JVM environment.
** o: Java object.
** handle: Handle retrieve from libnfc-nci.
**
** Returns: None
**
*******************************************************************************/
static void nfcManager_doDeregisterT3tIdentifier(JNIEnv*, jobject,
jint handle) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter; handle=%d", __func__, handle);
RoutingManager::getInstance().deregisterT3tIdentifier(handle);
RoutingManager::getInstance().commitRouting();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
}
/*******************************************************************************
**
** Function: nfcManager_getLfT3tMax
**
** Description: Returns LF_T3T_MAX value.
** e: JVM environment.
** o: Java object.
**
** Returns: LF_T3T_MAX value.
**
*******************************************************************************/
static jint nfcManager_getLfT3tMax(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("LF_T3T_MAX=%d", sLfT3tMax);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return sLfT3tMax;
}
/*******************************************************************************
**
** Function: nfcManager_doInitialize
**
** Description: Turn on NFC.
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_doInitialize(JNIEnv* e, jobject o) {
#if (NXP_EXTNS == TRUE)
tNFA_MW_VERSION mwVer;
#endif
initializeGlobalDebugEnabledFlag();
tNFA_STATUS stat = NFA_STATUS_OK;
PowerSwitch& powerSwitch = PowerSwitch::getInstance();
if (sIsNfaEnabled) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: already enabled", __func__);
goto TheEnd;
}
#if (NXP_EXTNS == TRUE)
mwVer= NFA_GetMwVersion();
LOG(ERROR) << StringPrintf(
"%s: MW Version: NFC_AR_%02X_%04X_%02d.%02x.%02x_RC%0x", __func__,
mwVer.cust_id, mwVer.validation, mwVer.android_version,
mwVer.major_version, mwVer.minor_version,mwVer.rc_version);
if (NfcConfig::hasKey(NAME_NXP_DUAL_UICC_ENABLE)) {
isDynamicUiccEnabled = NfcConfig::getUnsigned(NAME_NXP_DUAL_UICC_ENABLE);
isDynamicUiccEnabled = (isDynamicUiccEnabled == 0x01 ? true : false);
} else
isDynamicUiccEnabled = true;
#endif
powerSwitch.initialize(PowerSwitch::FULL_POWER);
{
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.Initialize(); // start GKI, NCI task, NFC task
{
SyncEventGuard guard(sNfaEnableEvent);
tHAL_NFC_ENTRY* halFuncEntries = theInstance.GetHalEntryFuncs();
NFA_Init(halFuncEntries);
#if (NXP_EXTNS == TRUE)
NativeJniExtns::getInstance().initializeNativeData(getNative(e, o));
stat = theInstance.DownloadFirmware(nfcFwUpdateStatusCallback, true);
#endif
stat = NFA_Enable(nfaDeviceManagementCallback, nfaConnectionCallback);
if (stat == NFA_STATUS_OK) {
sNfaEnableEvent.wait(); // wait for NFA command to finish
}
EXTNS_Init(nfaDeviceManagementCallback, nfaConnectionCallback);
}
if (stat == NFA_STATUS_OK) {
// sIsNfaEnabled indicates whether stack started successfully
if (sIsNfaEnabled) {
#if (NXP_EXTNS == TRUE)
SecureElement::getInstance().initialize (getNative(e, o));
#endif
sRoutingInitialized =
RoutingManager::getInstance().initialize(getNative(e, o));
nativeNfcTag_registerNdefTypeHandler();
NfcTag::getInstance().initialize(getNative(e, o));
PeerToPeer::getInstance().initialize();
PeerToPeer::getInstance().handleNfcOnOff(true);
HciEventManager::getInstance().initialize(getNative(e, o));
#if(NXP_EXTNS == TRUE)
MposManager::getInstance().initialize(getNative(e, o));
#endif
/////////////////////////////////////////////////////////////////////////////////
// Add extra configuration here (work-arounds, etc.)
if (gIsDtaEnabled == true) {
uint8_t configData = 0;
configData = 0x01; /* Poll NFC-DEP : Highest Available Bit Rates */
NFA_SetConfig(NCI_PARAM_ID_BITR_NFC_DEP, sizeof(uint8_t),
&configData);
configData = 0x0B; /* Listen NFC-DEP : Waiting Time */
NFA_SetConfig(NFC_PMID_WT, sizeof(uint8_t), &configData);
configData = 0x0F; /* Specific Parameters for NFC-DEP RF Interface */
NFA_SetConfig(NCI_PARAM_ID_NFC_DEP_OP, sizeof(uint8_t), &configData);
}
struct nfc_jni_native_data* nat = getNative(e, o);
if (nat) {
nat->tech_mask =
NfcConfig::getUnsigned(NAME_POLLING_TECH_MASK, DEFAULT_TECH_MASK);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: tag polling tech mask=0x%X", __func__, nat->tech_mask);
}
// if this value exists, set polling interval.
nat->discovery_duration = NfcConfig::getUnsigned(
NAME_NFA_DM_DISC_DURATION_POLL, DEFAULT_DISCOVERY_DURATION);
NFA_SetRfDiscoveryDuration(nat->discovery_duration);
// get LF_T3T_MAX
{
SyncEventGuard guard(sNfaGetConfigEvent);
tNFA_PMID configParam[1] = {NCI_PARAM_ID_LF_T3T_MAX};
stat = NFA_GetConfig(1, configParam);
if (stat == NFA_STATUS_OK) {
sNfaGetConfigEvent.wait();
if (sCurrentConfigLen >= 4 ||
sConfig[1] == NCI_PARAM_ID_LF_T3T_MAX) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: lfT3tMax=%d", __func__, sConfig[3]);
sLfT3tMax = sConfig[3];
}
}
}
#if (NXP_EXTNS==TRUE)
prevScreenState = NFA_SCREEN_STATE_UNKNOWN;
#else
prevScreenState = NFA_SCREEN_STATE_OFF_LOCKED;
#endif
// Do custom NFCA startup configuration.
doStartupConfig();
goto TheEnd;
}
}
LOG(ERROR) << StringPrintf("%s: fail nfa enable; error=0x%X", __func__,
stat);
if (sIsNfaEnabled) {
EXTNS_Close();
stat = NFA_Disable(FALSE /* ungraceful */);
}
theInstance.Finalize();
}
TheEnd:
if (sIsNfaEnabled)
PowerSwitch::getInstance().setLevel(PowerSwitch::LOW_POWER);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return sIsNfaEnabled ? JNI_TRUE : JNI_FALSE;
}
static void nfcManager_doEnableDtaMode(JNIEnv*, jobject) {
gIsDtaEnabled = true;
}
static void nfcManager_doDisableDtaMode(JNIEnv*, jobject) {
gIsDtaEnabled = false;
}
static void nfcManager_doFactoryReset(JNIEnv*, jobject) {
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.FactoryReset();
}
static void nfcManager_doShutdown(JNIEnv*, jobject) {
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
#if (NXP_EXTNS == TRUE)
handleWiredmode(true); /* Device off*/
#endif
theInstance.DeviceShutdown();
}
/*******************************************************************************
**
** Function: nfcManager_enableDiscovery
**
** Description: Start polling and listening for devices.
** e: JVM environment.
** o: Java object.
** technologies_mask: the bitmask of technologies for which to
*enable discovery
** enable_lptd: whether to enable low power polling (default:
*false)
**
** Returns: None
**
*******************************************************************************/
static void nfcManager_enableDiscovery(JNIEnv* e, jobject o,
jint technologies_mask,
jboolean enable_lptd,
jboolean reader_mode,
jboolean enable_host_routing,
jboolean enable_p2p, jboolean restart) {
tNFA_TECHNOLOGY_MASK tech_mask = DEFAULT_TECH_MASK;
struct nfc_jni_native_data* nat = getNative(e, o);
#if(NXP_EXTNS == TRUE)
storeLastDiscoveryParams(technologies_mask, enable_lptd,
reader_mode, enable_host_routing ,enable_p2p, restart);
tNFA_STATUS status = NFA_STATUS_OK;
tNFA_TECHNOLOGY_MASK etsi_tech_mask = 0;
if((nfcFL.nfcNxpEse && nfcFL.eseFL._ESE_ETSI_READER_ENABLE) &&
(MposManager::getInstance().getEtsiReaederState() == STATE_SE_RDR_MODE_STARTED)) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter STATE_SE_RDR_MODE_START_CONFIG", __func__);
Rdr_req_ntf_info_t mSwp_info = MposManager::getInstance().getSwpRrdReqInfo();
{
SyncEventGuard guard (android::sNfaEnableDisablePollingEvent);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: disable polling", __func__);
status = NFA_DisablePolling ();
if (status == NFA_STATUS_OK)
{
android::sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_DISABLED_EVT
}
else
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: fail disable polling; error=0x%X", __func__, status);
}
}
if(mSwp_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_A)
etsi_tech_mask |= NFA_TECHNOLOGY_MASK_A;
if(mSwp_info.swp_rd_req_info.tech_mask & NFA_TECHNOLOGY_MASK_B)
etsi_tech_mask |= NFA_TECHNOLOGY_MASK_B;
{
SyncEventGuard guard (android::sNfaEnableDisablePollingEvent);
status = NFA_EnablePolling (etsi_tech_mask);
if (status == NFA_STATUS_OK)
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: wait for enable event", __func__);
android::sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_ENABLED_EVT
}
else
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: fail enable polling; error=0x%X", __func__, status);
}
}
startRfDiscovery (true);
return;
}
#endif
if (technologies_mask == -1 && nat)
tech_mask = (tNFA_TECHNOLOGY_MASK)nat->tech_mask;
else if (technologies_mask != -1)
tech_mask = (tNFA_TECHNOLOGY_MASK)technologies_mask;
#if (NXP_EXTNS == TRUE)
uint8_t default_tech_mask =
NfcConfig::getUnsigned(NAME_POLLING_TECH_MASK, DEFAULT_TECH_MASK);
tech_mask &= default_tech_mask;
#endif
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter; tech_mask = %02x", __func__, tech_mask);
if (sDiscoveryEnabled && !restart) {
LOG(ERROR) << StringPrintf("%s: already discovering", __func__);
return;
}
PowerSwitch::getInstance().setLevel(PowerSwitch::FULL_POWER);
if (sRfEnabled) {
// Stop RF discovery to reconfigure
startRfDiscovery(false);
}
// Check polling configuration
if (tech_mask != 0) {
stopPolling_rfDiscoveryDisabled();
#if (NXP_EXTNS==FALSE)
enableDisableLptd(enable_lptd);
#endif
startPolling_rfDiscoveryDisabled(tech_mask);
// Start P2P listening if tag polling was enabled
if (sPollingEnabled) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Enable p2pListening", __func__);
if (enable_p2p && !sP2pEnabled) {
sP2pEnabled = true;
PeerToPeer::getInstance().enableP2pListening(true);
NFA_ResumeP2p();
} else if (!enable_p2p && sP2pEnabled) {
sP2pEnabled = false;
PeerToPeer::getInstance().enableP2pListening(false);
NFA_PauseP2p();
}
if (reader_mode && !sReaderModeEnabled) {
sReaderModeEnabled = true;
NFA_DisableListening();
NFA_SetRfDiscoveryDuration(READER_MODE_DISCOVERY_DURATION);
} else if (!reader_mode && sReaderModeEnabled) {
struct nfc_jni_native_data* nat = getNative(e, o);
sReaderModeEnabled = false;
NFA_EnableListening();
NFA_SetRfDiscoveryDuration(nat->discovery_duration);
}
}
} else {
// No technologies configured, stop polling
stopPolling_rfDiscoveryDisabled();
}
// Check listen configuration
#if (NXP_EXTNS != TRUE)
if (enable_host_routing) {
RoutingManager::getInstance().enableRoutingToHost();
RoutingManager::getInstance().commitRouting();
} else {
RoutingManager::getInstance().disableRoutingToHost();
RoutingManager::getInstance().commitRouting();
}
#endif
// Actually start discovery.
startRfDiscovery(true);
sDiscoveryEnabled = true;
PowerSwitch::getInstance().setModeOn(PowerSwitch::DISCOVERY);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
}
/*******************************************************************************
**
** Function: nfcManager_disableDiscovery
**
** Description: Stop polling and listening for devices.
** e: JVM environment.
** o: Java object.
**
** Returns: None
**
*******************************************************************************/
void nfcManager_disableDiscovery(JNIEnv* e, jobject o) {
tNFA_STATUS status = NFA_STATUS_OK;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter;", __func__);
pn544InteropAbortNow();
#if(NXP_EXTNS == TRUE)
if(nfcFL.nfcNxpEse && nfcFL.eseFL._ESE_ETSI_READER_ENABLE) {
if(MposManager::getInstance().getEtsiReaederState() == STATE_SE_RDR_MODE_START_IN_PROGRESS)
{
Rdr_req_ntf_info_t mSwp_info = MposManager::getInstance().getSwpRrdReqInfo();
// if(android::isDiscoveryStarted() == true)
android::startRfDiscovery(false);
goto TheEnd;
}
else if(MposManager::getInstance().getEtsiReaederState() == STATE_SE_RDR_MODE_STOP_IN_PROGRESS)
{
android::startRfDiscovery(false);
goto TheEnd;
}
}
#endif
if (sDiscoveryEnabled == false) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: already disabled", __func__);
goto TheEnd;
}
// Stop RF Discovery.
startRfDiscovery(false);
if (sPollingEnabled) status = stopPolling_rfDiscoveryDisabled();
PeerToPeer::getInstance().enableP2pListening(false);
sP2pEnabled = false;
sDiscoveryEnabled = false;
// if nothing is active after this, then tell the controller to power down
if (!PowerSwitch::getInstance().setModeOff(PowerSwitch::DISCOVERY))
PowerSwitch::getInstance().setLevel(PowerSwitch::LOW_POWER);
TheEnd:
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
}
#if (NXP_EXTNS==FALSE)
void enableDisableLptd(bool enable) {
// This method is *NOT* thread-safe. Right now
// it is only called from the same thread so it's
// not an issue.
static bool sCheckedLptd = false;
static bool sHasLptd = false;
tNFA_STATUS stat = NFA_STATUS_OK;
if (!sCheckedLptd) {
sCheckedLptd = true;
SyncEventGuard guard(sNfaGetConfigEvent);
tNFA_PMID configParam[1] = {NCI_PARAM_ID_TAGSNIFF_CFG};
stat = NFA_GetConfig(1, configParam);
if (stat != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: NFA_GetConfig failed", __func__);
return;
}
sNfaGetConfigEvent.wait();
if (sCurrentConfigLen < 4 || sConfig[1] != NCI_PARAM_ID_TAGSNIFF_CFG) {
LOG(ERROR) << StringPrintf(
"%s: Config TLV length %d returned is too short", __func__,
sCurrentConfigLen);
return;
}
if (sConfig[3] == 0) {
LOG(ERROR) << StringPrintf(
"%s: LPTD is disabled, not enabling in current config", __func__);
return;
}
sHasLptd = true;
}
// Bail if we checked and didn't find any LPTD config before
if (!sHasLptd) return;
uint8_t enable_byte = enable ? 0x01 : 0x00;
SyncEventGuard guard(sNfaSetConfigEvent);
stat = NFA_SetConfig(NCI_PARAM_ID_TAGSNIFF_CFG, 1, &enable_byte);
if (stat == NFA_STATUS_OK)
sNfaSetConfigEvent.wait();
else
LOG(ERROR) << StringPrintf("%s: Could not configure LPTD feature",
__func__);
return;
}
#endif
/*******************************************************************************
**
** Function: nfcManager_doCreateLlcpServiceSocket
**
** Description: Create a new LLCP server socket.
** e: JVM environment.
** o: Java object.
** nSap: Service access point.
** sn: Service name
** miu: Maximum information unit.
** rw: Receive window size.
** linearBufferLength: Max buffer size.
**
** Returns: NativeLlcpServiceSocket Java object.
**
*******************************************************************************/
static jobject nfcManager_doCreateLlcpServiceSocket(JNIEnv* e, jobject,
jint nSap, jstring sn,
jint miu, jint rw,
jint linearBufferLength) {
PeerToPeer::tJNI_HANDLE jniHandle =
PeerToPeer::getInstance().getNewJniHandle();
ScopedUtfChars serviceName(e, sn);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: enter: sap=%i; name=%s; miu=%i; rw=%i; buffLen=%i", __func__, nSap,
serviceName.c_str(), miu, rw, linearBufferLength);
/* Create new NativeLlcpServiceSocket object */
jobject serviceSocket = NULL;
if (nfc_jni_cache_object_local(e, gNativeLlcpServiceSocketClassName,
&(serviceSocket)) == -1) {
LOG(ERROR) << StringPrintf("%s: Llcp socket object creation error",
__func__);
return NULL;
}
/* Get NativeLlcpServiceSocket class object */
ScopedLocalRef<jclass> clsNativeLlcpServiceSocket(
e, e->GetObjectClass(serviceSocket));
if (e->ExceptionCheck()) {
e->ExceptionClear();
LOG(ERROR) << StringPrintf("%s: Llcp Socket get object class error",
__func__);
return NULL;
}
if (!PeerToPeer::getInstance().registerServer(jniHandle,
serviceName.c_str())) {
LOG(ERROR) << StringPrintf("%s: RegisterServer error", __func__);
return NULL;
}
jfieldID f;
/* Set socket handle to be the same as the NfaHandle*/
f = e->GetFieldID(clsNativeLlcpServiceSocket.get(), "mHandle", "I");
e->SetIntField(serviceSocket, f, (jint)jniHandle);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: socket Handle = 0x%X", __func__, jniHandle);
/* Set socket linear buffer length */
f = e->GetFieldID(clsNativeLlcpServiceSocket.get(),
"mLocalLinearBufferLength", "I");
e->SetIntField(serviceSocket, f, (jint)linearBufferLength);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: buffer length = %d", __func__, linearBufferLength);
/* Set socket MIU */
f = e->GetFieldID(clsNativeLlcpServiceSocket.get(), "mLocalMiu", "I");
e->SetIntField(serviceSocket, f, (jint)miu);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: MIU = %d", __func__, miu);
/* Set socket RW */
f = e->GetFieldID(clsNativeLlcpServiceSocket.get(), "mLocalRw", "I");
e->SetIntField(serviceSocket, f, (jint)rw);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: RW = %d", __func__, rw);
sLastError = 0;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return serviceSocket;
}
/*******************************************************************************
**
** Function: nfcManager_doGetLastError
**
** Description: Get the last error code.
** e: JVM environment.
** o: Java object.
**
** Returns: Last error code.
**
*******************************************************************************/
static jint nfcManager_doGetLastError(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: last error=%i", __func__, sLastError);
return sLastError;
}
/*******************************************************************************
**
** Function: nfcManager_doDeinitialize
**
** Description: Turn off NFC.
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_doDeinitialize(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
#if (NXP_EXTNS == TRUE)
NativeJniExtns::getInstance().notifyNfcEvent(__func__);
handleWiredmode(false); /* Nfc Off*/
#endif
sIsDisabling = true;
pn544InteropAbortNow();
RoutingManager::getInstance().onNfccShutdown();
PowerSwitch::getInstance().initialize(PowerSwitch::UNKNOWN_LEVEL);
HciEventManager::getInstance().finalize();
#if (NXP_EXTNS == TRUE)
SecureElement::getInstance().releasePendingTransceive();
#endif
if (sIsNfaEnabled) {
SyncEventGuard guard(sNfaDisableEvent);
EXTNS_Close();
tNFA_STATUS stat = NFA_Disable(TRUE /* graceful */);
if (stat == NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: wait for completion", __func__);
sNfaDisableEvent.wait(); // wait for NFA command to finish
PeerToPeer::getInstance().handleNfcOnOff(false);
} else {
LOG(ERROR) << StringPrintf("%s: fail disable; error=0x%X", __func__,
stat);
}
}
nativeNfcTag_abortWaits();
NfcTag::getInstance().abort();
sAbortConnlessWait = true;
nativeLlcpConnectionlessSocket_abortWait();
sIsNfaEnabled = false;
sDiscoveryEnabled = false;
sPollingEnabled = false;
sIsDisabling = false;
sP2pEnabled = false;
gActivated = false;
sLfT3tMax = 0;
{
// unblock NFA_EnablePolling() and NFA_DisablePolling()
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
sNfaEnableDisablePollingEvent.notifyOne();
}
#if (NXP_EXTNS == TRUE)
/*Disable Field Detect Mode if enabled*/
#ifdef FIELD_DETECT_FEATURE
if (NFA_IsFieldDetectEnabled()) NFA_SetFieldDetectMode(false);
#endif
SecureElement::getInstance().finalize ();
#endif
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.Finalize();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return JNI_TRUE;
}
/*******************************************************************************
**
** Function: nfcManager_doCreateLlcpSocket
**
** Description: Create a LLCP connection-oriented socket.
** e: JVM environment.
** o: Java object.
** nSap: Service access point.
** miu: Maximum information unit.
** rw: Receive window size.
** linearBufferLength: Max buffer size.
**
** Returns: NativeLlcpSocket Java object.
**
*******************************************************************************/
static jobject nfcManager_doCreateLlcpSocket(JNIEnv* e, jobject, jint nSap,
jint miu, jint rw,
jint linearBufferLength) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter; sap=%d; miu=%d; rw=%d; buffer len=%d",
__func__, nSap, miu, rw, linearBufferLength);
PeerToPeer::tJNI_HANDLE jniHandle =
PeerToPeer::getInstance().getNewJniHandle();
PeerToPeer::getInstance().createClient(jniHandle, miu, rw);
/* Create new NativeLlcpSocket object */
jobject clientSocket = NULL;
if (nfc_jni_cache_object_local(e, gNativeLlcpSocketClassName,
&(clientSocket)) == -1) {
LOG(ERROR) << StringPrintf("%s: fail Llcp socket creation", __func__);
return clientSocket;
}
/* Get NativeConnectionless class object */
ScopedLocalRef<jclass> clsNativeLlcpSocket(e,
e->GetObjectClass(clientSocket));
if (e->ExceptionCheck()) {
e->ExceptionClear();
LOG(ERROR) << StringPrintf("%s: fail get class object", __func__);
return clientSocket;
}
jfieldID f;
/* Set socket SAP */
f = e->GetFieldID(clsNativeLlcpSocket.get(), "mSap", "I");
e->SetIntField(clientSocket, f, (jint)nSap);
/* Set socket handle */
f = e->GetFieldID(clsNativeLlcpSocket.get(), "mHandle", "I");
e->SetIntField(clientSocket, f, (jint)jniHandle);
/* Set socket MIU */
f = e->GetFieldID(clsNativeLlcpSocket.get(), "mLocalMiu", "I");
e->SetIntField(clientSocket, f, (jint)miu);
/* Set socket RW */
f = e->GetFieldID(clsNativeLlcpSocket.get(), "mLocalRw", "I");
e->SetIntField(clientSocket, f, (jint)rw);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return clientSocket;
}
/*******************************************************************************
**
** Function: nfcManager_doCreateLlcpConnectionlessSocket
**
** Description: Create a connection-less socket.
** e: JVM environment.
** o: Java object.
** nSap: Service access point.
** sn: Service name.
**
** Returns: NativeLlcpConnectionlessSocket Java object.
**
*******************************************************************************/
static jobject nfcManager_doCreateLlcpConnectionlessSocket(JNIEnv*, jobject,
jint nSap,
jstring /*sn*/) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: nSap=0x%X", __func__, nSap);
return NULL;
}
/*******************************************************************************
**
** Function: nfcManager_getDefaultAidRoute
**
** Description: Get the default Aid Route Entry.
** e: JVM environment.
** o: Java object.
** mode: Not used.
**
** Returns: None
**
*******************************************************************************/
static jint nfcManager_getDefaultAidRoute(JNIEnv* e, jobject o) {
unsigned long num = 0;
if (NfcConfig::hasKey(NAME_DEFAULT_AID_ROUTE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_AID_ROUTE);
return num;
}
/*******************************************************************************
**
** Function: nfcManager_getDefaultDesfireRoute
**
** Description: Get the default Desfire Route Entry.
** e: JVM environment.
** o: Java object.
** mode: Not used.
**
** Returns: None
**
*******************************************************************************/
static jint nfcManager_getDefaultDesfireRoute(JNIEnv* e, jobject o) {
unsigned long num = 0;
if (NfcConfig::hasKey(NAME_DEFAULT_ISODEP_ROUTE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_ISODEP_ROUTE);
return num;
}
/*******************************************************************************
**
** Function: getConfig
**
** Description: read the config values from NFC controller.
**
** Returns: SUCCESS/FAILURE
**
*******************************************************************************/
tNFA_STATUS getConfig(uint16_t* rspLen, uint8_t* configValue, uint8_t numParam,
tNFA_PMID* param) {
tNFA_STATUS status = NFA_STATUS_FAILED;
if (rspLen == NULL || configValue == NULL || param == NULL)
return NFA_STATUS_FAILED;
SyncEventGuard guard(sNfaGetConfigEvent);
status = NFA_GetConfig(numParam, param);
if (status == NFA_STATUS_OK) {
if (sNfaGetConfigEvent.wait(WIRED_MODE_TRANSCEIVE_TIMEOUT) == false) {
*rspLen = 0;
} else {
*rspLen = sCurrentConfigLen;
memcpy(configValue, sConfig, sCurrentConfigLen);
}
} else {
*rspLen = 0;
}
return status;
}
/*******************************************************************************
**
** Function: nfcManager_getDefaultMifareCLTRoute
**
** Description: Get the default mifare CLT Route Entry.
** e: JVM environment.
** o: Java object.
** mode: Not used.
**
** Returns: None
**
*******************************************************************************/
static jint nfcManager_getDefaultMifareCLTRoute(JNIEnv* e, jobject o) {
unsigned long num = 0;
if (NfcConfig::hasKey(NAME_DEFAULT_MIFARE_CLT_ROUTE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_MIFARE_CLT_ROUTE);
return num;
}
#if(NXP_EXTNS == TRUE)
/*******************************************************************************
**
** Function: nfcManager_getDefaultFelicaCLTPowerState
**
** Description: Get the default mifare CLT Power States.
** e: JVM environment.
** o: Java object.
**
** Returns: Power State
**
*******************************************************************************/
static jint nfcManager_getDefaultFelicaCLTPowerState(JNIEnv* e, jobject o) {
unsigned long num = 0;
if (NfcConfig::hasKey(NAME_DEFAULT_FELICA_CLT_PWR_STATE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_FELICA_CLT_PWR_STATE);
return num;
}
/*******************************************************************************
**
** Function: nfcManager_getDefaultFelicaCLTRoute
**
** Description: Get the default mifare CLT Route Entry.
** e: JVM environment.
** o: Java object.
** mode: Not used.
**
** Returns: None
**
*******************************************************************************/
static jint nfcManager_getDefaultFelicaCLTRoute(JNIEnv* e, jobject o) {
unsigned long num = 0;
if (NfcConfig::hasKey(NAME_DEFAULT_FELICA_CLT_ROUTE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_FELICA_CLT_ROUTE);
return num;
}
/*******************************************************************************
**
** Function: nfcManager_SetFieldDetectMode
**
** Description: Updates field detect mode ENABLE/DISABLE
** e: JVM environment.
** o: Java object.
**
** Returns: Update status
**
*******************************************************************************/
static field_detect_status_t nfcManager_SetFieldDetectMode(JNIEnv*, jobject,
jboolean mode) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Enter", __func__);
#ifdef FIELD_DETECT_FEATURE
se_rd_req_state_t state = MposManager::getInstance().getEtsiReaederState();
if (!nfcManager_isNfcActive()) {1
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Nfc is not Enabled. Returning", __func__);
return FDSTATUS_ERROR_NFC_IS_OFF;
}
if ((state != STATE_SE_RDR_MODE_STOPPED) &&
(state != STATE_SE_RDR_MODE_INVALID)) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: MPOS is ongoing.. Returning", __func__);
return FDSTATUS_ERROR_NFC_BUSY_IN_MPOS;
}
if (NFA_IsFieldDetectEnabled() == mode) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: Already %s", __func__, ((mode) ? "ENABLED" : "DISABLED"));
return FDSTATUS_SUCCESS;
}
if (sRfEnabled) {
// Stop RF Discovery
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: stop discovery", __func__);
startRfDiscovery(false);
}
NFA_SetFieldDetectMode(mode);
// start discovery
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: reconfigured start discovery", __func__);
startRfDiscovery(true);
#else
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Feature not supported", __func__);
#endif
return FDSTATUS_ERROR_UNKNOWN;
}
/*******************************************************************************
**
** Function: nfcManager_IsFieldDetectEnabled
**
** Description: Returns current status of field detect mode
** e: JVM environment.
** o: Java object.
**
** Returns: true/false
**
*******************************************************************************/
static jboolean nfcManager_IsFieldDetectEnabled(JNIEnv*, jobject) {
#ifdef FIELD_DETECT_FEATURE
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Enter", __func__);
return NFA_IsFieldDetectEnabled();
#else
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: Feature not supported", __func__);
return false;
#endif
}
#endif
/*******************************************************************************
**
** Function: nfcManager_getDefaultAidPowerState
**
** Description: Get the default Desfire Power States.
** e: JVM environment.
** o: Java object.
**
** Returns: Power State
**
*******************************************************************************/
static jint nfcManager_getDefaultAidPowerState(JNIEnv* e, jobject o) {
unsigned long num = 0;
#if (NXP_EXTNS == TRUE)
if (NfcConfig::hasKey(NAME_DEFAULT_AID_PWR_STATE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_AID_PWR_STATE);
#endif
return num;
}
/*******************************************************************************
**
** Function: nfcManager_getDefaultDesfirePowerState
**
** Description: Get the default Desfire Power States.
** e: JVM environment.
** o: Java object.
**
** Returns: Power State
**
*******************************************************************************/
static jint nfcManager_getDefaultDesfirePowerState(JNIEnv* e, jobject o) {
unsigned long num = 0;
#if (NXP_EXTNS == TRUE)
if (NfcConfig::hasKey(NAME_DEFAULT_DESFIRE_PWR_STATE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_DESFIRE_PWR_STATE);
#endif
return num;
}
static int nfcManager_getDefaulGsmaPowerState(JNIEnv* e, jobject o)
{
return RoutingManager::getInstance().mDefaultGsmaPowerState;
}
/*******************************************************************************
**
** Function: nfcManager_getDefaultMifareCLTPowerState
**
** Description: Get the default mifare CLT Power States.
** e: JVM environment.
** o: Java object.
**
** Returns: Power State
**
*******************************************************************************/
static jint nfcManager_getDefaultMifareCLTPowerState(JNIEnv* e, jobject o) {
unsigned long num = 0;
#if (NXP_EXTNS == TRUE)
if (NfcConfig::hasKey(NAME_DEFAULT_MIFARE_CLT_PWR_STATE))
num = NfcConfig::getUnsigned(NAME_DEFAULT_MIFARE_CLT_PWR_STATE);
#endif
return num;
}
/*******************************************************************************
**
** Function: isPeerToPeer
**
** Description: Whether the activation data indicates the peer supports
*NFC-DEP.
** activated: Activation data.
**
** Returns: True if the peer supports NFC-DEP.
**
*******************************************************************************/
static bool isPeerToPeer(tNFA_ACTIVATED& activated) {
return activated.activate_ntf.protocol == NFA_PROTOCOL_NFC_DEP;
}
/*******************************************************************************
**
** Function: isListenMode
**
** Description: Indicates whether the activation data indicates it is
** listen mode.
**
** Returns: True if this listen mode.
**
*******************************************************************************/
static bool isListenMode(tNFA_ACTIVATED& activated) {
return ((NFC_INTERFACE_EE_DIRECT_RF ==
activated.activate_ntf.intf_param.type) ||
(NFC_DISCOVERY_TYPE_LISTEN_A ==
activated.activate_ntf.rf_tech_param.mode) ||
(NFC_DISCOVERY_TYPE_LISTEN_B ==
activated.activate_ntf.rf_tech_param.mode) ||
(NFC_DISCOVERY_TYPE_LISTEN_F ==
activated.activate_ntf.rf_tech_param.mode) ||
(NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE ==
activated.activate_ntf.rf_tech_param.mode) ||
(NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE ==
activated.activate_ntf.rf_tech_param.mode) ||
(NFC_DISCOVERY_TYPE_LISTEN_ISO15693 ==
activated.activate_ntf.rf_tech_param.mode) ||
(NFC_DISCOVERY_TYPE_LISTEN_B_PRIME ==
activated.activate_ntf.rf_tech_param.mode));
}
/*******************************************************************************
**
** Function: nfcManager_doCheckLlcp
**
** Description: Not used.
**
** Returns: True
**
*******************************************************************************/
static jboolean nfcManager_doCheckLlcp(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
return JNI_TRUE;
}
/*******************************************************************************
**
** Function: nfcManager_doActivateLlcp
**
** Description: Not used.
**
** Returns: True
**
*******************************************************************************/
static jboolean nfcManager_doActivateLlcp(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
return JNI_TRUE;
}
/*******************************************************************************
**
** Function: nfcManager_doAbort
**
** Description: Not used.
**
** Returns: None
**
*******************************************************************************/
static void nfcManager_doAbort(JNIEnv* e, jobject, jstring msg) {
ScopedUtfChars message = {e, msg};
e->FatalError(message.c_str());
abort(); // <-- Unreachable
}
#if(NXP_EXTNS == TRUE)
/*******************************************************************************
**
** Function: handleWiredmode
**
** Description: The function will close the wired mode if it is open.
** It shall be called in the NFC and Device off cases.
** Returns: void
**
*******************************************************************************/
void handleWiredmode(bool isShutdown)
{
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter, isShutdown %d", __func__, isShutdown);
SecureElement &se = SecureElement::getInstance();
if(se.mIsWiredModeOpen) {
se.setNfccPwrConfig(SecureElement::POWER_ALWAYS_ON);
se.sendEvent(SecureElement::EVT_END_OF_APDU_TRANSFER);
usleep(10 * 1000);
}
if(!isShutdown) {
se. SecEle_Modeset(SecureElement::NFCEE_DISABLE);
}
}
/*******************************************************************************
**
** Function: nfcManager_doPartialInitForEseCosUpdate
**
** Description: Partial Init for card OS update
**
** Returns: NFA_STATUS_OK
**
*******************************************************************************/
static jboolean nfcManager_doPartialInitForEseCosUpdate(JNIEnv* e, jobject o) {
/* Dummy API return always true.No need to initlize nfc mw
* as jcop update is done over spi interface.This api is
* maintained sothat customer app does not break. */
return true;
}
/*******************************************************************************
**
** Function: nfcManager_doPartialDeinitForEseCosUpdate
**
** Description: Partial Deinit for card OS Update
**
** Returns: NFA_STATUS_OK
**
*******************************************************************************/
static jboolean nfcManager_doPartialDeinitForEseCosUpdate(JNIEnv* e,
jobject o) {
/* Dummy API return always true.No need to initlize nfc mw
* as jcop update is done over spi interface.This api is
* maintained sothat customer app does not break. */
return true;
}
/*******************************************************************************
**
** Function: nfcManager_doResonantFrequency
**
** Description: factory mode to measure resonance frequency
**
** Returns: void
**
*******************************************************************************/
static void nfcManager_doResonantFrequency(JNIEnv* e, jobject o,
jboolean modeOn) {
(void)e;
(void)o;
tNFA_STATUS status = NFA_STATUS_FAILED;
jint pollTech, uiccListenTech;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"startResonantFrequency : mode[%s]", modeOn == true ? "ON" : "OFF");
if (!sIsNfaEnabled) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("startResonantFrequency :NFC is not enabled!!");
return;
} else if (modeOn && gselfTestData.isStored) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("startResonantFrequency: Already ON!!");
return;
} else if (!modeOn && !gselfTestData.isStored) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("startResonantFrequency: already OFF!!");
return;
}
/* Read the Polling and Listen Tech Mask from the config file */
pollTech = NfcConfig::getUnsigned(NAME_POLLING_TECH_MASK,
RESONANT_FREQ_DEFAULT_POLL_MASK);
uiccListenTech = NfcConfig::getUnsigned(NAME_UICC_LISTEN_TECH_MASK,
RESONANT_FREQ_DEFAULT_LISTEN_MASK);
/* Stop RF Discovery */
if (android::isDiscoveryStarted()) android::startRfDiscovery(false);
/* Perform the Requested Test */
status = NfcSelfTest::GetInstance().doNfccSelfTest(
modeOn ? TEST_TYPE_SET_RFTXCFG_RESONANT_FREQ : TEST_TYPE_RESTORE_RFTXCFG);
if (NFA_STATUS_OK == status) {
nfcManager_doDeinitialize(NULL, NULL);
usleep(1000 * 1000);
nfcManager_doInitialize(NULL, NULL);
usleep(1000 * 2000);
if (modeOn) /* TEST_TYPE_SET_RFTXCFG_RESONANT_FREQ */
pollTech = 0x00; /* Activate only Card Emulation Mode */
{ /* Change the discovery tech mask as per the test */
SyncEventGuard guard(sChangeDiscTechEvent);
status = NFA_ChangeDiscoveryTech(pollTech, uiccListenTech);
if (NFA_STATUS_OK == status) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: waiting for nfcManager_changeDiscoveryTech", __func__);
sChangeDiscTechEvent.wait();
} else {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: nfcManager_changeDiscoveryTech failed", __func__);
}
}
}
/* Restart the discovery
* CASE1: TEST_TYPE_SET_RFTXCFG_RESONANT_FREQ --> Only CARD EMULATION
* CASE2: TEST_TYPE_RESTORE_RFTXCFG --> Both the READER & CE mode
* CASE3: FAILURE OF TEST --> Restart last discovery*/
android::startRfDiscovery(true);
}
/*******************************************************************************
**
** Function: nfcManager_doPartialInitialize
**
** Description: Partial Initalize of NFC
**
** Returns: True if ok.
**
*******************************************************************************/
int nfcManager_doPartialInitialize(JNIEnv* e, jobject o) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
tNFA_STATUS stat = NFA_STATUS_OK;
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.Initialize();
tHAL_NFC_ENTRY* halFuncEntries = theInstance.GetHalEntryFuncs ();
if(NULL == halFuncEntries)
{
theInstance.Finalize();
gsNfaPartialEnabled = false;
return NFA_STATUS_FAILED;
}
theInstance.NFA_SetBootMode(NFA_FAST_BOOT_MODE);
NFA_Init (halFuncEntries);
DLOG_IF(INFO, nfc_debug_enabled)<< StringPrintf("%s: calling enable", __func__);
stat = NFA_Enable (nfaDeviceManagementCallback, nfaConnectionCallback);
if (stat == NFA_STATUS_OK)
{
SyncEventGuard guard (sNfaEnableEvent);
sNfaEnableEvent.wait(); //wait for NFA command to finish
}
if (sIsNfaEnabled)
{
gsNfaPartialEnabled = true;
sIsNfaEnabled = false;
}
else
{
NFA_Disable (false /* ungraceful */);
theInstance.Finalize();
gsNfaPartialEnabled = false;
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return NFA_STATUS_OK;
}
/*******************************************************************************
**
** Function: nfcManager_doPartialDeInitialize
**
** Description: Partial De-Initalize of NFC
**
** Returns: True if ok.
**
*******************************************************************************/
int nfcManager_doPartialDeInitialize(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
tNFA_STATUS stat = NFA_STATUS_OK;
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
if(!gsNfaPartialEnabled)
{
DLOG_IF(INFO, nfc_debug_enabled)<< StringPrintf("%s: cannot deinitialize NFC , not partially initilaized", __func__);
return NFA_STATUS_FAILED;
}
DLOG_IF(INFO, nfc_debug_enabled)<< StringPrintf("%s:enter", __func__);
stat = NFA_Disable (true /* graceful */);
if (stat == NFA_STATUS_OK)
{
DLOG_IF(INFO, nfc_debug_enabled)<< StringPrintf("%s: wait for completion", __func__);
SyncEventGuard guard (sNfaDisableEvent);
sNfaDisableEvent.wait (); //wait for NFA command to finish
}
else
{
DLOG_IF(ERROR, nfc_debug_enabled) << StringPrintf("%s: fail disable; error=0x%X", __func__, stat);
}
theInstance.Finalize();
theInstance.NFA_SetBootMode(NFA_NORMAL_BOOT_MODE);
gsNfaPartialEnabled = false;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return NFA_STATUS_OK;
}
#endif
/*******************************************************************************
**
** Function: nfcManager_doDownload
**
** Description: Download firmware patch files. Do not turn on NFC.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_doDownload(JNIEnv* e, jobject o) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
bool result = JNI_FALSE;
theInstance.Initialize(); // start GKI, NCI task, NFC task
#if (NXP_EXTNS == TRUE)
NativeJniExtns::getInstance().initializeNativeData(getNative(e, o));
result = theInstance.DownloadFirmware(nfcFwUpdateStatusCallback, false);
#else
result = theInstance.DownloadFirmware();
#endif
theInstance.Finalize();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return result;
}
/*******************************************************************************
**
** Function: nfcManager_doResetTimeouts
**
** Description: Not used.
**
** Returns: None
**
*******************************************************************************/
static void nfcManager_doResetTimeouts(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
NfcTag::getInstance().resetAllTransceiveTimeouts();
}
/*******************************************************************************
**
** Function: nfcManager_doSetTimeout
**
** Description: Set timeout value.
** e: JVM environment.
** o: Java object.
** tech: technology ID.
** timeout: Timeout value.
**
** Returns: True if ok.
**
*******************************************************************************/
static bool nfcManager_doSetTimeout(JNIEnv*, jobject, jint tech, jint timeout) {
if (timeout <= 0) {
LOG(ERROR) << StringPrintf("%s: Timeout must be positive.", __func__);
return false;
}
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: tech=%d, timeout=%d", __func__, tech, timeout);
NfcTag::getInstance().setTransceiveTimeout(tech, timeout);
return true;
}
/*******************************************************************************
**
** Function: nfcManager_doGetTimeout
**
** Description: Get timeout value.
** e: JVM environment.
** o: Java object.
** tech: technology ID.
**
** Returns: Timeout value.
**
*******************************************************************************/
static jint nfcManager_doGetTimeout(JNIEnv*, jobject, jint tech) {
int timeout = NfcTag::getInstance().getTransceiveTimeout(tech);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: tech=%d, timeout=%d", __func__, tech, timeout);
return timeout;
}
/*******************************************************************************
**
** Function: nfcManager_doDump
**
** Description: Get libnfc-nci dump
** e: JVM environment.
** obj: Java object.
** fdobj: File descriptor to be used
**
** Returns: Void
**
*******************************************************************************/
static void nfcManager_doDump(JNIEnv* e, jobject obj, jobject fdobj) {
int fd = jniGetFDFromFileDescriptor(e, fdobj);
if (fd < 0) return;
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.Dump(fd);
}
static jint nfcManager_doGetNciVersion(JNIEnv*, jobject) {
return NFC_GetNCIVersion();
}
static void nfcManager_doSetScreenState(JNIEnv* e, jobject o,
jint screen_state_mask) {
tNFA_STATUS status = NFA_STATUS_OK;
uint8_t state = (screen_state_mask & NFA_SCREEN_STATE_MASK);
uint8_t discovry_param =
NCI_LISTEN_DH_NFCEE_ENABLE_MASK | NCI_POLLING_DH_ENABLE_MASK;
#if (NXP_EXTNS == TRUE)
if(prevScreenState == state) {
LOG_IF(INFO, nfc_debug_enabled)<< StringPrintf("Screen state is not changed.");
return;
}
NativeJniExtns::getInstance().notifyNfcEvent(__func__);
#endif
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: state = %d prevScreenState= %d, discovry_param = %d",
__FUNCTION__, state, prevScreenState, discovry_param);
if (sIsDisabling || !sIsNfaEnabled ||
(NFC_GetNCIVersion() != NCI_VERSION_2_0)) {
prevScreenState = state;
return;
}
if (
#if (NXP_EXTNS == TRUE)
prevScreenState == NFA_SCREEN_STATE_UNKNOWN ||
#endif
prevScreenState == NFA_SCREEN_STATE_OFF_LOCKED ||
prevScreenState == NFA_SCREEN_STATE_OFF_UNLOCKED ||
prevScreenState == NFA_SCREEN_STATE_ON_LOCKED) {
SyncEventGuard guard(sNfaSetPowerSubState);
status = NFA_SetPowerSubStateForScreenState(state);
if (status != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: fail enable SetScreenState; error=0x%X",
__FUNCTION__, status);
return;
} else {
sNfaSetPowerSubState.wait();
}
}
if (state == NFA_SCREEN_STATE_OFF_LOCKED ||
state == NFA_SCREEN_STATE_OFF_UNLOCKED) {
// disable poll, and DH-NFCEE considered as enabled 0x00
discovry_param =
NCI_POLLING_DH_DISABLE_MASK | NCI_LISTEN_DH_NFCEE_ENABLE_MASK;
}
if (state == NFA_SCREEN_STATE_ON_LOCKED) {
// disable poll and enable listen on DH 0x00
discovry_param =
(screen_state_mask & NFA_SCREEN_POLLING_TAG_MASK)
? (NCI_LISTEN_DH_NFCEE_ENABLE_MASK | NCI_POLLING_DH_ENABLE_MASK)
: (NCI_POLLING_DH_DISABLE_MASK | NCI_LISTEN_DH_NFCEE_ENABLE_MASK);
}
if (state == NFA_SCREEN_STATE_ON_UNLOCKED) {
// enable both poll and listen on DH 0x01
discovry_param =
NCI_LISTEN_DH_NFCEE_ENABLE_MASK | NCI_POLLING_DH_ENABLE_MASK;
}
SyncEventGuard guard(sNfaSetConfigEvent);
status = NFA_SetConfig(NCI_PARAM_ID_CON_DISCOVERY_PARAM,
NCI_PARAM_LEN_CON_DISCOVERY_PARAM, &discovry_param);
if (status == NFA_STATUS_OK) {
sNfaSetConfigEvent.wait();
} else {
LOG(ERROR) << StringPrintf("%s: Failed to update CON_DISCOVER_PARAM",
__FUNCTION__);
return;
}
if (prevScreenState == NFA_SCREEN_STATE_ON_UNLOCKED) {
SyncEventGuard guard(sNfaSetPowerSubState);
status = NFA_SetPowerSubStateForScreenState(state);
if (status != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: fail enable SetScreenState; error=0x%X",
__FUNCTION__, status);
} else {
sNfaSetPowerSubState.wait();
}
}
if ((state == NFA_SCREEN_STATE_OFF_LOCKED ||
state == NFA_SCREEN_STATE_OFF_UNLOCKED) &&
prevScreenState == NFA_SCREEN_STATE_ON_UNLOCKED) {
// screen turns off, disconnect tag if connected
#if (NXP_EXTNS == TRUE)
if(sReaderModeEnabled || sP2pActive){
nativeNfcTag_doDisconnect(NULL, NULL);
}else{
//CardEmulation: Shouldn't take an action.
}
#else
nativeNfcTag_doDisconnect(NULL, NULL);
#endif
}
prevScreenState = state;
}
/*******************************************************************************
**
** Function: nfcManager_doSetP2pInitiatorModes
**
** Description: Set P2P initiator's activation modes.
** e: JVM environment.
** o: Java object.
** modes: Active and/or passive modes. The values are
*specified
** in external/libnfc-nxp/inc/phNfcTypes.h. See
** enum phNfc_eP2PMode_t.
**
** Returns: None.
**
*******************************************************************************/
static void nfcManager_doSetP2pInitiatorModes(JNIEnv* e, jobject o,
jint modes) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: modes=0x%X", __func__, modes);
struct nfc_jni_native_data* nat = getNative(e, o);
tNFA_TECHNOLOGY_MASK mask = 0;
if (modes & 0x01) mask |= NFA_TECHNOLOGY_MASK_A;
if (modes & 0x02) mask |= NFA_TECHNOLOGY_MASK_F;
if (modes & 0x04) mask |= NFA_TECHNOLOGY_MASK_F;
if (modes & 0x08) mask |= NFA_TECHNOLOGY_MASK_A_ACTIVE;
if (modes & 0x10) mask |= NFA_TECHNOLOGY_MASK_F_ACTIVE;
if (modes & 0x20) mask |= NFA_TECHNOLOGY_MASK_F_ACTIVE;
nat->tech_mask = mask;
}
/*******************************************************************************
**
** Function: nfcManager_doSetP2pTargetModes
**
** Description: Set P2P target's activation modes.
** e: JVM environment.
** o: Java object.
** modes: Active and/or passive modes.
**
** Returns: None.
**
*******************************************************************************/
static void nfcManager_doSetP2pTargetModes(JNIEnv*, jobject, jint modes) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: modes=0x%X", __func__, modes);
// Map in the right modes
tNFA_TECHNOLOGY_MASK mask = 0;
if (modes & 0x01) mask |= NFA_TECHNOLOGY_MASK_A;
if (modes & 0x02) mask |= NFA_TECHNOLOGY_MASK_F;
if (modes & 0x04) mask |= NFA_TECHNOLOGY_MASK_F;
if (modes & 0x08)
mask |= NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE;
PeerToPeer::getInstance().setP2pListenMask(mask);
}
static void nfcManager_doEnableScreenOffSuspend(JNIEnv* e, jobject o) {
PowerSwitch::getInstance().setScreenOffPowerState(
PowerSwitch::POWER_STATE_FULL);
}
static void nfcManager_doDisableScreenOffSuspend(JNIEnv* e, jobject o) {
PowerSwitch::getInstance().setScreenOffPowerState(
PowerSwitch::POWER_STATE_OFF);
}
/*******************************************************************************
**
** Function: nfcManager_getIsoDepMaxTransceiveLength
**
** Description: Get maximum ISO DEP Transceive Length supported by the NFC
** chip. Returns default 261 bytes if the property is not set.
**
** Returns: max value.
**
*******************************************************************************/
static jint nfcManager_getIsoDepMaxTransceiveLength(JNIEnv*, jobject) {
/* Check if extended APDU is supported by the chip.
* If not, default value is returned.
* The maximum length of a default IsoDep frame consists of:
* CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
*/
return NfcConfig::getUnsigned(NAME_ISO_DEP_MAX_TRANSCEIVE, 261);
}
static jboolean nfcManager_doSetNfcSecure(JNIEnv* e, jobject o,
jboolean enable) {
RoutingManager& routingManager = RoutingManager::getInstance();
routingManager.setNfcSecure(enable);
#if(NXP_EXTNS != TRUE)
bool rfEnabled = sRfEnabled;
#endif
if (sRoutingInitialized) {
#if(NXP_EXTNS != TRUE)
routingManager.disableRoutingToHost();
if (rfEnabled) startRfDiscovery(false);
routingManager.updateRoutingTable();
routingManager.enableRoutingToHost();
routingManager.commitRouting();
if (rfEnabled) startRfDiscovery(true);
#else
routingManager.updateRoutingTable();
#endif
}
return true;
}
/*****************************************************************************
**
** JNI functions for android-4.0.1_r1
**
*****************************************************************************/
static JNINativeMethod gMethods[] = {
{"doDownload", "()Z", (void*)nfcManager_doDownload},
{"initializeNativeStructure", "()Z", (void*)nfcManager_initNativeStruc},
{"doInitialize", "()Z", (void*)nfcManager_doInitialize},
{"doDeinitialize", "()Z", (void*)nfcManager_doDeinitialize},
{"sendRawFrame", "([B)Z", (void*)nfcManager_sendRawFrame},
{"routeAid", "([BIII)Z", (void*)nfcManager_routeAid},
{"unrouteAid", "([B)Z", (void*)nfcManager_unrouteAid},
{"doSetRoutingEntry", "(IIII)Z",
(void*)nfcManager_setRoutingEntry},
{"doClearRoutingEntry", "(I)Z",
(void*)nfcManager_clearRoutingEntry},
{"commitRouting", "()Z", (void*)nfcManager_commitRouting},
{"setEmptyAidRoute", "(I)V", (void*)nfcManager_setEmptyAidRoute},
{"doRegisterT3tIdentifier", "([B)I",
(void*)nfcManager_doRegisterT3tIdentifier},
{"doDeregisterT3tIdentifier", "(I)V",
(void*)nfcManager_doDeregisterT3tIdentifier},
{"getLfT3tMax", "()I", (void*)nfcManager_getLfT3tMax},
{"doEnableDiscovery", "(IZZZZZ)V", (void*)nfcManager_enableDiscovery},
{"doCheckLlcp", "()Z", (void*)nfcManager_doCheckLlcp},
{"doActivateLlcp", "()Z", (void*)nfcManager_doActivateLlcp},
{"doCreateLlcpConnectionlessSocket",
"(ILjava/lang/String;)Lcom/android/nfc/dhimpl/"
"NativeLlcpConnectionlessSocket;",
(void*)nfcManager_doCreateLlcpConnectionlessSocket},
{"doCreateLlcpServiceSocket",
"(ILjava/lang/String;III)Lcom/android/nfc/dhimpl/NativeLlcpServiceSocket;",
(void*)nfcManager_doCreateLlcpServiceSocket},
{"doCreateLlcpSocket", "(IIII)Lcom/android/nfc/dhimpl/NativeLlcpSocket;",
(void*)nfcManager_doCreateLlcpSocket},
{"doGetLastError", "()I", (void*)nfcManager_doGetLastError},
{"disableDiscovery", "()V", (void*)nfcManager_disableDiscovery},
{"doSetTimeout", "(II)Z", (void*)nfcManager_doSetTimeout},
{"doGetTimeout", "(I)I", (void*)nfcManager_doGetTimeout},
{"doResetTimeouts", "()V", (void*)nfcManager_doResetTimeouts},
{"doAbort", "(Ljava/lang/String;)V", (void*)nfcManager_doAbort},
{"doSetP2pInitiatorModes", "(I)V",
(void*)nfcManager_doSetP2pInitiatorModes},
{"doSetP2pTargetModes", "(I)V", (void*)nfcManager_doSetP2pTargetModes},
{"doEnableScreenOffSuspend", "()V",
(void*)nfcManager_doEnableScreenOffSuspend},
{"doSetScreenState", "(I)V", (void*)nfcManager_doSetScreenState},
{"doDisableScreenOffSuspend", "()V",
(void*)nfcManager_doDisableScreenOffSuspend},
{"doDump", "(Ljava/io/FileDescriptor;)V", (void*)nfcManager_doDump},
{"getNciVersion", "()I", (void*)nfcManager_doGetNciVersion},
{"doEnableDtaMode", "()V", (void*)nfcManager_doEnableDtaMode},
{"doDisableDtaMode", "()V", (void*)nfcManager_doDisableDtaMode},
{"doFactoryReset", "()V", (void*)nfcManager_doFactoryReset},
{"doShutdown", "()V", (void*)nfcManager_doShutdown},
{"getIsoDepMaxTransceiveLength", "()I",
(void*)nfcManager_getIsoDepMaxTransceiveLength},
{"getDefaultAidRoute", "()I",
(void*) nfcManager_getDefaultAidRoute},
{"getDefaultDesfireRoute", "()I",
(void*) nfcManager_getDefaultDesfireRoute},
{"getDefaultMifareCLTRoute", "()I",
(void*) nfcManager_getDefaultMifareCLTRoute},
{"getDefaultAidPowerState", "()I",
(void*) nfcManager_getDefaultAidPowerState},
{"getDefaultDesfirePowerState", "()I",
(void*) nfcManager_getDefaultDesfirePowerState},
{"getDefaultMifareCLTPowerState", "()I",
(void*) nfcManager_getDefaultMifareCLTPowerState},
#if(NXP_EXTNS == TRUE)
{"getGsmaPwrState", "()I",
(void*) nfcManager_getDefaulGsmaPowerState}
,{"getDefaultFelicaCLTPowerState", "()I",
(void*) nfcManager_getDefaultFelicaCLTPowerState},
{"getDefaultFelicaCLTRoute", "()I",
(void*) nfcManager_getDefaultFelicaCLTRoute},
{"doGetActiveSecureElementList", "()[I",
(void *)nfcManager_getActiveSecureElementList},
{"doChangeDiscoveryTech", "(II)V",
(void *)nfcManager_changeDiscoveryTech},
{"doPartialInitForEseCosUpdate", "()Z",
(void*)nfcManager_doPartialInitForEseCosUpdate},
{"doPartialDeinitForEseCosUpdate", "()Z",
(void*)nfcManager_doPartialDeinitForEseCosUpdate},
{"doResonantFrequency", "(Z)V",
(void *)nfcManager_doResonantFrequency},
{"doSetFieldDetectMode", "(Z)I",
(void*)nfcManager_SetFieldDetectMode},
{"isFieldDetectEnabled", "()Z",
(void*)nfcManager_IsFieldDetectEnabled},
#endif
#if(NXP_EXTNS == TRUE)
// check firmware version
{"getFWVersion", "()I", (void*)nfcManager_getFwVersion},
{"readerPassThruMode", "(BB)[B", (void*)nfcManager_readerPassThruMode},
{"transceiveAppData", "([B)[B", (void*)nfcManager_transceiveAppData},
{"isNfccBusy", "()Z", (void*)nfcManager_isNfccBusy},
{"setTransitConfig", "(Ljava/lang/String;)I",
(void*)nfcManager_setTransitConfig},
{"getAidTableSize", "()I",
(void*) nfcManager_getAidTableSize},
{"getRemainingAidTableSize", "()I",
(void*) nfcManager_getRemainingAidTableSize},
{"doselectUicc", "(I)I", (void*)nfcManager_doSelectUicc},
{"doGetSelectedUicc", "()I", (void*)nfcManager_doGetSelectedUicc},
{"setPreferredSimSlot", "(I)I", (void*)nfcManager_setPreferredSimSlot},
#endif
{"doSetNfcSecure", "(Z)Z", (void*)nfcManager_doSetNfcSecure},
};
/*******************************************************************************
**
** Function: register_com_android_nfc_NativeNfcManager
**
** Description: Regisgter JNI functions with Java Virtual Machine.
** e: Environment of JVM.
**
** Returns: Status of registration.
**
*******************************************************************************/
int register_com_android_nfc_NativeNfcManager(JNIEnv* e) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
PowerSwitch::getInstance().initialize(PowerSwitch::UNKNOWN_LEVEL);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
return jniRegisterNativeMethods(e, gNativeNfcManagerClassName, gMethods,
NELEM(gMethods));
}
/*******************************************************************************
**
** Function: startRfDiscovery
**
** Description: Ask stack to start polling and listening for devices.
** isStart: Whether to start.
**
** Returns: None
**
*******************************************************************************/
void startRfDiscovery(bool isStart) {
tNFA_STATUS status = NFA_STATUS_FAILED;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: is start=%d", __func__, isStart);
nativeNfcTag_acquireRfInterfaceMutexLock();
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
status = isStart ? NFA_StartRfDiscovery() : NFA_StopRfDiscovery();
if (status == NFA_STATUS_OK) {
sNfaEnableDisablePollingEvent.wait (); //wait for NFA_RF_DISCOVERY_xxxx_EVT
sRfEnabled = isStart;
} else {
LOG(ERROR) << StringPrintf(
"%s: Failed to start/stop RF discovery; error=0x%X", __func__, status);
}
nativeNfcTag_releaseRfInterfaceMutexLock();
}
/*******************************************************************************
**
** Function: isDiscoveryStarted
**
** Description: Indicates whether the discovery is started.
**
** Returns: True if discovery is started
**
*******************************************************************************/
bool isDiscoveryStarted() { return sRfEnabled; }
/*******************************************************************************
**
** Function: doStartupConfig
**
** Description: Configure the NFC controller.
**
** Returns: None
**
*******************************************************************************/
void doStartupConfig() {
#if (NXP_EXTNS == FALSE)
struct nfc_jni_native_data* nat = getNative(0, 0);
tNFA_STATUS stat = NFA_STATUS_FAILED;
//If polling for Active mode, set the ordering so that we choose Active over
//Passive mode first.
if (nat && (nat->tech_mask &
(NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE))) {
uint8_t act_mode_order_param[] = {0x01};
SyncEventGuard guard(sNfaSetConfigEvent);
stat = NFA_SetConfig(NCI_PARAM_ID_ACT_ORDER, sizeof(act_mode_order_param),
&act_mode_order_param[0]);
if (stat == NFA_STATUS_OK) sNfaSetConfigEvent.wait();
}
#endif
// configure RF polling frequency for each technology
static tNFA_DM_DISC_FREQ_CFG nfa_dm_disc_freq_cfg;
// values in the polling_frequency[] map to members of nfa_dm_disc_freq_cfg
std::vector<uint8_t> polling_frequency;
if (NfcConfig::hasKey(NAME_POLL_FREQUENCY))
polling_frequency = NfcConfig::getBytes(NAME_POLL_FREQUENCY);
if (polling_frequency.size() == 8) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: polling frequency", __func__);
memset(&nfa_dm_disc_freq_cfg, 0, sizeof(nfa_dm_disc_freq_cfg));
nfa_dm_disc_freq_cfg.pa = polling_frequency[0];
nfa_dm_disc_freq_cfg.pb = polling_frequency[1];
nfa_dm_disc_freq_cfg.pf = polling_frequency[2];
nfa_dm_disc_freq_cfg.pi93 = polling_frequency[3];
nfa_dm_disc_freq_cfg.pbp = polling_frequency[4];
nfa_dm_disc_freq_cfg.pk = polling_frequency[5];
nfa_dm_disc_freq_cfg.paa = polling_frequency[6];
nfa_dm_disc_freq_cfg.pfa = polling_frequency[7];
p_nfa_dm_rf_disc_freq_cfg = &nfa_dm_disc_freq_cfg;
}
// configure NFCC_CONFIG_CONTROL- NFCC allowed to manage RF configuration.
if (NFC_GetNCIVersion() != NCI_VERSION_1_0) {
uint8_t nfa_set_config[] = {0x01};
tNFA_STATUS status = NFA_SetConfig(NCI_PARAM_ID_NFCC_CONFIG_CONTROL,
sizeof(nfa_set_config), &nfa_set_config[0]);
if (status != NFA_STATUS_OK) {
LOG(ERROR) << __func__ << ": Failed to configure NFCC_CONFIG_CONTROL";
}
#if (NXP_EXTNS == TRUE)
send_flush_ram_to_flash();
#endif
}
}
/*******************************************************************************
**
** Function: nfcManager_isNfcActive
**
** Description: Used externaly to determine if NFC is active or not.
**
** Returns: 'true' if the NFC stack is running, else 'false'.
**
*******************************************************************************/
bool nfcManager_isNfcActive() { return sIsNfaEnabled; }
/*******************************************************************************
**
** Function: startStopPolling
**
** Description: Start or stop polling.
** isStartPolling: true to start polling; false to stop
*polling.
**
** Returns: None.
**
*******************************************************************************/
void startStopPolling(bool isStartPolling) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter; isStart=%u", __func__, isStartPolling);
startRfDiscovery(false);
if (isStartPolling)
startPolling_rfDiscoveryDisabled(0);
else
stopPolling_rfDiscoveryDisabled();
startRfDiscovery(true);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
}
static tNFA_STATUS startPolling_rfDiscoveryDisabled(
tNFA_TECHNOLOGY_MASK tech_mask) {
tNFA_STATUS stat = NFA_STATUS_FAILED;
if (tech_mask == 0)
tech_mask =
NfcConfig::getUnsigned(NAME_POLLING_TECH_MASK, DEFAULT_TECH_MASK);
nativeNfcTag_acquireRfInterfaceMutexLock();
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enable polling", __func__);
stat = NFA_EnablePolling(tech_mask);
if (stat == NFA_STATUS_OK) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: wait for enable event", __func__);
sPollingEnabled = true;
sNfaEnableDisablePollingEvent.wait(); // wait for NFA_POLL_ENABLED_EVT
} else {
LOG(ERROR) << StringPrintf("%s: fail enable polling; error=0x%X", __func__,
stat);
}
nativeNfcTag_releaseRfInterfaceMutexLock();
return stat;
}
static tNFA_STATUS stopPolling_rfDiscoveryDisabled() {
tNFA_STATUS stat = NFA_STATUS_FAILED;
nativeNfcTag_acquireRfInterfaceMutexLock();
SyncEventGuard guard(sNfaEnableDisablePollingEvent);
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: disable polling", __func__);
stat = NFA_DisablePolling();
if (stat == NFA_STATUS_OK) {
sPollingEnabled = false;
sNfaEnableDisablePollingEvent.wait(); // wait for NFA_POLL_DISABLED_EVT
} else {
LOG(ERROR) << StringPrintf("%s: fail disable polling; error=0x%X", __func__,
stat);
}
nativeNfcTag_releaseRfInterfaceMutexLock();
return stat;
}
#if(NXP_EXTNS == TRUE)
/*******************************************************************************
**
** Function: nfcManager_changeDiscoveryTech
**
** Description: set listen mode
** e: JVM environment.
** o: Java object.
**
** Returns: None.
**
*******************************************************************************/
static void nfcManager_changeDiscoveryTech(JNIEnv* e, jobject o, jint pollTech, jint listenTech)
{
DLOG_IF(INFO, nfc_debug_enabled)<< StringPrintf("Enter :%s pollTech = 0x%x, listenTech = 0x%x", __func__, pollTech, listenTech);
NFA_ChangeDiscoveryTech(pollTech, listenTech);
}
/*******************************************************************************
**
** Function: nfcManager_checkNfcStateBusy()
**
** Description This function returns whether NFC process is busy or not.
**
** Returns if Nfc state busy return true otherwise false.
**
*******************************************************************************/
bool nfcManager_checkNfcStateBusy()
{
bool status = false;
if(NFA_checkNfcStateBusy() == true)
status = true;
return status;
}
void enableLastRfDiscovery()
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter", __FUNCTION__);
RoutingManager::getInstance().configureOffHostNfceeTechMask();
nfcManager_enableDiscovery(NULL, NULL,
mDiscParams.technologies_mask,
mDiscParams.enable_lptd,
mDiscParams.reader_mode,
mDiscParams.enable_host_routing,
mDiscParams.enable_p2p,
true);
}
void storeLastDiscoveryParams(int technologies_mask, bool enable_lptd,
bool reader_mode, bool enable_host_routing ,bool enable_p2p, bool restart)
{
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: enter", __FUNCTION__);
mDiscParams.technologies_mask = technologies_mask;
mDiscParams.enable_lptd = enable_lptd;
mDiscParams.reader_mode = reader_mode;
mDiscParams.enable_p2p = enable_p2p;
mDiscParams.enable_host_routing = enable_host_routing;
mDiscParams.restart = restart;
}
#if(NXP_EXTNS == TRUE)
/**********************************************************************************
**
** Function: nfcManager_getFwVersion
**
** Description: To get the FW Version
**
** Returns: int fw version as below four byte format
** [0x00 0xROM_CODE_V 0xFW_MAJOR_NO 0xFW_MINOR_NO]
**
**********************************************************************************/
static jint nfcManager_getFwVersion(JNIEnv * e, jobject o) {
(void)e;
(void)o;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
tNFA_STATUS status = NFA_STATUS_FAILED;
// bool stat = false; /*commented to eliminate
// unused variable warning*/
jint version = 0, temp = 0;
tNFC_FW_VERSION nfc_native_fw_version;
if (!sIsNfaEnabled) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("NFC does not enabled!!");
return status;
}
memset(&nfc_native_fw_version, 0, sizeof(nfc_native_fw_version));
nfc_native_fw_version = nfc_ncif_getFWVersion();
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"FW Version: %x.%x.%x", nfc_native_fw_version.rom_code_version,
nfc_native_fw_version.major_version,
nfc_native_fw_version.minor_version);
temp = nfc_native_fw_version.rom_code_version;
version = temp << 16;
temp = nfc_native_fw_version.major_version;
version |= temp << 8;
version |= nfc_native_fw_version.minor_version;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: exit; version =0x%X", __func__, version);
return version;
}
/*******************************************************************************
**
** Class: Command
**
** Description: This class serves as base class for all propreitary
** commands for special FW mode of operation.
** It also holds reference to the HAL entry point functions.
** This class provides template for methods which can operate on
** command frames.It has default implementation for send() API
** which can be shared by all subclasses.
** This class shall not be instantiated.
** It should be treated as an abstracted class.
*******************************************************************************/
class Command {
public:
/*Response wait time*/
uint32_t rspTimeout;
/*Retrial count limit to handle failure rsp*/
int32_t retryCount;
/*Name of the command*/
char *name;
/*Reference to NFC adapter instance*/
NfcAdaptation &nfcAdapter;
/*Reference to HAL manager*/
tHAL_NFC_ENTRY *halMgr;
/*Constructor*/
Command() : nfcAdapter(NfcAdaptation::GetInstance()) {
rspTimeout = 0;
retryCount = 0;
name = NULL;
/*Retreive reference to HAL function manager*/
halMgr = nfcAdapter.GetHalEntryFuncs();
}
/*Overidable method list*/
virtual tNFA_STATUS preProcessor()
{ return 0;}
virtual tNFA_STATUS send(uint8_t *rsp_len, uint8_t *rsp_buf) {
return NFA_STATUS_OK;
}
virtual tNFA_STATUS send(uint8_t *pData4Tx, uint8_t dataLen, uint8_t *rsp_len,
uint8_t *rsp_buf) {
return NxpPropCmd_send(pData4Tx, dataLen, rsp_len, rsp_buf, rspTimeout,
halMgr);
}
virtual tNFA_STATUS postProcessor(uint8_t rsp_len, uint8_t *rsp_buf) {
return NFA_STATUS_OK;
}
virtual ~Command() {}
};
/*******************************************************************************
**
** Class: cmdEnablePassThru
**
** Description: This child class provides command frame. It also provides the
** API for validity check(preprocessor), sending command and
** post processing the response.
**
*******************************************************************************/
class cmdEnablePassThru : public Command {
private:
uint8_t cmd_buf[5];
public:
/*Constructor*/
cmdEnablePassThru(uint8_t modulationTyp, uint32_t timeoutVal,
uint32_t retryCnt) {
/*Set the command specific parameters*/
name = (char *)"RDR_PASS_THRU_MODE_ENABLE";
retryCount = retryCnt;
rspTimeout = timeoutVal;
/*Create the command frame*/
cmd_buf[0] = 0x2F;
cmd_buf[1] = 0x1C;
cmd_buf[2] = 0x02;
cmd_buf[3] = modulationTyp;
cmd_buf[4] = 0x00;
}
tNFA_STATUS send(uint8_t *rsp_len, uint8_t *rsp_buf) {
return Command::send(cmd_buf, sizeof(cmd_buf), rsp_len, rsp_buf);
}
tNFA_STATUS preProcessor() {
tNFA_STATUS status = NFA_STATUS_OK;
SecureElement &se = SecureElement::getInstance();
/*Reject request if secure element is listening*/
if (se.isActivatedInListenMode()) {
LOG(ERROR) << StringPrintf("%s: Denying access due to SE listen mode active", __func__);
status = NFA_STATUS_REJECTED;
}
/*Reject request if wired mode is ongoing*/
if (se.mIsWiredModeOpen == true) {
LOG(ERROR) << StringPrintf("%s: Denying access due to Wired session is ongoing", __func__);
status = NFA_STATUS_REJECTED;
}
if (android::sRfEnabled) {
/* Call the NFA_StopRfDiscovery to synchronize JNI, stack and FW*/
android::startRfDiscovery(false);
/*Stop RF discovery to reconfigure*/
/* [START]poll*/
{
uint8_t enable_discover[] = {0x21, 0x03, 0x03, 0x01, 0x00, 0x01};
uint8_t disable_discover[] = {0x21, 0x06, 0x01, 0x00};
status = android::NxpNfc_Write_Cmd_Common(sizeof(enable_discover),
enable_discover);
if (status == NFA_STATUS_OK)
status = android::NxpNfc_Write_Cmd_Common(sizeof(disable_discover),
disable_discover);
}
/*[END]poll*/
}
return status;
}
};
/*******************************************************************************
**
** Class: cmdDisablePassThru
**
** Description: This child class provides command frame. It also provides the
** API for validity check(preprocessor), sending command and
** post processing the response.
**
*******************************************************************************/
class cmdDisablePassThru : public Command {
private:
uint8_t cmd_buf[3];
public:
/*Constructor*/
cmdDisablePassThru(uint32_t timeoutVal, uint32_t retryCnt) {
/*Set the command specific parameters*/
name = (char *)"RDR_PASS_THRU_MODE_DISABLE";
retryCount = retryCnt;
rspTimeout = timeoutVal;
/*Create the command frame*/
cmd_buf[0] = 0x2F;
cmd_buf[1] = 0x1A;
cmd_buf[2] = 0x00;
}
tNFA_STATUS send(uint8_t *rsp_len, uint8_t *rsp_buf) {
return Command::send(cmd_buf, sizeof(cmd_buf), rsp_len, rsp_buf);
}
tNFA_STATUS preProcessor() {
/*Reject request if NFA layer is not enabled*/
if (!android::sIsNfaEnabled
) {
LOG(ERROR) << StringPrintf("%s: Denying request due to disabled NFA layer", __func__);
return NFA_STATUS_REJECTED;
}
/*Stop RF discovery in case RF is enabled*/
if (android::sRfEnabled && android::sIsNfaEnabled) {
// Stop RF discovery to reconfigure
android::startRfDiscovery(false);
}
return NFA_STATUS_OK;
}
tNFA_STATUS postProcessor(uint8_t rsp_len, uint8_t *rsp_buf) {
/*Start RF discovery in case RF is enabled*/
if (!android::sRfEnabled && android::sIsNfaEnabled)
android::startRfDiscovery(true);
return NFA_STATUS_OK;
}
};
/*******************************************************************************
**
** Class: cmdTransceive
**
** Description: Sends the iCode proprietary transcieve app command.
** This child class provides command frame. It also provides the
** API for validity check(preprocessor), sending command and
** post processing the response.
**
**
*******************************************************************************/
class cmdTransceive : public Command {
private:
uint8_t cmd_buf[258];
public:
/*Constructor*/
cmdTransceive(uint32_t timeoutVal, uint32_t retryCnt) {
/*Set the command specific parameters*/
name = (char *)"RDR_PASS_THRU_MODE_XCV";
retryCount = retryCnt;
rspTimeout = timeoutVal;
/*Create the command frame*/
cmd_buf[0] = 0x2F;
cmd_buf[1] = 0x1B;
}
tNFA_STATUS send(uint8_t *pData4Tx, uint8_t dataLen, uint8_t *rsp_len,
uint8_t *rsp_buf) {
cmd_buf[2] = dataLen;
memcpy(&cmd_buf[3], pData4Tx, dataLen);
return Command::send(cmd_buf, (dataLen + CMD_HDR_SIZE_XCV), rsp_len,
rsp_buf);
}
tNFA_STATUS preProcessor() {
tNFA_STATUS status = NFA_STATUS_OK;
SecureElement &se = SecureElement::getInstance();
if (!android::sIsNfaEnabled
) {
LOG(ERROR) << StringPrintf("%s: Denying access due to SE listen mode active", __func__);
return NFA_STATUS_REJECTED;
}
/*Reject request if wired mode is ongoing*/
if (se.mIsWiredModeOpen == true) {
LOG(ERROR) << StringPrintf("%s: Denying access due to Wired session is ongoing", __func__);
status = NFA_STATUS_REJECTED;
}
return status;
}
};
/*******************************************************************************
**
** Class: rdrPassThru
**
** Description: This is a factory class which creates command instances
** It creates transceive commands only when it is in busy mode.
**
** Returns: byte[]
**
*******************************************************************************/
class rdrPassThru {
private:
uint32_t state;
typedef enum { IDLE, BUSY } STATE_e;
public:
rdrPassThru() { state = IDLE; }
Command *createCommand(uint32_t rqst, uint32_t modulationType) {
switch (rqst) {
case RDR_PASS_THRU_MODE_ENABLE:
state = BUSY;
return new cmdEnablePassThru(modulationType, RDR_PASS_THRU_ENABLE_TIMEOUT, 3);
case RDR_PASS_THRU_MODE_DISABLE:
state = BUSY;
return new cmdDisablePassThru(RDR_PASS_THRU_DISABLE_TIMEOUT, 3);
case RDR_PASS_THRU_MODE_XCV:
state = BUSY;
return new cmdTransceive(RDR_PASS_THRU_DISABLE_TIMEOUT, 0);
default:
return NULL;
}
return NULL;
}
tNFA_STATUS condOfUseSatisfied(uint32_t rqst, uint32_t modulationTyp) {
if (rqst > RDR_PASS_THRU_MODE_XCV ||
modulationTyp > RDR_PASS_THRU_MOD_TYPE_LIMIT) {
LOG(ERROR) << StringPrintf("%s: Denying access due to Incorrect parameters", __func__);
return NFA_STATUS_REJECTED;
}
if (rqst == RDR_PASS_THRU_MODE_XCV && state == IDLE) {
LOG(ERROR) << StringPrintf("%s: Denying access due to Incorrect parameters", __func__);
return NFA_STATUS_REJECTED;
}
return NFA_STATUS_OK;
}
void destroy(Command *pCmdInstance) { delete pCmdInstance; }
void destroy(uint32_t rqst, Command *pCmdInstance) {
if (rqst == RDR_PASS_THRU_MODE_DISABLE)
state = IDLE;
delete pCmdInstance;
}
};
rdrPassThru rdrPassThruMgr;
/*******************************************************************************
**
** Function: nfcManager_readerPassThruMode()
**
** Description: Sends proprietary command to NFC controller to manage
** special FW mode
**
** Returns: byte[]
**
*******************************************************************************/
static jbyteArray nfcManager_readerPassThruMode(
JNIEnv * e, jobject o, jbyte rqst, jbyte modulationTyp) {
tNFA_STATUS ret_stat = NFA_STATUS_OK;
uint8_t rsp_buf[255];
uint8_t rsp_len = 0;
jbyteArray buf = NULL;
static const char fn[] = "nfcManager_readerPassThruMode";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s:enter", fn);
/*1. Check if the criteria for sending the command is satisfied*/
if ((ret_stat = rdrPassThruMgr.condOfUseSatisfied(rqst, modulationTyp)) ==
NFA_STATUS_OK) {
/*1.1. Retreive the requested command instance from reader pass through
* manager (command factory)*/
Command *pCommand = rdrPassThruMgr.createCommand(rqst, modulationTyp);
/*1.2. Check valid command instance and command specific criteria for use */
if (pCommand != NULL && pCommand->preProcessor() == NFA_STATUS_OK) {
do {
/*1.2.1. Send the command to NFC controller*/
ret_stat = pCommand->send(&rsp_len, rsp_buf);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s:Invoked", pCommand->name);
/*1.2.2. Incase of failure retry till the retrial limit is met*/
} while (ret_stat != NFA_STATUS_OK && pCommand->retryCount-- > 0);
/*1.2.3. Invoke command post processor*/
if (ret_stat == NFA_STATUS_OK)
ret_stat = pCommand->postProcessor(rsp_len, rsp_buf);
/*1.2.4. Delete the command instance*/
rdrPassThruMgr.destroy(rqst, pCommand);
}
} else {
/*2. If the criteria for sending the command is not satisfied; frame error
* rsp*/
rsp_len = sizeof(tNFA_STATUS);
rsp_buf[0] = NFA_STATUS_FAILED;
}
/*3. Set JNI variables for sending response to application*/
buf = e->NewByteArray(rsp_len);
e->SetByteArrayRegion(buf, 0, rsp_len, (jbyte *)rsp_buf);
return buf;
}
/*******************************************************************************
**
** Function: nfcManager_transceiveAppData()
**
** Description: Sends the proprietary transcieve app command
**
** Returns: byte[]
**
*******************************************************************************/
static jbyteArray nfcManager_transceiveAppData(JNIEnv * e, jobject o,
jbyteArray data) {
tNFA_STATUS ret_stat = NFA_STATUS_OK;
uint8_t rsp_buf[255];
uint8_t rsp_len = 0;
uint8_t *dataBuf = NULL;
uint16_t dataLen = 0;
jbyteArray buf = NULL;
static const char fn[] = "nfcManager_transceiveAppData";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s:enter", fn);
/*1. Check if the criteria for sending the command is satisfied*/
if ((ret_stat = rdrPassThruMgr.condOfUseSatisfied(RDR_PASS_THRU_MODE_XCV,
0)) == NFA_STATUS_OK) {
/*1.1. Retreive the requested command instance from reader pass through
* manager (command factory)*/
Command *pCommand = rdrPassThruMgr.createCommand(RDR_PASS_THRU_MODE_XCV, 0);
/*1.2. Check valid command instance and command specific criteria for use */
if (pCommand != NULL && pCommand->preProcessor() == NFA_STATUS_OK) {
/*1.2.1. Determine application data length */
ScopedByteArrayRW bytes(e, data);
dataBuf = const_cast<uint8_t *>(reinterpret_cast<uint8_t *>(&bytes[0]));
dataLen = bytes.size();
do {
/*1.2.2. Send the command to NFC controller*/
ret_stat = pCommand->send(dataBuf, dataLen, &rsp_len, rsp_buf);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s:Invoked", pCommand->name);
/*1.2.3. Incase of failure retry till the retrial limit is met*/
} while (ret_stat != NFA_STATUS_OK && pCommand->retryCount-- > 0);
/*1.2.4. Invoke command post processor*/
if (ret_stat == NFA_STATUS_OK)
ret_stat = pCommand->postProcessor(rsp_len, rsp_buf);
/*1.2.5. Delete the command instance*/
rdrPassThruMgr.destroy(pCommand);
}
} else {
/*2. If the criteria for sending the command is not satisfied; frame error
* rsp*/
rsp_len = sizeof(tNFA_STATUS);
rsp_buf[0] = NFA_STATUS_FAILED;
}
/*3. Set JNI variables for sending response to application*/
buf = e->NewByteArray(rsp_len);
e->SetByteArrayRegion(buf, 0, rsp_len, (jbyte *)rsp_buf);
return buf;
}
/*******************************************************************************
**
** Function: nfcManager_isNfccBusy
**
** Description: Check If NFCC is busy
**
** Returns: True if NFCC is busy.
**
*******************************************************************************/
static bool nfcManager_isNfccBusy(JNIEnv*, jobject) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: ENTER", __func__);
bool statBusy = false;
if (sSeRfActive || gActivated ) {
LOG(ERROR) << StringPrintf("%s:FAIL RF session ongoing", __func__);
statBusy = true;
}
return statBusy;
}
static int nfcManager_setTransitConfig(JNIEnv * e, jobject o,
jstring config) {
(void)e;
(void)o;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
std::string transitConfig = ConvertJavaStrToStdString(e, config);
SyncEventGuard guard(sNfaTransitConfigEvent);
int stat = NFA_SetTransitConfig(transitConfig);
if (stat != NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: NFA_SetTransitConfig failed", __func__);
} else {
if(sNfaTransitConfigEvent.wait(10 * ONE_SECOND_MS) == false) {
LOG(ERROR) << StringPrintf("Nfa transitConfig Event has terminated");
}
}
return stat;
}
/*******************************************************************************
**
** Function: ConvertJavaStrToStdString
**
** Description: Convert Jstring to string
** e: JVM environment.
** o: Java object.
** s: Jstring.
**
** Returns: std::string
**
*******************************************************************************/
static std::string ConvertJavaStrToStdString(JNIEnv * env, jstring s) {
if (!s) return "";
const jclass strClass = env->GetObjectClass(s);
const jmethodID getBytes =
env->GetMethodID(strClass, "getBytes", "(Ljava/lang/String;)[B");
const jbyteArray strJbytes = (jbyteArray)env->CallObjectMethod(
s, getBytes, env->NewStringUTF("UTF-8"));
size_t length = (size_t)env->GetArrayLength(strJbytes);
jbyte* pBytes = env->GetByteArrayElements(strJbytes, NULL);
std::string ret = std::string((char*)pBytes, length);
env->ReleaseByteArrayElements(strJbytes, pBytes, JNI_ABORT);
env->DeleteLocalRef(strJbytes);
env->DeleteLocalRef(strClass);
return ret;
}
/*******************************************************************************
**
** Function: nfcManager_getAidTableSize
** Description: Get the maximum supported size for AID routing table.
**
** e: JVM environment.
** o: Java object.
**
*******************************************************************************/
static jint nfcManager_getAidTableSize (JNIEnv*, jobject )
{
return NFA_GetAidTableSize();
}
/*******************************************************************************
**
** Function: nfcManager_getRemainingAidTableSize
** Description: Get the remaining size of AID routing table.
**
** e: JVM environment.
** o: Java object.
**
*******************************************************************************/
static jint nfcManager_getRemainingAidTableSize (JNIEnv* , jobject )
{
return NFA_GetRemainingAidTableSize();
}
/*******************************************************************************
**
** Function: nfcManager_doSelectUicc()
**
** Description: Select the preferred UICC slot
**
** Returns: Returns status as below
** DUAL_UICC_ERROR_STATUS_UNKNOWN when error status not defined.
** DUAL_UICC_ERROR_NFC_TURNING_OFF when Nfc is Disabling,
** DUAL_UICC_ERROR_INVALID_SLOT when slot id mismatch,
** DUAL_UICC_ERROR_NFCC_BUSY when RF session is ongoing
** DUAL_UICC_FEATURE_NOT_AVAILABLE when feature not available
** UICC_NOT_CONFIGURED when UICC is not configured.
*******************************************************************************/
static int nfcManager_doSelectUicc(JNIEnv* e, jobject o, jint uiccSlot) {
(void)e;
(void)o;
int retStat = DUAL_UICC_ERROR_STATUS_UNKNOWN;
tNFA_STATUS status = NFA_STATUS_FAILED;
NativeJniExtns& jniExtns = NativeJniExtns::getInstance();
if (!isDynamicUiccEnabled) {
if (!jniExtns.isExtensionPresent()) {
retStat = nfcManager_staticDualUicc_Precondition(uiccSlot);
if (sSeRfActive || SecureElement::getInstance().isRfFieldOn()) {
LOG(ERROR) << StringPrintf("%s:FAIL RF session ongoing", __func__);
retStat = DUAL_UICC_ERROR_NFCC_BUSY;
}
if (retStat != UICC_NOT_CONFIGURED) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("staticDualUicc_Precondition failed.");
return retStat;
}
}
status = nfcManager_setPreferredSimSlot(NULL, NULL, uiccSlot);
if (status == NFA_STATUS_OK) retStat = UICC_CONFIGURED;
} else {
retStat = DUAL_UICC_FEATURE_NOT_AVAILABLE;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s: Dual uicc not supported retStat = %d", __func__, retStat);
}
return retStat;
}
/*******************************************************************************
**
** Function: nfcManager_doGetSelectedUicc()
**
** Description: get the current selected active UICC
**
** Returns: UICC id
**
*******************************************************************************/
static int nfcManager_doGetSelectedUicc(JNIEnv * e, jobject o) {
uint8_t uicc_stat = STATUS_UNKNOWN_ERROR;
if (!isDynamicUiccEnabled) {
uicc_stat =
SecureElement::getInstance().getUiccStatus(sCurrentSelectedUICCSlot);
} else {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s: dual uicc not supported ", __func__);
uicc_stat = DUAL_UICC_FEATURE_NOT_AVAILABLE;
}
return uicc_stat;
}
/**********************************************************************************
**
** Function: nfcManager_staticDualUicc_Precondition
**
** Description: Performs precondition checks before switching UICC
**
** Returns: Returns status as below
** DUAL_UICC_ERROR_NFC_TURNING_OFF when Nfc is Disabling,
** DUAL_UICC_ERROR_INVALID_SLOT when slot id mismatch,
** DUAL_UICC_FEATURE_NOT_AVAILABLE when feature not available,
** UICC_NOT_CONFIGURED when UICC is not configured.
**********************************************************************************/
static int nfcManager_staticDualUicc_Precondition(int uiccSlot) {
if (isDynamicUiccEnabled) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"%s:Dual UICC feature not available . Returning", __func__);
return DUAL_UICC_FEATURE_NOT_AVAILABLE;
}
int retStat = UICC_NOT_CONFIGURED;
if (sIsDisabling) {
LOG(ERROR) << StringPrintf(
"%s:FAIL Nfc is Disabling : Switch UICC not allowed", __func__);
retStat = DUAL_UICC_ERROR_NFC_TURNING_OFF;
} else if ((uiccSlot != 0x01) && (uiccSlot != 0x02)) {
LOG(ERROR) << StringPrintf("%s: Invalid slot id", __func__);
retStat = DUAL_UICC_ERROR_INVALID_SLOT;
}
return retStat;
}
/*******************************************************************************
**
** Function: nfcManager_setPreferredSimSlot()
**
** Description: This api is used to select a particular UICC slot.
**
**
** Returns: success/failure
**
*******************************************************************************/
static int nfcManager_setPreferredSimSlot(JNIEnv* e, jobject o,
jint uiccSlot) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s : uiccslot : %d : enter", __func__, uiccSlot);
int retStat = UICC_NOT_CONFIGURED;
NativeJniExtns& jniExtns = NativeJniExtns::getInstance();
if (!isDynamicUiccEnabled) {
if (jniExtns.isExtensionPresent()) {
retStat = nfcManager_staticDualUicc_Precondition(uiccSlot);
if (retStat != UICC_NOT_CONFIGURED) {
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("staticDualUicc_Precondition failed.");
return NFA_STATUS_FAILED;
}
}
sCurrentSelectedUICCSlot = uiccSlot;
NFA_SetPreferredUiccId(
(uiccSlot == 2) ? (SecureElement::getInstance().EE_HANDLE_0xF8 &
~NFA_HANDLE_GROUP_EE)
: (SecureElement::getInstance().EE_HANDLE_0xF4 &
~NFA_HANDLE_GROUP_EE));
}
return NFA_STATUS_OK;
}
#endif
} /* namespace android */
/* namespace android */
/*******************************************************************************
**
** Function: nfcManager_getUiccId()
**
** Description:
**
** Returns: success/failure
**
*******************************************************************************/
jint nfcManager_getUiccId(jint uicc_slot)
{
if((uicc_slot == 0x00) || (uicc_slot == 0x01))
{
return 0x02;
}
else if(uicc_slot == 0x02)
{
return 0x04;
}
else
{
return 0xFF;
}
}
jint nfcManager_getUiccRoute(jint uicc_slot)
{
if(uicc_slot == 0x01)
{
return 0x480;
}
else if(uicc_slot == 0x02)
{
return 0x481;
}
else
{
return 0xFF;
}
}
#endif