summaryrefslogtreecommitdiffstats
path: root/nci/jni/NativeNfcTag.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'nci/jni/NativeNfcTag.cpp')
-rwxr-xr-xnci/jni/NativeNfcTag.cpp1507
1 files changed, 1507 insertions, 0 deletions
diff --git a/nci/jni/NativeNfcTag.cpp b/nci/jni/NativeNfcTag.cpp
new file mode 100755
index 0000000..0ba7b21
--- /dev/null
+++ b/nci/jni/NativeNfcTag.cpp
@@ -0,0 +1,1507 @@
+/*
+ * 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.
+ */
+
+#include <semaphore.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include "OverrideLog.h"
+#include "NfcJniUtil.h"
+#include "NfcTag.h"
+#include "config.h"
+#include "Mutex.h"
+#include "IntervalTimer.h"
+#include "JavaClassConstants.h"
+#include "Pn544Interop.h"
+
+extern "C"
+{
+ #include "nfa_api.h"
+ #include "nfa_rw_api.h"
+ #include "ndef_utils.h"
+ #include "rw_api.h"
+}
+namespace android
+{
+ extern nfc_jni_native_data* getNative(JNIEnv *e, jobject o);
+ extern bool nfcManager_isNfcActive();
+ extern int gGeneralTransceiveTimeout;
+}
+
+
+/*****************************************************************************
+**
+** public variables and functions
+**
+*****************************************************************************/
+namespace android
+{
+ bool gIsTagDeactivating = false; // flag for nfa callback indicating we are deactivating for RF interface switch
+ bool gIsSelectingRfInterface = false; // flag for nfa callback indicating we are selecting for RF interface switch
+}
+
+
+/*****************************************************************************
+**
+** private variables and functions
+**
+*****************************************************************************/
+namespace android
+{
+
+
+// Pre-defined tag type values. These must match the values in
+// framework Ndef.java for Google public NFC API.
+#define NDEF_UNKNOWN_TYPE -1
+#define NDEF_TYPE1_TAG 1
+#define NDEF_TYPE2_TAG 2
+#define NDEF_TYPE3_TAG 3
+#define NDEF_TYPE4_TAG 4
+#define NDEF_MIFARE_CLASSIC_TAG 101
+
+#define STATUS_CODE_TARGET_LOST 146 // this error code comes from the service
+
+static uint32_t sCheckNdefCurrentSize = 0;
+static tNFA_STATUS sCheckNdefStatus = 0; //whether tag already contains a NDEF message
+static bool sCheckNdefCapable = false; //whether tag has NDEF capability
+static tNFA_HANDLE sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
+static tNFA_INTF_TYPE sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
+static uint8_t* sTransceiveData = NULL;
+static uint32_t sTransceiveDataLen = 0;
+static bool sWaitingForTransceive = false;
+static bool sNeedToSwitchRf = false;
+static Mutex sRfInterfaceMutex;
+static uint32_t sReadDataLen = 0;
+static uint8_t* sReadData = NULL;
+static bool sIsReadingNdefMessage = false;
+static SyncEvent sReadEvent;
+static sem_t sWriteSem;
+static sem_t sFormatSem;
+static SyncEvent sTransceiveEvent;
+static SyncEvent sReconnectEvent;
+static sem_t sCheckNdefSem;
+static sem_t sPresenceCheckSem;
+static sem_t sMakeReadonlySem;
+static IntervalTimer sSwitchBackTimer; // timer used to tell us to switch back to ISO_DEP frame interface
+static jboolean sWriteOk = JNI_FALSE;
+static jboolean sWriteWaitingForComplete = JNI_FALSE;
+static bool sFormatOk = false;
+static jboolean sConnectOk = JNI_FALSE;
+static jboolean sConnectWaitingForComplete = JNI_FALSE;
+static bool sGotDeactivate = false;
+static uint32_t sCheckNdefMaxSize = 0;
+static bool sCheckNdefCardReadOnly = false;
+static jboolean sCheckNdefWaitingForComplete = JNI_FALSE;
+static int sCountTagAway = 0; //count the consecutive number of presence-check failures
+static tNFA_STATUS sMakeReadonlyStatus = NFA_STATUS_FAILED;
+static jboolean sMakeReadonlyWaitingForComplete = JNI_FALSE;
+
+static int reSelect (tNFA_INTF_TYPE rfInterface);
+static bool switchRfInterface(tNFA_INTF_TYPE rfInterface);
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_abortWaits
+**
+** Description: Unblock all thread synchronization objects.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_abortWaits ()
+{
+ ALOGD ("%s", __FUNCTION__);
+ {
+ SyncEventGuard g (sReadEvent);
+ sReadEvent.notifyOne ();
+ }
+ sem_post (&sWriteSem);
+ sem_post (&sFormatSem);
+ {
+ SyncEventGuard g (sTransceiveEvent);
+ sTransceiveEvent.notifyOne ();
+ }
+ {
+ SyncEventGuard g (sReconnectEvent);
+ sReconnectEvent.notifyOne ();
+ }
+
+ sem_post (&sCheckNdefSem);
+ sem_post (&sPresenceCheckSem);
+ sem_post (&sMakeReadonlySem);
+}
+
+
+/*******************************************************************************
+**
+** Function: switchBackTimerProc
+**
+** Description: Callback function for interval timer.
+**
+** Returns: None
+**
+*******************************************************************************/
+static void switchBackTimerProc (union sigval)
+{
+ ALOGD ("%s", __FUNCTION__);
+ switchRfInterface(NFA_INTERFACE_ISO_DEP);
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doReadCompleted
+**
+** Description: Receive the completion status of read operation. Called by
+** NFA_READ_CPLT_EVT.
+** status: Status of operation.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doReadCompleted (tNFA_STATUS status)
+{
+ ALOGD ("%s: status=0x%X; is reading=%u", __FUNCTION__, status, sIsReadingNdefMessage);
+
+ if (sIsReadingNdefMessage == false)
+ return; //not reading NDEF message right now, so just return
+
+ if (status != NFA_STATUS_OK)
+ {
+ sReadDataLen = 0;
+ if (sReadData)
+ free (sReadData);
+ sReadData = NULL;
+ }
+ SyncEventGuard g (sReadEvent);
+ sReadEvent.notifyOne ();
+}
+
+
+/*******************************************************************************
+**
+** Function: ndefHandlerCallback
+**
+** Description: Receive NDEF-message related events from stack.
+** event: Event code.
+** p_data: Event data.
+**
+** Returns: None
+**
+*******************************************************************************/
+static void ndefHandlerCallback (tNFA_NDEF_EVT event, tNFA_NDEF_EVT_DATA *eventData)
+{
+ ALOGD ("%s: event=%u, eventData=%p", __FUNCTION__, event, eventData);
+
+ switch (event)
+ {
+ case NFA_NDEF_REGISTER_EVT:
+ {
+ tNFA_NDEF_REGISTER& ndef_reg = eventData->ndef_reg;
+ ALOGD ("%s: NFA_NDEF_REGISTER_EVT; status=0x%X; h=0x%X", __FUNCTION__, ndef_reg.status, ndef_reg.ndef_type_handle);
+ sNdefTypeHandlerHandle = ndef_reg.ndef_type_handle;
+ }
+ break;
+
+ case NFA_NDEF_DATA_EVT:
+ {
+ ALOGD ("%s: NFA_NDEF_DATA_EVT; data_len = %lu", __FUNCTION__, eventData->ndef_data.len);
+ sReadDataLen = eventData->ndef_data.len;
+ sReadData = (uint8_t*) malloc (sReadDataLen);
+ memcpy (sReadData, eventData->ndef_data.p_data, eventData->ndef_data.len);
+ }
+ break;
+
+ default:
+ ALOGE ("%s: Unknown event %u ????", __FUNCTION__, event);
+ break;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doRead
+**
+** Description: Read the NDEF message on the tag.
+** e: JVM environment.
+** o: Java object.
+**
+** Returns: NDEF message.
+**
+*******************************************************************************/
+static jbyteArray nativeNfcTag_doRead (JNIEnv *e, jobject o)
+{
+ ALOGD ("%s: enter", __FUNCTION__);
+ tNFA_STATUS status = NFA_STATUS_FAILED;
+ jbyteArray buf = NULL;
+
+ sReadDataLen = 0;
+ if (sReadData != NULL)
+ {
+ free (sReadData);
+ sReadData = NULL;
+ }
+
+ if (sCheckNdefCurrentSize > 0)
+ {
+ {
+ SyncEventGuard g (sReadEvent);
+ sIsReadingNdefMessage = true;
+ status = NFA_RwReadNDef ();
+ sReadEvent.wait (); //wait for NFA_READ_CPLT_EVT
+ }
+ sIsReadingNdefMessage = false;
+
+ if (sReadDataLen > 0) //if stack actually read data from the tag
+ {
+ ALOGD ("%s: read %u bytes", __FUNCTION__, sReadDataLen);
+ buf = e->NewByteArray (sReadDataLen);
+ e->SetByteArrayRegion (buf, 0, sReadDataLen, (jbyte*) sReadData);
+ }
+ }
+ else
+ {
+ ALOGD ("%s: create emtpy buffer", __FUNCTION__);
+ static uint8_t* empty = (uint8_t*) "";
+ sReadDataLen = 0;
+ sReadData = (uint8_t*) malloc (1);
+ buf = e->NewByteArray (sReadDataLen);
+ e->SetByteArrayRegion (buf, 0, sReadDataLen, (jbyte*) sReadData);
+ }
+
+ if (sReadData)
+ {
+ free (sReadData);
+ sReadData = NULL;
+ }
+ sReadDataLen = 0;
+
+ ALOGD ("%s: exit", __FUNCTION__);
+ return buf;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doWriteStatus
+**
+** Description: Receive the completion status of write operation. Called
+** by NFA_WRITE_CPLT_EVT.
+** isWriteOk: Status of operation.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doWriteStatus (jboolean isWriteOk)
+{
+ if (sWriteWaitingForComplete != JNI_FALSE)
+ {
+ sWriteWaitingForComplete = JNI_FALSE;
+ sWriteOk = isWriteOk;
+ sem_post (&sWriteSem);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_formatStatus
+**
+** Description: Receive the completion status of format operation. Called
+** by NFA_FORMAT_CPLT_EVT.
+** isOk: Status of operation.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_formatStatus (bool isOk)
+{
+ sFormatOk = isOk;
+ sem_post (&sFormatSem);
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doWrite
+**
+** Description: Write a NDEF message to the tag.
+** e: JVM environment.
+** o: Java object.
+** buf: Contains a NDEF message.
+**
+** Returns: True if ok.
+**
+*******************************************************************************/
+static jboolean nativeNfcTag_doWrite (JNIEnv *e, jobject o, jbyteArray buf)
+{
+ jboolean result = JNI_FALSE;
+ tNFA_STATUS status = 0;
+ UINT32 len = 0;
+ UINT8* p_data = NULL;
+ const int maxBufferSize = 1024;
+ UINT8 buffer[maxBufferSize] = { 0 };
+ UINT32 curDataSize = 0;
+
+ len = (UINT32) e->GetArrayLength (buf);
+ p_data = (UINT8*) e->GetByteArrayElements (buf, NULL);
+
+ ALOGD ("%s: enter; len = %lu", __FUNCTION__, len);
+
+ /* Create the write semaphore */
+ if (sem_init (&sWriteSem, 0, 0) == -1)
+ {
+ ALOGE ("%s: semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
+ return JNI_FALSE;
+ }
+
+ sWriteWaitingForComplete = JNI_TRUE;
+ if (sCheckNdefStatus == NFA_STATUS_FAILED)
+ {
+ //if tag does not contain a NDEF message
+ //and tag is capable of storing NDEF message
+ if (sCheckNdefCapable)
+ {
+ ALOGD ("%s: try format", __FUNCTION__);
+ sem_init (&sFormatSem, 0, 0);
+ sFormatOk = false;
+ status = NFA_RwFormatTag ();
+ sem_wait (&sFormatSem);
+ sem_destroy (&sFormatSem);
+ if (sFormatOk == false) //if format operation failed
+ goto TheEnd;
+ }
+ ALOGD ("%s: try write", __FUNCTION__);
+ status = NFA_RwWriteNDef (p_data, len);
+ }
+ else if (len == 0)
+ {
+ //if (NXP TagWriter wants to erase tag) then create and write an empty ndef message
+ NDEF_MsgInit (buffer, maxBufferSize, &curDataSize);
+ status = NDEF_MsgAddRec (buffer, maxBufferSize, &curDataSize, NDEF_TNF_EMPTY, NULL, 0, NULL, 0, NULL, 0);
+ ALOGD ("%s: create empty ndef msg; status=%u; size=%lu", __FUNCTION__, status, curDataSize);
+ status = NFA_RwWriteNDef (buffer, curDataSize);
+ }
+ else
+ {
+ ALOGD ("%s: NFA_RwWriteNDef", __FUNCTION__);
+ status = NFA_RwWriteNDef (p_data, len);
+ }
+
+ if (status != NFA_STATUS_OK)
+ {
+ ALOGE ("%s: write/format error=%d", __FUNCTION__, status);
+ goto TheEnd;
+ }
+
+ /* Wait for write completion status */
+ sWriteOk = false;
+ if (sem_wait (&sWriteSem))
+ {
+ ALOGE ("%s: wait semaphore (errno=0x%08x)", __FUNCTION__, errno);
+ goto TheEnd;
+ }
+
+ result = sWriteOk;
+
+TheEnd:
+ /* Destroy semaphore */
+ if (sem_destroy (&sWriteSem))
+ {
+ ALOGE ("%s: failed destroy semaphore (errno=0x%08x)", __FUNCTION__, errno);
+ }
+ sWriteWaitingForComplete = JNI_FALSE;
+ ALOGD ("%s: exit; result=%d", __FUNCTION__, result);
+ return result;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doConnectStatus
+**
+** Description: Receive the completion status of connect operation.
+** isConnectOk: Status of the operation.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doConnectStatus (jboolean isConnectOk)
+{
+ if (sConnectWaitingForComplete != JNI_FALSE)
+ {
+ sConnectWaitingForComplete = JNI_FALSE;
+ sConnectOk = isConnectOk;
+ SyncEventGuard g (sReconnectEvent);
+ sReconnectEvent.notifyOne ();
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doDeactivateStatus
+**
+** Description: Receive the completion status of deactivate operation.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doDeactivateStatus (int status)
+{
+ sGotDeactivate = (status == 0);
+
+ SyncEventGuard g (sReconnectEvent);
+ sReconnectEvent.notifyOne ();
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doConnect
+**
+** Description: Connect to the tag in RF field.
+** e: JVM environment.
+** o: Java object.
+** targetHandle: Handle of the tag.
+**
+** Returns: Must return NXP status code, which NFC service expects.
+**
+*******************************************************************************/
+static jint nativeNfcTag_doConnect (JNIEnv *e, jobject o, jint targetHandle)
+{
+ ALOGD ("%s: targetHandle = %d", __FUNCTION__, targetHandle);
+ int i = targetHandle;
+ struct nfc_jni_native_data *nat = getNative (0, 0);
+ NfcTag& natTag = NfcTag::getInstance ();
+ int retCode = NFCSTATUS_SUCCESS;
+
+ sNeedToSwitchRf = false;
+ if (i >= NfcTag::MAX_NUM_TECHNOLOGY)
+ {
+ ALOGE ("%s: Handle not found", __FUNCTION__);
+ 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]);
+ retCode = NFCSTATUS_SUCCESS;
+ goto TheEnd;
+ }
+
+ if (natTag.mTechList[i] == TARGET_TYPE_ISO14443_3A || natTag.mTechList[i] == TARGET_TYPE_ISO14443_3B)
+ {
+ ALOGD ("%s: switching to tech: %d need to switch rf intf to frame", __FUNCTION__, natTag.mTechList[i]);
+ // connecting to NfcA or NfcB don't actually switch until/unless we get a transceive
+ sNeedToSwitchRf = true;
+ }
+ else
+ {
+ // connecting back to IsoDep or NDEF
+ return (switchRfInterface (NFA_INTERFACE_ISO_DEP) ? NFCSTATUS_SUCCESS : NFCSTATUS_FAILED);
+ }
+
+TheEnd:
+ ALOGD ("%s: exit 0x%X", __FUNCTION__, retCode);
+ return retCode;
+}
+
+/*******************************************************************************
+**
+** Function: reSelect
+**
+** Description: Deactivates the tag and re-selects it with the specified
+** rf interface.
+**
+** Returns: status code, 0 on success, 1 on failure,
+** 146 (defined in service) on tag lost
+**
+*******************************************************************************/
+static int reSelect (tNFA_INTF_TYPE rfInterface)
+{
+ ALOGD ("%s: enter; rf intf = %d", __FUNCTION__, rfInterface);
+ NfcTag& natTag = NfcTag::getInstance ();
+
+ 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;
+ ALOGD ("%s: deactivate to sleep", __FUNCTION__);
+ if (NFA_STATUS_OK != (status = NFA_Deactivate (TRUE))) //deactivate to sleep state
+ {
+ ALOGE ("%s: deactivate failed, status = %d", __FUNCTION__, status);
+ break;
+ }
+
+ if (sReconnectEvent.wait (1000) == false) //if timeout occurred
+ {
+ ALOGE ("%s: timeout waiting for deactivate", __FUNCTION__);
+ }
+ }
+
+ if (NfcTag::getInstance ().getActivationState () != NfcTag::Sleep)
+ {
+ ALOGD ("%s: tag is not in sleep", __FUNCTION__);
+ rVal = STATUS_CODE_TARGET_LOST;
+ break;
+ }
+
+ gIsTagDeactivating = false;
+
+ {
+ SyncEventGuard g2 (sReconnectEvent);
+
+ sConnectWaitingForComplete = JNI_TRUE;
+ ALOGD ("%s: select interface %u", __FUNCTION__, rfInterface);
+ gIsSelectingRfInterface = true;
+ if (NFA_STATUS_OK != (status = NFA_Select (natTag.mTechHandles[0], natTag.mTechLibNfcTypes[0], rfInterface)))
+ {
+ ALOGE ("%s: NFA_Select failed, status = %d", __FUNCTION__, status);
+ break;
+ }
+
+ sConnectOk = false;
+ if (sReconnectEvent.wait (1000) == false) //if timeout occured
+ {
+ ALOGE ("%s: timeout waiting for select", __FUNCTION__);
+ break;
+ }
+ }
+
+ ALOGD("%s: select completed; sConnectOk=%d", __FUNCTION__, sConnectOk);
+ if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
+ {
+ ALOGD("%s: tag is not active", __FUNCTION__);
+ rVal = STATUS_CODE_TARGET_LOST;
+ break;
+ }
+ rVal = (sConnectOk) ? 0 : 1;
+ } while (0);
+
+ sConnectWaitingForComplete = JNI_FALSE;
+ gIsTagDeactivating = false;
+ gIsSelectingRfInterface = false;
+ ALOGD ("%s: exit; status=%d", __FUNCTION__, rVal);
+ return rVal;
+}
+
+/*******************************************************************************
+**
+** Function: switchRfInterface
+**
+** Description: Switch controller's RF interface to frame, ISO-DEP, or NFC-DEP.
+** rfInterface: Type of RF interface.
+**
+** Returns: True if ok.
+**
+*******************************************************************************/
+static bool switchRfInterface (tNFA_INTF_TYPE rfInterface)
+{
+ ALOGD ("%s: rf intf = %d", __FUNCTION__, rfInterface);
+ NfcTag& natTag = NfcTag::getInstance ();
+
+ if (natTag.mTechLibNfcTypes[0] != NFC_PROTOCOL_ISO_DEP)
+ {
+ ALOGD ("%s: protocol: %d not ISO_DEP, do nothing", __FUNCTION__, natTag.mTechLibNfcTypes[0]);
+ return true;
+ }
+
+ sRfInterfaceMutex.lock ();
+ ALOGD ("%s: new rf intf = %d, cur rf intf = %d", __FUNCTION__, rfInterface, sCurrentRfInterface);
+
+ bool rVal = true;
+ if (rfInterface != sCurrentRfInterface)
+ {
+ if (rVal = (0 == reSelect(rfInterface)))
+ {
+ sCurrentRfInterface = rfInterface;
+ }
+ }
+
+ sRfInterfaceMutex.unlock ();
+ return rVal;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doReconnect
+**
+** Description: Re-connect to the tag in RF field.
+** e: JVM environment.
+** o: Java object.
+**
+** Returns: Status code.
+**
+*******************************************************************************/
+static jint nativeNfcTag_doReconnect (JNIEnv *e, jobject o)
+{
+ 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)
+ retCode = reSelect(NFA_INTERFACE_ISO_DEP);
+ else if (natTag.mTechLibNfcTypes[0] == NFA_PROTOCOL_T2T)
+ retCode = reSelect(NFA_INTERFACE_FRAME);
+
+TheEnd:
+ ALOGD ("%s: exit 0x%X", __FUNCTION__, retCode);
+ return retCode;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doHandleReconnect
+**
+** Description: Re-connect to the tag in RF field.
+** e: JVM environment.
+** o: Java object.
+** targetHandle: Handle of the tag.
+**
+** Returns: Status code.
+**
+*******************************************************************************/
+static jint nativeNfcTag_doHandleReconnect (JNIEnv *e, jobject o, jint targetHandle)
+{
+ ALOGD ("%s: targetHandle = %d", __FUNCTION__, targetHandle);
+ return nativeNfcTag_doConnect (e, o, targetHandle);
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doDisconnect
+**
+** Description: Deactivate the RF field.
+** e: JVM environment.
+** o: Java object.
+**
+** Returns: True if ok.
+**
+*******************************************************************************/
+static jboolean nativeNfcTag_doDisconnect (JNIEnv *e, jobject o)
+{
+ ALOGD ("%s: enter", __FUNCTION__);
+ struct nfc_jni_native_data *nat = getNative (0, 0);
+ tNFA_STATUS nfaStat = NFA_STATUS_OK;
+
+ gGeneralTransceiveTimeout = DEFAULT_GENERAL_TRANS_TIMEOUT;
+
+ if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
+ {
+ ALOGE ("%s: tag already deactivated", __FUNCTION__);
+ goto TheEnd;
+ }
+
+ nfaStat = NFA_Deactivate (FALSE);
+ if (nfaStat != NFA_STATUS_OK)
+ ALOGE ("%s: deactivate failed; error=0x%X", __FUNCTION__, nfaStat);
+
+TheEnd:
+ ALOGD ("%s: exit", __FUNCTION__);
+ return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doTransceiveStatus
+**
+** Description: Receive the completion status of transceive operation.
+** buf: Contains tag's response.
+** bufLen: Length of buffer.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doTransceiveStatus (uint8_t* buf, uint32_t bufLen)
+{
+ ALOGD ("%s: data len=%d, waiting for transceive: %d", __FUNCTION__, bufLen, sWaitingForTransceive);
+ if (!sWaitingForTransceive)
+ return;
+
+ sTransceiveDataLen = 0;
+ if (bufLen)
+ {
+ if (NULL == (sTransceiveData = (uint8_t *) malloc (bufLen)))
+ {
+ ALOGD ("%s: memory allocation error", __FUNCTION__);
+ }
+ else
+ {
+ memcpy (sTransceiveData, buf, sTransceiveDataLen = bufLen);
+ }
+ }
+
+ {
+ SyncEventGuard g (sTransceiveEvent);
+ sTransceiveEvent.notifyOne ();
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doTransceive
+**
+** Description: Send raw data to the tag; receive tag's response.
+** e: JVM environment.
+** o: Java object.
+** raw: Not used.
+** statusTargetLost: Whether tag responds or times out.
+**
+** Returns: Response from tag.
+**
+*******************************************************************************/
+static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray data, jboolean raw, jintArray statusTargetLost)
+{
+ ALOGD ("%s: enter; raw=%u; timeout = %d", __FUNCTION__, raw, gGeneralTransceiveTimeout);
+ bool fNeedToSwitchBack = false;
+ nfc_jni_native_data *nat = getNative (0, 0);
+ bool waitOk = false;
+ bool isNack = false;
+ uint8_t *buf = NULL;
+ uint32_t bufLen = 0;
+ jint *targetLost = NULL;
+
+ if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
+ {
+ if (statusTargetLost)
+ {
+ targetLost = e->GetIntArrayElements (statusTargetLost, 0);
+ if (targetLost)
+ *targetLost = 1; //causes NFC service to throw TagLostException
+ e->ReleaseIntArrayElements (statusTargetLost, targetLost, 0);
+ }
+ ALOGD ("%s: tag not active", __FUNCTION__);
+ return NULL;
+ }
+
+ NfcTag& natTag = NfcTag::getInstance ();
+
+ // get input buffer and length from java call
+ buf = (uint8_t *) e->GetByteArrayElements (data, NULL);
+ bufLen = (uint32_t) e->GetArrayLength (data);
+
+ if (statusTargetLost)
+ {
+ targetLost = e->GetIntArrayElements (statusTargetLost, 0);
+ if (targetLost)
+ *targetLost = 0; //success, tag is still present
+ }
+
+ sSwitchBackTimer.kill ();
+ jbyteArray result = NULL;
+ do
+ {
+ if (sNeedToSwitchRf)
+ {
+ // for ISO_DEP tags connected to NfcA or NfcB we need to be in FRAME interface
+ if (!switchRfInterface (NFA_INTERFACE_FRAME)) //NFA_INTERFACE_ISO_DEP
+ {
+ break;
+ }
+ fNeedToSwitchBack = true;
+ }
+
+ sWaitingForTransceive = true;
+ sTransceiveDataLen = 0;
+ {
+ SyncEventGuard g (sTransceiveEvent);
+ tNFA_STATUS status = NFA_SendRawFrame (buf, bufLen);
+ if (status != NFA_STATUS_OK)
+ {
+ ALOGE ("%s: fail send; error=%d", __FUNCTION__, status);
+ break;
+ }
+ waitOk = sTransceiveEvent.wait (gGeneralTransceiveTimeout);
+ }
+
+ if (waitOk == false) //if timeout occurred
+ {
+ ALOGE ("%s: wait response timeout", __FUNCTION__);
+ if (targetLost)
+ *targetLost = 1; //causes NFC service to throw TagLostException
+ break;
+ }
+
+ if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
+ {
+ ALOGE ("%s: already deactivated", __FUNCTION__);
+ if (targetLost)
+ *targetLost = 1; //causes NFC service to throw TagLostException
+ break;
+ }
+
+ ALOGD ("%s: response %d bytes", __FUNCTION__, sTransceiveDataLen);
+
+ if ((natTag.getProtocol () == NFA_PROTOCOL_T2T) &&
+ natTag.isT2tNackResponse (sTransceiveData, sTransceiveDataLen))
+ {
+ isNack = true;
+ }
+
+ if (sTransceiveDataLen)
+ {
+ if (!isNack) {
+ // marshall data to java for return
+ result = e->NewByteArray (sTransceiveDataLen);
+ if (result != NULL)
+ {
+ e->SetByteArrayRegion (result, 0, sTransceiveDataLen, (jbyte *) sTransceiveData);
+ }
+ else
+ ALOGE ("%s: Failed to allocate java byte array", __FUNCTION__);
+ } // else a nack is treated as a transceive failure to the upper layers
+
+ free (sTransceiveData);
+ sTransceiveData = NULL;
+ sTransceiveDataLen = 0;
+ }
+ } while (0);
+
+ sWaitingForTransceive = false;
+ e->ReleaseByteArrayElements (data, (jbyte *) buf, JNI_ABORT);
+ if (targetLost)
+ e->ReleaseIntArrayElements (statusTargetLost, targetLost, 0);
+
+ if (fNeedToSwitchBack)
+ {
+ // this timer proc will switch us back to ISO_DEP frame interface
+ sSwitchBackTimer.set (1500, switchBackTimerProc);
+ }
+
+ ALOGD ("%s: exit", __FUNCTION__);
+ return result;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doGetNdefType
+**
+** Description: Retrieve the type of tag.
+** e: JVM environment.
+** o: Java object.
+** libnfcType: Type of tag represented by JNI.
+** javaType: Not used.
+**
+** Returns: Type of tag represented by NFC Service.
+**
+*******************************************************************************/
+static jint nativeNfcTag_doGetNdefType (JNIEnv *e, jobject o, jint libnfcType, jint javaType)
+{
+ ALOGD ("%s: enter; libnfc type=%d; java type=%d", __FUNCTION__, libnfcType, javaType);
+ jint ndefType = NDEF_UNKNOWN_TYPE;
+
+ // For NFA, libnfcType is mapped to the protocol value received
+ // in the NFA_ACTIVATED_EVT and NFA_DISC_RESULT_EVT event.
+ switch (libnfcType) {
+ case NFA_PROTOCOL_T1T:
+ ndefType = NDEF_TYPE1_TAG;
+ break;
+ case NFA_PROTOCOL_T2T:
+ ndefType = NDEF_TYPE2_TAG;;
+ break;
+ case NFA_PROTOCOL_T3T:
+ ndefType = NDEF_TYPE3_TAG;
+ break;
+ case NFA_PROTOCOL_ISO_DEP:
+ ndefType = NDEF_TYPE4_TAG;
+ break;
+ case NFA_PROTOCOL_ISO15693:
+ ndefType = NDEF_UNKNOWN_TYPE;
+ break;
+ case NFA_PROTOCOL_INVALID:
+ ndefType = NDEF_UNKNOWN_TYPE;
+ break;
+ default:
+ ndefType = NDEF_UNKNOWN_TYPE;
+ break;
+ }
+ ALOGD ("%s: exit; ndef type=%d", __FUNCTION__, ndefType);
+ return ndefType;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doCheckNdefResult
+**
+** Description: Receive the result of checking whether the tag contains a NDEF
+** message. Called by the NFA_NDEF_DETECT_EVT.
+** status: Status of the operation.
+** maxSize: Maximum size of NDEF message.
+** currentSize: Current size of NDEF message.
+** flags: Indicate various states.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doCheckNdefResult (tNFA_STATUS status, uint32_t maxSize, uint32_t currentSize, uint8_t flags)
+{
+ //this function's flags parameter is defined using the following macros
+ //in nfc/include/rw_api.h;
+ //#define RW_NDEF_FL_READ_ONLY 0x01 /* Tag is read only */
+ //#define RW_NDEF_FL_FORMATED 0x02 /* Tag formated for NDEF */
+ //#define RW_NDEF_FL_SUPPORTED 0x04 /* NDEF supported by the tag */
+ //#define RW_NDEF_FL_UNKNOWN 0x08 /* Unable to find if tag is ndef capable/formated/read only */
+ //#define RW_NDEF_FL_FORMATABLE 0x10 /* Tag supports format operation */
+
+ if (status == NFC_STATUS_BUSY)
+ {
+ ALOGE ("%s: stack is busy", __FUNCTION__);
+ return;
+ }
+
+ if (!sCheckNdefWaitingForComplete)
+ {
+ ALOGE ("%s: not waiting", __FUNCTION__);
+ return;
+ }
+
+ if (flags & RW_NDEF_FL_READ_ONLY)
+ ALOGD ("%s: flag read-only", __FUNCTION__);
+ if (flags & RW_NDEF_FL_FORMATED)
+ ALOGD ("%s: flag formatted for ndef", __FUNCTION__);
+ if (flags & RW_NDEF_FL_SUPPORTED)
+ ALOGD ("%s: flag ndef supported", __FUNCTION__);
+ if (flags & RW_NDEF_FL_UNKNOWN)
+ ALOGD ("%s: flag all unknown", __FUNCTION__);
+ if (flags & RW_NDEF_FL_FORMATABLE)
+ ALOGD ("%s: flag formattable", __FUNCTION__);
+
+ sCheckNdefWaitingForComplete = JNI_FALSE;
+ sCheckNdefStatus = status;
+ sCheckNdefCapable = false; //assume tag is NOT ndef capable
+ if (sCheckNdefStatus == NFA_STATUS_OK)
+ {
+ //NDEF content is on the tag
+ sCheckNdefMaxSize = maxSize;
+ sCheckNdefCurrentSize = currentSize;
+ sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
+ sCheckNdefCapable = true;
+ }
+ else if (sCheckNdefStatus == NFA_STATUS_FAILED)
+ {
+ //no NDEF content on the tag
+ sCheckNdefMaxSize = 0;
+ sCheckNdefCurrentSize = 0;
+ sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
+ if ((flags & RW_NDEF_FL_UNKNOWN) == 0) //if stack understands the tag
+ {
+ if (flags & RW_NDEF_FL_SUPPORTED) //if tag is ndef capable
+ sCheckNdefCapable = true;
+ }
+ }
+ else
+ {
+ ALOGE ("%s: unknown status=0x%X", __FUNCTION__, status);
+ sCheckNdefMaxSize = 0;
+ sCheckNdefCurrentSize = 0;
+ sCheckNdefCardReadOnly = false;
+ }
+ sem_post (&sCheckNdefSem);
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doCheckNdef
+**
+** Description: Does the tag contain a NDEF message?
+** e: JVM environment.
+** o: Java object.
+** ndefInfo: NDEF info.
+**
+** Returns: Status code; 0 is success.
+**
+*******************************************************************************/
+static jint nativeNfcTag_doCheckNdef (JNIEnv *e, jobject o, jintArray ndefInfo)
+{
+ tNFA_STATUS status = NFA_STATUS_FAILED;
+ jint* ndef = NULL;
+
+ ALOGD ("%s: enter", __FUNCTION__);
+
+ /* Create the write semaphore */
+ if (sem_init (&sCheckNdefSem, 0, 0) == -1)
+ {
+ ALOGE ("%s: Check NDEF semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
+ return JNI_FALSE;
+ }
+
+ if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
+ {
+ ALOGE ("%s: tag already deactivated", __FUNCTION__);
+ goto TheEnd;
+ }
+
+ ALOGD ("%s: try NFA_RwDetectNDef", __FUNCTION__);
+ sCheckNdefWaitingForComplete = JNI_TRUE;
+ status = NFA_RwDetectNDef ();
+
+ if (status != NFA_STATUS_OK)
+ {
+ ALOGE ("%s: NFA_RwDetectNDef failed, status = 0x%X", __FUNCTION__, status);
+ goto TheEnd;
+ }
+
+ /* Wait for check NDEF completion status */
+ if (sem_wait (&sCheckNdefSem))
+ {
+ ALOGE ("%s: Failed to wait for check NDEF semaphore (errno=0x%08x)", __FUNCTION__, errno);
+ goto TheEnd;
+ }
+
+ if (sCheckNdefStatus == NFA_STATUS_OK)
+ {
+ //stack found a NDEF message on the tag
+ ndef = e->GetIntArrayElements (ndefInfo, 0);
+ if (NfcTag::getInstance ().getProtocol () == NFA_PROTOCOL_T1T)
+ ndef[0] = NfcTag::getInstance ().getT1tMaxMessageSize ();
+ else
+ ndef[0] = sCheckNdefMaxSize;
+ if (sCheckNdefCardReadOnly)
+ ndef[1] = NDEF_MODE_READ_ONLY;
+ else
+ ndef[1] = NDEF_MODE_READ_WRITE;
+ e->ReleaseIntArrayElements (ndefInfo, ndef, 0);
+ status = NFA_STATUS_OK;
+ }
+ else if (sCheckNdefStatus == NFA_STATUS_FAILED)
+ {
+ //stack did not find a NDEF message on the tag;
+ ndef = e->GetIntArrayElements (ndefInfo, 0);
+ if (NfcTag::getInstance ().getProtocol () == NFA_PROTOCOL_T1T)
+ ndef[0] = NfcTag::getInstance ().getT1tMaxMessageSize ();
+ else
+ ndef[0] = sCheckNdefMaxSize;
+ if (sCheckNdefCardReadOnly)
+ ndef[1] = NDEF_MODE_READ_ONLY;
+ else
+ ndef[1] = NDEF_MODE_READ_WRITE;
+ 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:
+ /* Destroy semaphore */
+ if (sem_destroy (&sCheckNdefSem))
+ {
+ ALOGE ("%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __FUNCTION__, errno);
+ }
+ sCheckNdefWaitingForComplete = JNI_FALSE;
+ ALOGD ("%s: exit; status=0x%X", __FUNCTION__, status);
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_resetPresenceCheck
+**
+** Description: Reset variables related to presence-check.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_resetPresenceCheck ()
+{
+ sCountTagAway = 0;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doPresenceCheckResult
+**
+** Description: Receive the result of presence-check.
+** status: Result of presence-check.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doPresenceCheckResult (tNFA_STATUS status)
+{
+ if (status == NFA_STATUS_OK)
+ sCountTagAway = 0;
+ else
+ sCountTagAway++;
+ if (sCountTagAway > 0)
+ ALOGD ("%s: sCountTagAway=%d", __FUNCTION__, sCountTagAway);
+ sem_post (&sPresenceCheckSem);
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doPresenceCheck
+**
+** Description: Check if the tag is in the RF field.
+** e: JVM environment.
+** o: Java object.
+**
+** Returns: True if tag is in RF field.
+**
+*******************************************************************************/
+static jboolean nativeNfcTag_doPresenceCheck (JNIEnv *e, jobject o)
+{
+ ALOGD ("%s", __FUNCTION__);
+ tNFA_STATUS status = NFA_STATUS_OK;
+ jboolean isPresent = JNI_FALSE;
+
+ if (nfcManager_isNfcActive() == false)
+ {
+ ALOGD ("%s: NFC is no longer active.", __FUNCTION__);
+ return JNI_FALSE;
+ }
+
+ if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
+ {
+ ALOGD ("%s: tag already deactivated", __FUNCTION__);
+ return JNI_FALSE;
+ }
+
+ if (sem_init (&sPresenceCheckSem, 0, 0) == -1)
+ {
+ ALOGE ("%s: semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
+ return JNI_FALSE;
+ }
+
+ status = NFA_RwPresenceCheck ();
+ if (status == NFA_STATUS_OK)
+ {
+ if (sem_wait (&sPresenceCheckSem))
+ {
+ ALOGE ("%s: failed to wait (errno=0x%08x)", __FUNCTION__, errno);
+ }
+ else
+ {
+ isPresent = (sCountTagAway > 3) ? JNI_FALSE : JNI_TRUE;
+ }
+ }
+
+ if (sem_destroy (&sPresenceCheckSem))
+ {
+ ALOGE ("Failed to destroy check NDEF semaphore (errno=0x%08x)", errno);
+ }
+
+ if (isPresent == JNI_FALSE)
+ ALOGD ("%s: tag absent ????", __FUNCTION__);
+ return isPresent;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doIsNdefFormatable
+**
+** Description: Can tag be formatted to store NDEF message?
+** e: JVM environment.
+** o: Java object.
+** libNfcType: Type of tag.
+** uidBytes: Tag's unique ID.
+** pollBytes: Data from activation.
+** actBytes: Data from activation.
+**
+** Returns: True if formattable.
+**
+*******************************************************************************/
+static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv *e,
+ jobject o, jint libNfcType, jbyteArray uidBytes, jbyteArray pollBytes,
+ jbyteArray actBytes)
+{
+ jboolean isFormattable = JNI_FALSE;
+
+ switch (NfcTag::getInstance().getProtocol())
+ {
+ case NFA_PROTOCOL_T1T:
+ case NFA_PROTOCOL_ISO15693:
+ isFormattable = JNI_TRUE;
+ break;
+
+ case NFA_PROTOCOL_T2T:
+ isFormattable = NfcTag::getInstance().isMifareUltralight() ? JNI_TRUE : JNI_FALSE;
+ }
+ ALOGD("%s: is formattable=%u", __FUNCTION__, isFormattable);
+ return isFormattable;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doIsIsoDepNdefFormatable
+**
+** Description: Is ISO-DEP tag formattable?
+** e: JVM environment.
+** o: Java object.
+** pollBytes: Data from activation.
+** actBytes: Data from activation.
+**
+** Returns: True if formattable.
+**
+*******************************************************************************/
+static jboolean nativeNfcTag_doIsIsoDepNdefFormatable (JNIEnv *e, jobject o, jbyteArray pollBytes, jbyteArray actBytes)
+{
+ uint8_t uidFake[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+ ALOGD ("%s", __FUNCTION__);
+ jbyteArray uidArray = e->NewByteArray (8);
+ e->SetByteArrayRegion (uidArray, 0, 8, (jbyte*) uidFake);
+ return nativeNfcTag_doIsNdefFormatable (e, o, 0, uidArray, pollBytes, actBytes);
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doNdefFormat
+**
+** Description: Format a tag so it can store NDEF message.
+** e: JVM environment.
+** o: Java object.
+** key: Not used.
+**
+** Returns: True if ok.
+**
+*******************************************************************************/
+static jboolean nativeNfcTag_doNdefFormat (JNIEnv *e, jobject o, jbyteArray key)
+{
+ ALOGD ("%s: enter", __FUNCTION__);
+ tNFA_STATUS status = NFA_STATUS_OK;
+
+ sem_init (&sFormatSem, 0, 0);
+ sFormatOk = false;
+ status = NFA_RwFormatTag ();
+ if (status == NFA_STATUS_OK)
+ {
+ ALOGD ("%s: wait for completion", __FUNCTION__);
+ sem_wait (&sFormatSem);
+ status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
+ }
+ else
+ ALOGE ("%s: error status=%u", __FUNCTION__, status);
+ sem_destroy (&sFormatSem);
+
+ ALOGD ("%s: exit", __FUNCTION__);
+ return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doMakeReadonlyResult
+**
+** Description: Receive the result of making a tag read-only. Called by the
+** NFA_SET_TAG_RO_EVT.
+** status: Status of the operation.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_doMakeReadonlyResult (tNFA_STATUS status)
+{
+ if (sMakeReadonlyWaitingForComplete != JNI_FALSE)
+ {
+ sMakeReadonlyWaitingForComplete = JNI_FALSE;
+ sMakeReadonlyStatus = status;
+
+ sem_post (&sMakeReadonlySem);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_doMakeReadonly
+**
+** Description: Make the tag read-only.
+** e: JVM environment.
+** o: Java object.
+** key: Key to access the tag.
+**
+** Returns: True if ok.
+**
+*******************************************************************************/
+static jboolean nativeNfcTag_doMakeReadonly (JNIEnv *e, jobject o, jbyteArray key)
+{
+ jboolean result = JNI_FALSE;
+ tNFA_STATUS status;
+
+ ALOGD ("%s", __FUNCTION__);
+
+ /* Create the make_readonly semaphore */
+ if (sem_init (&sMakeReadonlySem, 0, 0) == -1)
+ {
+ ALOGE ("%s: Make readonly semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
+ return JNI_FALSE;
+ }
+
+ sMakeReadonlyWaitingForComplete = JNI_TRUE;
+
+ // Hard-lock the tag (cannot be reverted)
+ status = NFA_RwSetTagReadOnly(TRUE);
+
+ if (status != NFA_STATUS_OK)
+ {
+ ALOGE ("%s: NFA_RwSetTagReadOnly failed, status = %d", __FUNCTION__, status);
+ goto TheEnd;
+ }
+
+ /* Wait for check NDEF completion status */
+ if (sem_wait (&sMakeReadonlySem))
+ {
+ ALOGE ("%s: Failed to wait for make_readonly semaphore (errno=0x%08x)", __FUNCTION__, errno);
+ goto TheEnd;
+ }
+
+ if (sMakeReadonlyStatus == NFA_STATUS_OK)
+ {
+ result = JNI_TRUE;
+ }
+
+TheEnd:
+ /* Destroy semaphore */
+ if (sem_destroy (&sMakeReadonlySem))
+ {
+ ALOGE ("%s: Failed to destroy read_only semaphore (errno=0x%08x)", __FUNCTION__, errno);
+ }
+ sMakeReadonlyWaitingForComplete = JNI_FALSE;
+ return result;
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_registerNdefTypeHandler
+**
+** Description: Register a callback to receive NDEF message from the tag
+** from the NFA_NDEF_DATA_EVT.
+**
+** Returns: None
+**
+*******************************************************************************/
+//register a callback to receive NDEF message from the tag
+//from the NFA_NDEF_DATA_EVT;
+void nativeNfcTag_registerNdefTypeHandler ()
+{
+ ALOGD ("%s", __FUNCTION__);
+ sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
+ NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_DEFAULT, (UINT8 *) "", 0, ndefHandlerCallback);
+}
+
+
+/*******************************************************************************
+**
+** Function: nativeNfcTag_deregisterNdefTypeHandler
+**
+** Description: No longer need to receive NDEF message from the tag.
+**
+** Returns: None
+**
+*******************************************************************************/
+void nativeNfcTag_deregisterNdefTypeHandler ()
+{
+ ALOGD ("%s", __FUNCTION__);
+ NFA_DeregisterNDefTypeHandler (sNdefTypeHandlerHandle);
+ sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
+}
+
+
+/*****************************************************************************
+**
+** JNI functions for Android 4.0.3
+**
+*****************************************************************************/
+static JNINativeMethod gMethods[] =
+{
+ {"doConnect", "(I)I", (void *)nativeNfcTag_doConnect},
+ {"doDisconnect", "()Z", (void *)nativeNfcTag_doDisconnect},
+ {"doReconnect", "()I", (void *)nativeNfcTag_doReconnect},
+ {"doHandleReconnect", "(I)I", (void *)nativeNfcTag_doHandleReconnect},
+ {"doTransceive", "([BZ[I)[B", (void *)nativeNfcTag_doTransceive},
+ {"doGetNdefType", "(II)I", (void *)nativeNfcTag_doGetNdefType},
+ {"doCheckNdef", "([I)I", (void *)nativeNfcTag_doCheckNdef},
+ {"doRead", "()[B", (void *)nativeNfcTag_doRead},
+ {"doWrite", "([B)Z", (void *)nativeNfcTag_doWrite},
+ {"doPresenceCheck", "()Z", (void *)nativeNfcTag_doPresenceCheck},
+ {"doIsIsoDepNdefFormatable", "([B[B)Z", (void *)nativeNfcTag_doIsIsoDepNdefFormatable},
+ {"doNdefFormat", "([B)Z", (void *)nativeNfcTag_doNdefFormat},
+ {"doMakeReadonly", "([B)Z", (void *)nativeNfcTag_doMakeReadonly},
+};
+
+
+/*******************************************************************************
+**
+** Function: register_com_android_nfc_NativeNfcTag
+**
+** Description: Regisgter JNI functions with Java Virtual Machine.
+** e: Environment of JVM.
+**
+** Returns: Status of registration.
+**
+*******************************************************************************/
+int register_com_android_nfc_NativeNfcTag (JNIEnv *e)
+{
+ ALOGD ("%s", __FUNCTION__);
+ return jniRegisterNativeMethods (e, gNativeNfcTagClassName, gMethods, NELEM (gMethods));
+}
+
+
+} /* namespace android */