diff options
-rwxr-xr-x | nci/jni/NativeNfcManager.cpp | 70 | ||||
-rwxr-xr-x | nci/jni/NativeNfcTag.cpp | 101 | ||||
-rwxr-xr-x | nci/jni/NfcTag.cpp | 85 | ||||
-rwxr-xr-x | nci/jni/NfcTag.h | 49 | ||||
-rw-r--r-- | nci/jni/Pn544Interop.cpp | 153 | ||||
-rw-r--r-- | nci/jni/Pn544Interop.h | 64 | ||||
-rwxr-xr-x | nci/jni/SecureElement.cpp | 34 | ||||
-rwxr-xr-x | nci/jni/SecureElement.h | 3 |
8 files changed, 501 insertions, 58 deletions
diff --git a/nci/jni/NativeNfcManager.cpp b/nci/jni/NativeNfcManager.cpp index c3e76fa..5fd3025 100755 --- a/nci/jni/NativeNfcManager.cpp +++ b/nci/jni/NativeNfcManager.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "PowerSwitch.h" #include "JavaClassConstants.h" +#include "Pn544Interop.h" extern "C" { @@ -85,6 +86,7 @@ namespace android const char* gNativeNfcManagerClassName = "com/android/nfc/dhimpl/NativeNfcManager"; const char* gNativeNfcSecureElementClassName = "com/android/nfc/dhimpl/NativeNfcSecureElement"; void doStartupConfig (); + void startStopPolling (bool isStartPolling); } @@ -284,6 +286,7 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat case NFA_ACTIVATED_EVT: // NFC link/protocol activated ALOGD("%s: NFA_ACTIVATED_EVT: gIsSelectingRfInterface=%d", __FUNCTION__, gIsSelectingRfInterface); + NfcTag::getInstance().setActivationState (); if (gIsSelectingRfInterface) { nativeNfcTag_doConnectStatus(true); @@ -294,13 +297,14 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat if (isPeerToPeer(eventData->activated)) { ALOGD("%s: NFA_ACTIVATED_EVT; is p2p", __FUNCTION__); - break; } - NfcTag::getInstance().connectionEventHandler (connEvent, eventData); + else if (pn544InteropIsBusy() == false) + NfcTag::getInstance().connectionEventHandler (connEvent, eventData); break; case NFA_DEACTIVATED_EVT: // NFC link/protocol deactivated ALOGD("%s: NFA_DEACTIVATED_EVT Type: %u, gIsTagDeactivating: %d", __FUNCTION__, eventData->deactivated.type,gIsTagDeactivating); + NfcTag::getInstance().setDeactivationState (eventData->deactivated); if (gIsTagDeactivating || gIsSelectingRfInterface) { if (gIsTagDeactivating) @@ -333,6 +337,7 @@ static void nfaConnectionCallback (UINT8 connEvent, tNFA_CONN_EVT_DATA* eventDat 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); @@ -720,7 +725,8 @@ static jboolean nfcManager_doInitialize (JNIEnv* e, jobject o) } TheEnd: - PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER); + if (sIsNfaEnabled) + PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER); ALOGD ("%s: exit", __FUNCTION__); return sIsNfaEnabled ? JNI_TRUE : JNI_FALSE; } @@ -767,7 +773,7 @@ static void nfcManager_enableDiscovery (JNIEnv* e, jobject o) { ALOGD ("%s: wait for enable event", __FUNCTION__); sDiscoveryEnabled = true; - sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_START_EVT + sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_ENABLED_EVT ALOGD ("%s: got enabled event", __FUNCTION__); } else @@ -810,6 +816,7 @@ void nfcManager_disableDiscovery (JNIEnv* e, jobject o) tNFA_STATUS status = NFA_STATUS_OK; ALOGD ("%s: enter;", __FUNCTION__); + pn544InteropAbortNow (); if (sDiscoveryEnabled == false) { ALOGD ("%s: already disabled", __FUNCTION__); @@ -826,7 +833,7 @@ void nfcManager_disableDiscovery (JNIEnv* e, jobject o) if (status == NFA_STATUS_OK) { sDiscoveryEnabled = false; - sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_STOP_EVT + sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_DISABLED_EVT } else ALOGE ("%s: Failed to disable polling; error=0x%X", __FUNCTION__, status); @@ -994,7 +1001,7 @@ static jboolean nfcManager_doDeinitialize (JNIEnv* e, jobject o) ALOGD ("%s: enter", __FUNCTION__); sIsDisabling = true; - + pn544InteropAbortNow (); SecureElement::getInstance().finalize (); if (sIsNfaEnabled) @@ -1676,5 +1683,56 @@ bool nfcManager_isNfcActive() } +/******************************************************************************* +** +** Function: startStopPolling +** +** Description: Start or stop polling. +** isStartPolling: true to start polling; false to stop polling. +** +** Returns: None. +** +*******************************************************************************/ +void startStopPolling (bool isStartPolling) +{ + ALOGD ("%s: enter; isStart=%u", __FUNCTION__, isStartPolling); + tNFA_STATUS stat = NFA_STATUS_FAILED; + + startRfDiscovery (false); + if (isStartPolling) + { + tNFA_TECHNOLOGY_MASK tech_mask = DEFAULT_TECH_MASK; + unsigned long num = 0; + if (GetNumValue(NAME_POLLING_TECH_MASK, &num, sizeof(num))) + tech_mask = num; + + SyncEventGuard guard (sNfaEnableDisablePollingEvent); + ALOGD ("%s: enable polling", __FUNCTION__); + stat = NFA_EnablePolling (tech_mask); + if (stat == NFA_STATUS_OK) + { + ALOGD ("%s: wait for enable event", __FUNCTION__); + sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_ENABLED_EVT + } + else + ALOGE ("%s: fail enable polling; error=0x%X", __FUNCTION__, stat); + } + else + { + SyncEventGuard guard (sNfaEnableDisablePollingEvent); + ALOGD ("%s: disable polling", __FUNCTION__); + stat = NFA_DisablePolling (); + if (stat == NFA_STATUS_OK) + { + sNfaEnableDisablePollingEvent.wait (); //wait for NFA_POLL_DISABLED_EVT + } + else + ALOGE ("%s: fail disable polling; error=0x%X", __FUNCTION__, stat); + } + startRfDiscovery (true); + ALOGD ("%s: exit", __FUNCTION__); +} + + } /* namespace android */ diff --git a/nci/jni/NativeNfcTag.cpp b/nci/jni/NativeNfcTag.cpp index e7352c5..8c0426b 100755 --- a/nci/jni/NativeNfcTag.cpp +++ b/nci/jni/NativeNfcTag.cpp @@ -25,6 +25,7 @@ #include "Mutex.h" #include "IntervalTimer.h" #include "JavaClassConstants.h" +#include "Pn544Interop.h" extern "C" { @@ -488,18 +489,28 @@ static jint nativeNfcTag_doConnect (JNIEnv *e, jobject o, jint targetHandle) int i = targetHandle; struct nfc_jni_native_data *nat = getNative (0, 0); NfcTag& natTag = NfcTag::getInstance (); - sNeedToSwitchRf = false; + int retCode = NFCSTATUS_SUCCESS; + sNeedToSwitchRf = false; if (i >= NfcTag::MAX_NUM_TECHNOLOGY) { ALOGE ("%s: Handle not found", __FUNCTION__); - return NFCSTATUS_FAILED; + retCode = NFCSTATUS_FAILED; + goto TheEnd; + } + + if (natTag.getActivationState() != NfcTag::Active) + { + ALOGE ("%s: tag already deactivated", __FUNCTION__); + retCode = NFCSTATUS_FAILED; + goto TheEnd; } if (natTag.mTechLibNfcTypes[i] != NFC_PROTOCOL_ISO_DEP) { ALOGD ("%s() Nfc type = %d, do nothing for non ISO_DEP", __FUNCTION__, natTag.mTechLibNfcTypes[i]); - return NFCSTATUS_SUCCESS; + retCode = NFCSTATUS_SUCCESS; + goto TheEnd; } if (natTag.mTechList[i] == TARGET_TYPE_ISO14443_3A || natTag.mTechList[i] == TARGET_TYPE_ISO14443_3B) @@ -514,7 +525,9 @@ static jint nativeNfcTag_doConnect (JNIEnv *e, jobject o, jint targetHandle) return (switchRfInterface (NFA_INTERFACE_ISO_DEP) ? NFCSTATUS_SUCCESS : NFCSTATUS_FAILED); } - return NFCSTATUS_SUCCESS; +TheEnd: + ALOGD ("%s: exit 0x%X", __FUNCTION__, retCode); + return retCode; } /******************************************************************************* @@ -530,22 +543,30 @@ static jint nativeNfcTag_doConnect (JNIEnv *e, jobject o, jint targetHandle) *******************************************************************************/ static int reSelect (tNFA_INTF_TYPE rfInterface) { - ALOGD ("%s: rf intf = %d", __FUNCTION__, rfInterface); + ALOGD ("%s: enter; rf intf = %d", __FUNCTION__, rfInterface); NfcTag& natTag = NfcTag::getInstance (); - ALOGD ("%s: NFA_Deactivate()", __FUNCTION__); tNFA_STATUS status; int rVal = 1; do { + //if tag has shutdown, abort this method + if (NfcTag::getInstance ().isNdefDetectionTimedOut()) + { + ALOGD ("%s: ndef detection timeout; break", __FUNCTION__); + rVal = STATUS_CODE_TARGET_LOST; + break; + } + { SyncEventGuard g (sReconnectEvent); gIsTagDeactivating = true; sGotDeactivate = false; - if (NFA_STATUS_OK != (status = NFA_Deactivate (TRUE))) + ALOGD ("%s: deactivate to sleep", __FUNCTION__); + if (NFA_STATUS_OK != (status = NFA_Deactivate (TRUE))) //deactivate to sleep state { - ALOGE ("%s: NFA_Deactivate failed, status = %d", __FUNCTION__, status); + ALOGE ("%s: deactivate failed, status = %d", __FUNCTION__, status); break; } @@ -555,8 +576,9 @@ static int reSelect (tNFA_INTF_TYPE rfInterface) } } - if (! NfcTag::getInstance ().isActivated ()) + if (NfcTag::getInstance ().getActivationState () != NfcTag::Sleep) { + ALOGD ("%s: tag is not in sleep", __FUNCTION__); rVal = STATUS_CODE_TARGET_LOST; break; } @@ -567,7 +589,7 @@ static int reSelect (tNFA_INTF_TYPE rfInterface) SyncEventGuard g2 (sReconnectEvent); sConnectWaitingForComplete = JNI_TRUE; - ALOGD ("%s: NFA_Select()", __FUNCTION__); + ALOGD ("%s: select interface %u", __FUNCTION__, rfInterface); gIsSelectingRfInterface = true; if (NFA_STATUS_OK != (status = NFA_Select (natTag.mTechHandles[0], natTag.mTechLibNfcTypes[0], rfInterface))) { @@ -578,15 +600,15 @@ static int reSelect (tNFA_INTF_TYPE rfInterface) sConnectOk = false; if (sReconnectEvent.wait (1000) == false) //if timeout occured { - ALOGE ("%s: wait response timeout", __FUNCTION__); + ALOGE ("%s: timeout waiting for select", __FUNCTION__); break; } } - ALOGD("%s: done waiting on NFA_Select() sConnectOk=%d", __FUNCTION__, sConnectOk); - if (! NfcTag::getInstance ().isActivated ()) + ALOGD("%s: select completed; sConnectOk=%d", __FUNCTION__, sConnectOk); + if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) { - ALOGD("%s: Tag no longer active", __FUNCTION__); + ALOGD("%s: tag is not active", __FUNCTION__); rVal = STATUS_CODE_TARGET_LOST; break; } @@ -596,6 +618,7 @@ static int reSelect (tNFA_INTF_TYPE rfInterface) sConnectWaitingForComplete = JNI_FALSE; gIsTagDeactivating = false; gIsSelectingRfInterface = false; + ALOGD ("%s: exit; status=%d", __FUNCTION__, rVal); return rVal; } @@ -650,22 +673,26 @@ static bool switchRfInterface (tNFA_INTF_TYPE rfInterface) *******************************************************************************/ static jint nativeNfcTag_doReconnect (JNIEnv *e, jobject o) { - ALOGD ("%s", __FUNCTION__); - - tNFA_INTF_TYPE intf = NFA_INTERFACE_FRAME; + ALOGD ("%s: enter", __FUNCTION__); + int retCode = NFCSTATUS_SUCCESS; NfcTag& natTag = NfcTag::getInstance (); + if (natTag.getActivationState() != NfcTag::Active) + { + ALOGE ("%s: tag already deactivated", __FUNCTION__); + retCode = NFCSTATUS_FAILED; + goto TheEnd; + } + // this is only supported for type 2 or 4 (ISO_DEP) tags if (natTag.mTechLibNfcTypes[0] == NFA_PROTOCOL_ISO_DEP) - intf = NFA_INTERFACE_ISO_DEP; + retCode = reSelect(NFA_INTERFACE_ISO_DEP); else if (natTag.mTechLibNfcTypes[0] == NFA_PROTOCOL_T2T) - intf = NFA_INTERFACE_FRAME; - else - { - return 0; // success - } + retCode = reSelect(NFA_INTERFACE_FRAME); - return reSelect(intf); +TheEnd: + ALOGD ("%s: exit 0x%X", __FUNCTION__, retCode); + return retCode; } @@ -707,9 +734,9 @@ static jboolean nativeNfcTag_doDisconnect (JNIEnv *e, jobject o) gGeneralTransceiveTimeout = DEFAULT_GENERAL_TRANS_TIMEOUT; - if (NfcTag::getInstance ().isActivated () == false) + if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) { - ALOGD ("%s: tag already deactivated", __FUNCTION__); + ALOGE ("%s: tag already deactivated", __FUNCTION__); goto TheEnd; } @@ -783,7 +810,7 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da uint32_t bufLen = 0; jint *targetLost = NULL; - if (! NfcTag::getInstance ().isActivated ()) + if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) { if (statusTargetLost) { @@ -844,7 +871,7 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da break; } - if (! NfcTag::getInstance ().isActivated ()) + if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) { ALOGE ("%s: already deactivated", __FUNCTION__); if (targetLost) @@ -1036,7 +1063,7 @@ void nativeNfcTag_doCheckNdefResult (tNFA_STATUS status, uint32_t maxSize, uint3 ** o: Java object. ** ndefInfo: NDEF info. ** -** Returns: Status code. +** Returns: Status code; 0 is success. ** *******************************************************************************/ static jint nativeNfcTag_doCheckNdef (JNIEnv *e, jobject o, jintArray ndefInfo) @@ -1053,9 +1080,9 @@ static jint nativeNfcTag_doCheckNdef (JNIEnv *e, jobject o, jintArray ndefInfo) return JNI_FALSE; } - if (NfcTag::getInstance ().isActivated () == false) + if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) { - ALOGE ("%s: tag not present", __FUNCTION__); + ALOGE ("%s: tag already deactivated", __FUNCTION__); goto TheEnd; } @@ -1065,7 +1092,7 @@ static jint nativeNfcTag_doCheckNdef (JNIEnv *e, jobject o, jintArray ndefInfo) if (status != NFA_STATUS_OK) { - ALOGE ("%s: NFA_RwDetectNDef failed, status = %d", __FUNCTION__, status); + ALOGE ("%s: NFA_RwDetectNDef failed, status = 0x%X", __FUNCTION__, status); goto TheEnd; } @@ -1106,9 +1133,15 @@ static jint nativeNfcTag_doCheckNdef (JNIEnv *e, jobject o, jintArray ndefInfo) e->ReleaseIntArrayElements (ndefInfo, ndef, 0); status = NFA_STATUS_FAILED; } + else if (sCheckNdefStatus == NFA_STATUS_TIMEOUT) + { + pn544InteropStopPolling (); + status = sCheckNdefStatus; + } else { ALOGD ("%s: unknown status 0x%X", __FUNCTION__, sCheckNdefStatus); + status = sCheckNdefStatus; } TheEnd: @@ -1118,7 +1151,7 @@ TheEnd: ALOGE ("%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __FUNCTION__, errno); } sCheckNdefWaitingForComplete = JNI_FALSE; - ALOGD ("%s: exit; status=%u", __FUNCTION__, status); + ALOGD ("%s: exit; status=0x%X", __FUNCTION__, status); return status; } @@ -1183,7 +1216,7 @@ static jboolean nativeNfcTag_doPresenceCheck (JNIEnv *e, jobject o) return JNI_FALSE; } - if (NfcTag::getInstance ().isActivated () == false) + if (NfcTag::getInstance ().getActivationState () != NfcTag::Active) { ALOGD ("%s: tag already deactivated", __FUNCTION__); return JNI_FALSE; diff --git a/nci/jni/NfcTag.cpp b/nci/jni/NfcTag.cpp index e996fdd..b94355f 100755 --- a/nci/jni/NfcTag.cpp +++ b/nci/jni/NfcTag.cpp @@ -37,17 +37,18 @@ extern "C" *******************************************************************************/ NfcTag::NfcTag () : mNativeData (NULL), - mIsActivated (false), + mActivationState (Idle), mProtocol(NFC_PROTOCOL_UNKNOWN), mNumTechList (0), mtT1tMaxMessageSize (0), - mReadCompletedStatus (NFA_STATUS_OK) + mReadCompletedStatus (NFA_STATUS_OK), + mLastKovioUidLen (0), + mNdefDetectionTimedOut (false) { memset (mTechList, 0, sizeof(mTechList)); memset (mTechHandles, 0, sizeof(mTechHandles)); memset (mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes)); memset (mTechParams, 0, sizeof(mTechParams)); - mLastKovioUidLen = 0; memset(mLastKovioUid, 0, NFC_KOVIO_MAX_LEN); } @@ -81,7 +82,7 @@ NfcTag& NfcTag::getInstance () void NfcTag::initialize (nfc_jni_native_data* native) { mNativeData = native; - mIsActivated = false; + mActivationState = Idle; mProtocol = NFC_PROTOCOL_UNKNOWN; mNumTechList = 0; mtT1tMaxMessageSize = 0; @@ -108,16 +109,55 @@ void NfcTag::abort () /******************************************************************************* ** -** Function: isActivated +** Function: getActivationState ** -** Description: Is tag activated? +** Description: What is the current state: Idle, Sleep, or Activated. ** -** Returns: True if tag is activated. +** Returns: Idle, Sleep, or Activated. ** *******************************************************************************/ -bool NfcTag::isActivated () +NfcTag::ActivationState NfcTag::getActivationState () { - return mIsActivated; + return mActivationState; +} + + +/******************************************************************************* +** +** Function: setDeactivationState +** +** Description: Set the current state: Idle or Sleep. +** deactivated: state of deactivation. +** +** Returns: None. +** +*******************************************************************************/ +void NfcTag::setDeactivationState (tNFA_DEACTIVATED& deactivated) +{ + static const char fn [] = "NfcTag::setDeactivationState"; + mActivationState = Idle; + mNdefDetectionTimedOut = false; + if (deactivated.type == NFA_DEACTIVATE_TYPE_SLEEP) + mActivationState = Sleep; + ALOGD ("%s: state=%u", fn, mActivationState); +} + + +/******************************************************************************* +** +** Function: setActivationState +** +** Description: Set the current state to Active. +** +** Returns: None. +** +*******************************************************************************/ +void NfcTag::setActivationState () +{ + static const char fn [] = "NfcTag::setActivationState"; + mNdefDetectionTimedOut = false; + mActivationState = Active; + ALOGD ("%s: state=%u", fn, mActivationState); } @@ -1204,6 +1244,21 @@ bool NfcTag::isT2tNackResponse (const UINT8* response, UINT32 responseLen) /******************************************************************************* ** +** Function: isNdefDetectionTimedOut +** +** Description: Whether NDEF-detection algorithm timed out. +** +** Returns: True if NDEF-detection algorithm timed out. +** +*******************************************************************************/ +bool NfcTag::isNdefDetectionTimedOut () +{ + return mNdefDetectionTimedOut; +} + + +/******************************************************************************* +** ** Function: connectionEventHandler ** ** Description: Handle connection-related events. @@ -1215,6 +1270,8 @@ bool NfcTag::isT2tNackResponse (const UINT8* response, UINT32 responseLen) *******************************************************************************/ void NfcTag::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* data) { + static const char fn [] = "NfcTag::connectionEventHandler"; + switch (event) { case NFA_DISC_RESULT_EVT: @@ -1236,7 +1293,6 @@ void NfcTag::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* data) tNFA_ACTIVATED& activated = data->activated; if (IsSameKovio(activated)) break; - mIsActivated = true; mProtocol = activated.activate_ntf.protocol; calculateT1tMaxMessageSize (activated); discoverTechnologies (activated); @@ -1245,7 +1301,6 @@ void NfcTag::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* data) break; case NFA_DEACTIVATED_EVT: - mIsActivated = false; mProtocol = NFC_PROTOCOL_UNKNOWN; resetTechnologies (); break; @@ -1257,6 +1312,14 @@ void NfcTag::connectionEventHandler (UINT8 event, tNFA_CONN_EVT_DATA* data) mReadCompleteEvent.notifyOne (); } break; + + case NFA_NDEF_DETECT_EVT: + { + tNFA_NDEF_DETECT& ndef_detect = data->ndef_detect; + mNdefDetectionTimedOut = ndef_detect.status == NFA_STATUS_TIMEOUT; + if (mNdefDetectionTimedOut) + ALOGE ("%s: NDEF detection timed out", fn); + } } } diff --git a/nci/jni/NfcTag.h b/nci/jni/NfcTag.h index 76a6bb7..7fa56ee 100755 --- a/nci/jni/NfcTag.h +++ b/nci/jni/NfcTag.h @@ -30,6 +30,7 @@ extern "C" class NfcTag { public: + enum ActivationState {Idle, Sleep, Active}; static const int MAX_NUM_TECHNOLOGY = 10; //max number of technologies supported by one or more tags int mTechList [MAX_NUM_TECHNOLOGY]; //array of NFC technologies according to NFC service int mTechHandles [MAX_NUM_TECHNOLOGY]; //array of tag handles according to NFC service @@ -100,18 +101,42 @@ public: /******************************************************************************* ** - ** Function: isActivated + ** Function: getActivationState ** - ** Description: Is tag activated? + ** Description: What is the current state: Idle, Sleep, or Activated. ** - ** Returns: True if tag is activated. + ** Returns: Idle, Sleep, or Activated. ** *******************************************************************************/ - bool isActivated (); + ActivationState getActivationState (); /******************************************************************************* ** + ** Function: setDeactivationState + ** + ** Description: Set the current state: Idle or Sleep. + ** deactivated: state of deactivation. + ** + ** Returns: None. + ** + *******************************************************************************/ + void setDeactivationState (tNFA_DEACTIVATED& deactivated); + + + /******************************************************************************* + ** + ** Function: setActivationState + ** + ** Description: Set the current state to Active. + ** + ** Returns: None. + ** + *******************************************************************************/ + void setActivationState (); + + /******************************************************************************* + ** ** Function: getProtocol ** ** Description: Get the protocol of the current tag. @@ -197,15 +222,27 @@ public: *******************************************************************************/ bool isT2tNackResponse (const UINT8* response, UINT32 responseLen); + /******************************************************************************* + ** + ** Function: isNdefDetectionTimedOut + ** + ** Description: Whether NDEF-detection algorithm has timed out. + ** + ** Returns: True if NDEF-detection algorithm timed out. + ** + *******************************************************************************/ + bool isNdefDetectionTimedOut (); + private: nfc_jni_native_data* mNativeData; - bool mIsActivated; + ActivationState mActivationState; tNFC_PROTOCOL mProtocol; int mtT1tMaxMessageSize; //T1T max NDEF message size tNFA_STATUS mReadCompletedStatus; + int mLastKovioUidLen; // len of uid of last Kovio tag activated + bool mNdefDetectionTimedOut; // whether NDEF detection algorithm timed out tNFC_RF_TECH_PARAMS mTechParams [MAX_NUM_TECHNOLOGY]; //array of technology parameters SyncEvent mReadCompleteEvent; - int mLastKovioUidLen; // len of uid of last Kovio tag activated struct timespec mLastKovioTime; // time of last Kovio tag activation UINT8 mLastKovioUid[NFC_KOVIO_MAX_LEN]; // uid of last Kovio tag activated diff --git a/nci/jni/Pn544Interop.cpp b/nci/jni/Pn544Interop.cpp new file mode 100644 index 0000000..be92c75 --- /dev/null +++ b/nci/jni/Pn544Interop.cpp @@ -0,0 +1,153 @@ +/* + * 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. + */ + +/***************************************************************************** +** +** Name: Pn544Interop.cpp +** +** Description: Implement operations that provide compatibility with NXP +** PN544 controller. Specifically facilitate peer-to-peer +** operations with PN544 controller. +** +*****************************************************************************/ +#include "OverrideLog.h" +#include "Pn544Interop.h" +#include "IntervalTimer.h" +#include "Mutex.h" +#include "NfcTag.h" +namespace android +{ + extern void startStopPolling (bool isStartPolling); +} + + +/***************************************************************************** +** +** private variables and functions +** +*****************************************************************************/ + + +static const int gIntervalTime = 1000; //millisecond between the check to restore polling +static IntervalTimer gTimer; +static Mutex gMutex; +static void pn544InteropStartPolling (union sigval); //callback function for interval timer +static bool gIsBusy = false; //is timer busy? +static bool gAbortNow = false; //stop timer during next callback + + +/******************************************************************************* +** +** Function: pn544InteropStopPolling +** +** Description: Stop polling to let NXP PN544 controller poll. +** PN544 should activate in P2P mode. +** +** Returns: None +** +*******************************************************************************/ +void pn544InteropStopPolling () +{ + ALOGD ("%s: enter", __FUNCTION__); + gMutex.lock (); + gTimer.kill (); + android::startStopPolling (false); + gIsBusy = true; + gAbortNow = false; + gTimer.set (gIntervalTime, pn544InteropStartPolling); //after some time, start polling again + gMutex.unlock (); + ALOGD ("%s: exit", __FUNCTION__); +} + + +/******************************************************************************* +** +** Function: pn544InteropStartPolling +** +** Description: Start polling when activation state is idle. +** sigval: Unused. +** +** Returns: None +** +*******************************************************************************/ +void pn544InteropStartPolling (union sigval) +{ + ALOGD ("%s: enter", __FUNCTION__); + gMutex.lock (); + NfcTag::ActivationState state = NfcTag::getInstance ().getActivationState (); + + if (gAbortNow) + { + ALOGD ("%s: abort now", __FUNCTION__); + gIsBusy = false; + goto TheEnd; + } + + if (state == NfcTag::Idle) + { + ALOGD ("%s: start polling", __FUNCTION__); + android::startStopPolling (true); + gIsBusy = false; + } + else + { + ALOGD ("%s: try again later", __FUNCTION__); + gTimer.set (gIntervalTime, pn544InteropStartPolling); //after some time, start polling again + } + +TheEnd: + gMutex.unlock (); + ALOGD ("%s: exit", __FUNCTION__); +} + + +/******************************************************************************* +** +** Function: pn544InteropIsBusy +** +** Description: Is the code performing operations? +** +** Returns: True if the code is busy. +** +*******************************************************************************/ +bool pn544InteropIsBusy () +{ + bool isBusy = false; + gMutex.lock (); + isBusy = gIsBusy; + gMutex.unlock (); + ALOGD ("%s: %u", __FUNCTION__, isBusy); + return isBusy; +} + + +/******************************************************************************* +** +** Function: pn544InteropAbortNow +** +** Description: Request to abort all operations. +** +** Returns: None. +** +*******************************************************************************/ +void pn544InteropAbortNow () +{ + ALOGD ("%s", __FUNCTION__); + gMutex.lock (); + gAbortNow = true; + gMutex.unlock (); +} + diff --git a/nci/jni/Pn544Interop.h b/nci/jni/Pn544Interop.h new file mode 100644 index 0000000..c9a2df6 --- /dev/null +++ b/nci/jni/Pn544Interop.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +/***************************************************************************** +** +** Name: Pn544Interop.h +** +** Description: Implement operations that provide compatibility with NXP +** PN544 controller. Specifically facilitate peer-to-peer +** operations with PN544 controller. +** +*****************************************************************************/ +#pragma once +#include "NfcJniUtil.h" + + +/******************************************************************************* +** +** Function: pn544InteropStopPolling +** +** Description: Stop polling to let NXP PN544 controller poll. +** PN544 should activate in P2P mode. +** +** Returns: None +** +*******************************************************************************/ +void pn544InteropStopPolling (); + + +/******************************************************************************* +** +** Function: pn544InteropIsBusy +** +** Description: Is the code performing operations? +** +** Returns: True if the code is busy. +** +*******************************************************************************/ +bool pn544InteropIsBusy (); + + +/******************************************************************************* +** +** Function: pn544InteropAbortNow +** +** Description: Request to abort all operations. +** +** Returns: None. +** +*******************************************************************************/ +void pn544InteropAbortNow (); diff --git a/nci/jni/SecureElement.cpp b/nci/jni/SecureElement.cpp index b67ee66..2f94047 100755 --- a/nci/jni/SecureElement.cpp +++ b/nci/jni/SecureElement.cpp @@ -70,7 +70,9 @@ SecureElement::SecureElement () mCommandStatus (NFA_STATUS_OK), mIsPiping (false), mCurrentRouteSelection (NoRoute), - mActualResponseSize(0) + mActualResponseSize(0), + mUseOberthurWarmReset (false), + mOberthurWarmResetCommand (3) { memset (&mEeInfo, 0, sizeof(mEeInfo)); memset (&mUiccInfo, 0, sizeof(mUiccInfo)); @@ -153,6 +155,12 @@ bool SecureElement::initialize (nfc_jni_native_data* native) mActiveSeOverride = num; ALOGD ("%s: Active SE override: %d", fn, mActiveSeOverride); + if (GetNumValue("OBERTHUR_WARM_RESET_COMMAND", &num, sizeof(num))) + { + mUseOberthurWarmReset = true; + mOberthurWarmResetCommand = (UINT8) num; + } + mActiveEeHandle = NFA_HANDLE_INVALID; mNfaHciHandle = NFA_HANDLE_INVALID; @@ -777,6 +785,21 @@ bool SecureElement::disconnectEE (jint seID) ALOGD("%s: seID=0x%X; handle=0x%04x", fn, seID, eeHandle); + if (mUseOberthurWarmReset) + { + //send warm-reset command to Oberthur secure element which deselects the applet; + //this is an Oberthur-specific command; + ALOGD("%s: try warm-reset on pipe id 0x%X; cmd=0x%X", fn, mNewPipeId, mOberthurWarmResetCommand); + SyncEventGuard guard (mRegistryEvent); + nfaStat = NFA_HciSetRegistry (mNfaHciHandle, mNewPipeId, + 1, 1, &mOberthurWarmResetCommand); + if (nfaStat == NFA_STATUS_OK) + { + mRegistryEvent.wait (); + ALOGD("%s: completed warm-reset on pipe 0x%X", fn, mNewPipeId); + } + } + if (mNewSourceGate) { SyncEventGuard guard (mDeallocateGateEvent); @@ -1718,6 +1741,15 @@ void SecureElement::nfaHciCallback (tNFA_HCI_EVT event, tNFA_HCI_EVT_DATA* event } break; + case NFA_HCI_SET_REG_RSP_EVT: //received response to write registry command + { + tNFA_HCI_REGISTRY& registry = eventData->registry; + ALOGD ("%s: NFA_HCI_SET_REG_RSP_EVT; status=0x%X; pipe=0x%X", fn, registry.status, registry.pipe); + SyncEventGuard guard (sSecElem.mRegistryEvent); + sSecElem.mRegistryEvent.notifyOne (); + break; + } + default: ALOGE ("%s: unknown event code=0x%X ????", fn, event); break; diff --git a/nci/jni/SecureElement.h b/nci/jni/SecureElement.h index b887513..6a5cebd 100755 --- a/nci/jni/SecureElement.h +++ b/nci/jni/SecureElement.h @@ -372,6 +372,8 @@ private: bool mIsPiping; //is a pipe connected to the controller? RouteSelection mCurrentRouteSelection; int mActualResponseSize; //number of bytes in the response received from secure element + bool mUseOberthurWarmReset; //whether to use warm-reset command + UINT8 mOberthurWarmResetCommand; //warm-reset command byte tNFA_EE_INFO mEeInfo [MAX_NUM_EE]; //actual size stored in mActualNumEe tNFA_EE_DISCOVER_REQ mUiccInfo; tNFA_HCI_GET_GATE_PIPE_LIST mHciCfg; @@ -389,6 +391,7 @@ private: SyncEvent mAidAddRemoveEvent; SyncEvent mTransceiveEvent; SyncEvent mVerInfoEvent; + SyncEvent mRegistryEvent; UINT8 mVerInfo [3]; UINT8 mResponseData [MAX_RESPONSE_SIZE]; RouteDataSet mRouteDataSet; //routing data |