/*
 * Copyright (C) 2010 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 "com_android_nfc.h"
#include "phNfcHalTypes.h"

static phLibNfc_Data_t nfc_jni_ndef_rw;
static phLibNfc_Handle handle;
uint8_t *nfc_jni_ndef_buf = NULL;
uint32_t nfc_jni_ndef_buf_len = 0;



namespace android {

extern phLibNfc_Handle storedHandle;

extern void nfc_jni_restart_discovery_locked(struct nfc_jni_native_data *nat);

/*
 * Callbacks
 */
 static void nfc_jni_tag_rw_callback(void *pContext, NFCSTATUS status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_tag_rw_callback", status);

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   sem_post(&pCallbackData->sem);
}

static void nfc_jni_connect_callback(void *pContext,
   phLibNfc_Handle hRemoteDev,
   phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_connect_callback", status);

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   if (pCallbackData->pContext != NULL) {
       // Store the remote dev info ptr in the callback context
       // Note that this ptr will remain valid, it is tied to a statically
       // allocated buffer in libnfc.
       phLibNfc_sRemoteDevInformation_t** ppRemoteDevInfo =
           (phLibNfc_sRemoteDevInformation_t**)pCallbackData->pContext;
       *ppRemoteDevInfo = psRemoteDevInfo;
   }

   sem_post(&pCallbackData->sem);
}

static void nfc_jni_checkndef_callback(void *pContext,
   phLibNfc_ChkNdef_Info_t info, NFCSTATUS status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_checkndef_callback", status);
   phLibNfc_ChkNdef_Info_t* pNdefInfo = (phLibNfc_ChkNdef_Info_t*) (pCallbackData->pContext);
   if(status == NFCSTATUS_OK)
   {
      if(nfc_jni_ndef_buf)
      {
         free(nfc_jni_ndef_buf);
      }
      nfc_jni_ndef_buf_len = info.MaxNdefMsgLength;
      nfc_jni_ndef_buf = (uint8_t*)malloc(nfc_jni_ndef_buf_len);
      if (pNdefInfo != NULL) *pNdefInfo = info;
   }
   else {
      if (pNdefInfo != NULL) {
        memset(pNdefInfo, 0, sizeof(*pNdefInfo));
      }
   }

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   sem_post(&pCallbackData->sem);
}

static void nfc_jni_disconnect_callback(void *pContext,
   phLibNfc_Handle hRemoteDev, NFCSTATUS status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_disconnect_callback", status);

   if(nfc_jni_ndef_buf)
   {
      free(nfc_jni_ndef_buf);
   }
   nfc_jni_ndef_buf = NULL;
   nfc_jni_ndef_buf_len = 0;

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   sem_post(&pCallbackData->sem);
}

static void nfc_jni_async_disconnect_callback(void *pContext,
   phLibNfc_Handle hRemoteDev, NFCSTATUS status)
{
   LOG_CALLBACK("nfc_jni_async_disconnect_callback", status);

   if(nfc_jni_ndef_buf)
   {
      free(nfc_jni_ndef_buf);
   }
   nfc_jni_ndef_buf = NULL;
   nfc_jni_ndef_buf_len = 0;
}

static void nfc_jni_presence_check_callback(void* pContext,NFCSTATUS  status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_presence_check_callback", status);

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   sem_post(&pCallbackData->sem);
}

static void nfc_jni_async_presence_check_callback(void* pContext,NFCSTATUS  status)
{
   NFCSTATUS ret;
   JNIEnv* env = (JNIEnv*)pContext;

   LOG_CALLBACK("nfc_jni_async_presence_check_callback", status);

   if(status != NFCSTATUS_SUCCESS)
   {
      /* Disconnect & Restart Polling loop */
      TRACE("Tag removed from the RF Field\n");

      TRACE("phLibNfc_RemoteDev_Disconnect(async)");
      REENTRANCE_LOCK();
      ret = phLibNfc_RemoteDev_Disconnect(handle, NFC_DISCOVERY_CONTINUE, nfc_jni_async_disconnect_callback,(void*)handle);
      REENTRANCE_UNLOCK();
      if(ret != NFCSTATUS_PENDING)
      {
         LOGE("phLibNfc_RemoteDev_Disconnect() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
         /* concurrency lock held while in callback */
         nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(env));
         return;
      }
      TRACE("phLibNfc_RemoteDev_Disconnect() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
   }
   else
   {
      TRACE("phLibNfc_RemoteDev_CheckPresence(async)");
      /* Presence Check */
      REENTRANCE_LOCK();
      ret = phLibNfc_RemoteDev_CheckPresence(handle,nfc_jni_async_presence_check_callback, (void*)env);
      REENTRANCE_UNLOCK();
      if(ret != NFCSTATUS_PENDING)
      {
         LOGE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
         return;
      }
      TRACE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
   }
}



static phNfc_sData_t *nfc_jni_transceive_buffer;

static void nfc_jni_transceive_callback(void *pContext,
   phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_transceive_callback", status);
  
   nfc_jni_transceive_buffer = pResBuffer;

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   sem_post(&pCallbackData->sem);
}

static void nfc_jni_presencecheck_callback(void *pContext, NFCSTATUS status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_presencecheck_callback", status);

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   sem_post(&pCallbackData->sem);
}

static void nfc_jni_formatndef_callback(void *pContext, NFCSTATUS status)
{
   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
   LOG_CALLBACK("nfc_jni_formatndef_callback", status);

   /* Report the callback status and wake up the caller */
   pCallbackData->status = status;
   sem_post(&pCallbackData->sem);
}

/* Functions */
static jbyteArray com_android_nfc_NativeNfcTag_doRead(JNIEnv *e,
   jobject o)
{
   NFCSTATUS status;
   phLibNfc_Handle handle = 0;
   jbyteArray buf = NULL;
   struct nfc_jni_callback_data cb_data;

   CONCURRENCY_LOCK();

   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, NULL))
   {
      goto clean_and_return;
   }

   handle = nfc_jni_get_nfc_tag_handle(e, o);

   nfc_jni_ndef_rw.length = nfc_jni_ndef_buf_len;
   nfc_jni_ndef_rw.buffer = nfc_jni_ndef_buf;

   TRACE("phLibNfc_Ndef_Read()");
   REENTRANCE_LOCK();
   status = phLibNfc_Ndef_Read(handle, &nfc_jni_ndef_rw,
                               phLibNfc_Ndef_EBegin, 
                               nfc_jni_tag_rw_callback, 
                               (void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    
   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
      goto clean_and_return;
   }

   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
      goto clean_and_return;
   }

   buf = e->NewByteArray(nfc_jni_ndef_rw.length);
   e->SetByteArrayRegion(buf, 0, nfc_jni_ndef_rw.length,
      (jbyte *)nfc_jni_ndef_rw.buffer);

clean_and_return:
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();

   return buf;
}
 

static jboolean com_android_nfc_NativeNfcTag_doWrite(JNIEnv *e,
   jobject o, jbyteArray buf)
{
   NFCSTATUS   status;
   jboolean    result = JNI_FALSE;
   struct nfc_jni_callback_data cb_data;

   phLibNfc_Handle handle = nfc_jni_get_nfc_tag_handle(e, o);

   CONCURRENCY_LOCK();

   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, NULL))
   {
      goto clean_and_return;
   }

   nfc_jni_ndef_rw.length = (uint32_t)e->GetArrayLength(buf);
   nfc_jni_ndef_rw.buffer = (uint8_t *)e->GetByteArrayElements(buf, NULL);

   TRACE("phLibNfc_Ndef_Write()");
   TRACE("Ndef Handle :0x%x\n",handle);
   TRACE("Ndef buffer length : %d", nfc_jni_ndef_rw.length);
   REENTRANCE_LOCK();
   status = phLibNfc_Ndef_Write(handle, &nfc_jni_ndef_rw,nfc_jni_tag_rw_callback, (void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
      goto clean_and_return;
   }

   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
      goto clean_and_return;
   }

   result = JNI_TRUE;

clean_and_return:
   e->ReleaseByteArrayElements(buf, (jbyte *)nfc_jni_ndef_rw.buffer, JNI_ABORT);

   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();
   return result;
}

/*
 *  Utility to recover poll bytes from target infos
 */
static void set_target_pollBytes(JNIEnv *e, jobject tag,
        phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo)
{
    jclass tag_cls = e->GetObjectClass(tag);
    jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I");
    jintArray techList = (jintArray) e->GetObjectField(tag, techListField);
    jint *techId = e->GetIntArrayElements(techList, 0);
    int techListLength = e->GetArrayLength(techList);

    jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B");
    jbyteArray pollBytes = e->NewByteArray(0);
    jobjectArray techPollBytes = e->NewObjectArray(techListLength,
            e->GetObjectClass(pollBytes), 0);

    for (int tech = 0; tech < techListLength; tech++) {
        switch(techId[tech])
        {
            /* ISO14443-3A: ATQA/SENS_RES */
            case TARGET_TYPE_ISO14443_3A:
                pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA));
                e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA),
                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA);
                break;
            /* ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES */
            case TARGET_TYPE_ISO14443_3B:
                pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData)
                                           + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo));
                e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData),
                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData);
                e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData),
                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo),
                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo);
                break;
            /* JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte) */
            case TARGET_TYPE_FELICA:
                pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm)
                                           + sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode));
                e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm),
                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm);
                e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm),
                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode),
                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode);
                break;
            /* ISO15693: response flags (1 byte), DSFID (1 byte) */
            case TARGET_TYPE_ISO15693:
                pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags)
                                           + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid));
                e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags);
                e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid),
                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid);
                break;
            default:
                pollBytes = e->NewByteArray(0);
                break;
        }
        e->SetObjectArrayElement(techPollBytes, tech, pollBytes);
    }

    e->SetObjectField(tag, f, techPollBytes);

}

/*
 *  Utility to recover activation bytes from target infos
 */
static void set_target_activationBytes(JNIEnv *e, jobject tag,
        phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo)
{
    jclass tag_cls = e->GetObjectClass(tag);
    jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I");
    jintArray techList = (jintArray) e->GetObjectField(tag, techListField);
    int techListLength = e->GetArrayLength(techList);
    jint *techId = e->GetIntArrayElements(techList, 0);

    jfieldID f = e->GetFieldID(tag_cls, "mTechActBytes", "[[B");
    jbyteArray actBytes = e->NewByteArray(0);
    jobjectArray techActBytes = e->NewObjectArray(techListLength,
            e->GetObjectClass(actBytes), 0);

    for (int tech = 0; tech < techListLength; tech++) {
        switch(techId[tech]) {

            /* ISO14443-3A: SAK/SEL_RES */
            case TARGET_TYPE_ISO14443_3A:
                actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak));
                e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak),
                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak);
                break;
            /* ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS */
            /* ISO14443-3B & ISO14443-4: HiLayerResp */
            case TARGET_TYPE_ISO14443_4:
                // Determine whether -A or -B
                if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_B_PICC ||
                    psRemoteDevInfo->RemDevType == phNfc_eISO14443_4B_PICC) {
                    actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength);
                    e->SetByteArrayRegion(actBytes, 0, psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength,
                                      (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerResp);
                }
                else {
                    actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength);
                    e->SetByteArrayRegion(actBytes, 0,
                                          psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength,
                                          (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppData);
                }
                break;
            /* ISO15693: response flags (1 byte), DSFID (1 byte) */
            case TARGET_TYPE_ISO15693:
                actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags)
                                           + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid));
                e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags);
                e->SetByteArrayRegion(actBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
                                      sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid),
                                      (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid);
                break;
            default:
                actBytes = e->NewByteArray(0);
                break;
        }
        e->SetObjectArrayElement(techActBytes, tech, actBytes);
    }
    e->SetObjectField(tag, f, techActBytes);
}

static jboolean com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e,
   jobject o)
{
   phLibNfc_Handle handle = 0;
   jclass cls;
   jfieldID f;
   NFCSTATUS status;
   jboolean result = JNI_FALSE;
   struct nfc_jni_callback_data cb_data;
   phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL;

   CONCURRENCY_LOCK();

   handle = nfc_jni_get_nfc_tag_handle(e, o);

   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
   {
      goto clean_and_return;
   }

   TRACE("phLibNfc_RemoteDev_Connect(RW)");
   REENTRANCE_LOCK();
   status = phLibNfc_RemoteDev_Connect(handle, nfc_jni_connect_callback,(void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
      goto clean_and_return;
   }
   
   /* Connect Status */
   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
      goto clean_and_return;
   }

   // Success, set poll & act bytes
   set_target_pollBytes(e, o, pRemDevInfo);
   set_target_activationBytes(e, o, pRemDevInfo);

   result = JNI_TRUE;

clean_and_return:
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();
   return result;
}

static jboolean com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e,
   jobject o)
{
    // Reconnect is provided by libnfc by just calling connect again
    // on the same handle.
    return com_android_nfc_NativeNfcTag_doConnect(e, o);
}


static jboolean com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv *e, jobject o)
{
   phLibNfc_Handle handle = 0;
   jclass cls;
   jfieldID f;
   NFCSTATUS status;
   jboolean result = JNI_FALSE;
   struct nfc_jni_callback_data cb_data;

   CONCURRENCY_LOCK();

   handle = nfc_jni_get_nfc_tag_handle(e, o);

   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, NULL))
   {
      goto clean_and_return;
   }

   /* Reset the stored handle */
   storedHandle = 0;

   /* Disconnect */
   TRACE("Disconnecting from tag (%x)", handle);
   
   /* Presence Check */
   do
   {
      TRACE("phLibNfc_RemoteDev_CheckPresence(%x)", handle);
      REENTRANCE_LOCK();
      status = phLibNfc_RemoteDev_CheckPresence(handle,nfc_jni_presence_check_callback,(void *)&cb_data);
      REENTRANCE_UNLOCK();
      if(status != NFCSTATUS_PENDING)
      {
         LOGE("phLibNfc_RemoteDev_CheckPresence(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
         /* Disconnect Tag */
         break;
      }
      TRACE("phLibNfc_RemoteDev_CheckPresence(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));

      /* Wait for callback response */
      if(sem_wait(&cb_data.sem))
      {
         LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
         goto clean_and_return;
      }

    } while(cb_data.status == NFCSTATUS_SUCCESS);

    TRACE("Tag removed from the RF Field\n");

    TRACE("phLibNfc_RemoteDev_Disconnect(%x)", handle);
    REENTRANCE_LOCK();
    status = phLibNfc_RemoteDev_Disconnect(handle, NFC_DISCOVERY_CONTINUE,
                                          nfc_jni_disconnect_callback, (void *)&cb_data);
    REENTRANCE_UNLOCK();

    if(status == NFCSTATUS_TARGET_NOT_CONNECTED)
    {
        result = JNI_TRUE;
        TRACE("phLibNfc_RemoteDev_Disconnect() - Target already disconnected");
        goto clean_and_return;
    }
    if(status != NFCSTATUS_PENDING)
    {
        LOGE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
        nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
        goto clean_and_return;
    }
    TRACE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));

    /* Wait for callback response */
    if(sem_wait(&cb_data.sem))
    {
       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
       goto clean_and_return;
    }
   
    /* Disconnect Status */
    if(cb_data.status != NFCSTATUS_SUCCESS)
    {
        goto clean_and_return;
    }
    result = JNI_TRUE;

clean_and_return:
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();
   return result;
}

static uint16_t
crc_16_ccitt1( uint8_t* msg, size_t len, uint16_t init )
{
    uint16_t b, crc = init;

    do {
        b = *msg++ ^ (crc & 0xFF);
        b ^= (b << 4) & 0xFF;
        crc = (crc >> 8) ^ (b << 8) ^ (b << 3) ^ (b >> 4);
    } while( --len );

    return crc;
}

static void
nfc_insert_crc_a( uint8_t* msg, size_t len )
{
    uint16_t crc;

    crc = crc_16_ccitt1( msg, len, 0x6363 );
    msg[len] = crc & 0xFF;
    msg[len + 1] = (crc >> 8) & 0xFF;
}

static void
nfc_get_crc_a( uint8_t* msg, size_t len, uint8_t* byte1, uint8_t* byte2)
{
    uint16_t crc;

    crc = crc_16_ccitt1( msg, len, 0x6363 );
    *byte1 = crc & 0xFF;
    *byte2 = (crc >> 8) & 0xFF;
}

static bool
crc_valid( uint8_t* msg, size_t len)
{
    uint8_t crcByte1, crcByte2;

    nfc_get_crc_a(nfc_jni_transceive_buffer->buffer,
          len - 2, &crcByte1, &crcByte2);

    if (msg[len - 2] == crcByte1 &&
          msg[len - 1] == crcByte2) {
        return true;
    }
    else {
        return false;
    }

}
static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e,
   jobject o, jbyteArray data, jboolean raw)
{
    uint8_t offset = 0;
    // buf is the pointer to the JNI array and never overwritten,
    // outbuf is passed into the transceive - it may be pointed to new memory
    // to be extended with CRC.
    uint8_t *buf = NULL;
    uint32_t buflen;

    uint8_t *outbuf = NULL;
    uint32_t outlen;
    phLibNfc_sTransceiveInfo_t transceive_info;
    jbyteArray result = NULL;
    int res;
    jintArray techtypes = nfc_jni_get_nfc_tag_type(e, o);
    phLibNfc_Handle handle = nfc_jni_get_nfc_tag_handle(e, o);
    NFCSTATUS status;
    struct nfc_jni_callback_data cb_data;
    int selectedTech = 0;
    jint* technologies = NULL;
    bool checkResponseCrc = false;

    CONCURRENCY_LOCK();

    /* Create the local semaphore */
    if (!nfc_cb_data_init(&cb_data, NULL))
    {
       goto clean_and_return;
    }

    if ((techtypes == NULL) || (e->GetArrayLength(techtypes) == 0)) {
      goto clean_and_return;
    }
    // TODO: code to determine the selected technology
    // For now, take the first
    technologies = e->GetIntArrayElements(techtypes, 0);
    selectedTech = technologies[0];

    TRACE("Transceive thinks selected tag technology = %d\n", selectedTech);

    buf = outbuf = (uint8_t *)e->GetByteArrayElements(data, NULL);
    buflen = outlen = (uint32_t)e->GetArrayLength(data);

    switch (selectedTech) {
/* TODO figure out how to pipe Jewel commands through from Java
        case TARGET_TYPE_JEWEL:
          transceive_info.cmd.JewelCmd = phNfc_eJewel_Raw;
          transceive_info.addr = 0;
          break;
*/
        case TARGET_TYPE_FELICA:
          transceive_info.cmd.FelCmd = phNfc_eFelica_Raw;
          transceive_info.addr = 0;
          break;
        case TARGET_TYPE_MIFARE_CLASSIC:
        case TARGET_TYPE_MIFARE_UL:
          if (raw) {
              transceive_info.cmd.MfCmd = phHal_eMifareRaw;
              transceive_info.addr = 0;
              // Need to add in the crc here
              outbuf = (uint8_t*)malloc(buflen + 2);
              outlen += 2;
              memcpy(outbuf, buf, buflen);
              nfc_insert_crc_a(outbuf, buflen);

              checkResponseCrc = true;
          } else {
              offset = 2;
              transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
              transceive_info.addr = (uint8_t)buf[1];
          }
          break;
        case TARGET_TYPE_ISO14443_3A:
          if (raw) {
              transceive_info.cmd.MfCmd = phHal_eMifareRaw;
              transceive_info.addr = 0;
              // Need to add in the crc here
              outbuf = (uint8_t*)malloc(buflen + 2);
              outlen += 2;
              memcpy(outbuf, buf, buflen);
              nfc_insert_crc_a(outbuf, buflen);

              checkResponseCrc = true;
          } else {
              offset = 2;
              transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
              transceive_info.addr = (uint8_t)buf[1];
          }
          break;
        case TARGET_TYPE_ISO14443_4:
          transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
          transceive_info.addr = 0;
          break;
        case TARGET_TYPE_ISO15693:
          transceive_info.cmd.Iso15693Cmd = phNfc_eIso15693_Cmd;
          transceive_info.addr = 0;
          break;
        case TARGET_TYPE_UNKNOWN:
        case TARGET_TYPE_ISO14443_3B:
          // Not supported
          goto clean_and_return;
        default:
          break;
    }

    transceive_info.sSendData.buffer = outbuf + offset;
    transceive_info.sSendData.length = outlen - offset;
    transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024);
    transceive_info.sRecvData.length = 1024;
    if(transceive_info.sRecvData.buffer == NULL)
    {
      goto clean_and_return;
    }

    TRACE("phLibNfc_RemoteDev_Transceive()");
    REENTRANCE_LOCK();
    status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
         nfc_jni_transceive_callback, (void *)&cb_data);
    REENTRANCE_UNLOCK();
    if(status != NFCSTATUS_PENDING)
    {
      LOGE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
    }
    TRACE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

    /* Wait for callback response */
    if(sem_wait(&cb_data.sem))
    {
       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
       goto clean_and_return;
    }

    if(cb_data.status != NFCSTATUS_SUCCESS)
    {
        goto clean_and_return;
    }

    /* Copy results back to Java *
     * In case of NfcA and raw, also check the CRC in the response
     * and cut it off in the returned data.
     */
    if (checkResponseCrc) {
        if (crc_valid(nfc_jni_transceive_buffer->buffer, nfc_jni_transceive_buffer->length)) {
            result = e->NewByteArray(nfc_jni_transceive_buffer->length - 2);
            if (result != NULL) {
                e->SetByteArrayRegion(result, 0,
                 nfc_jni_transceive_buffer->length - 2,
                 (jbyte *)nfc_jni_transceive_buffer->buffer);
            }
        }
    } else {
        result = e->NewByteArray(nfc_jni_transceive_buffer->length);
        if (result != NULL) {
            e->SetByteArrayRegion(result, 0,
             nfc_jni_transceive_buffer->length,
             (jbyte *)nfc_jni_transceive_buffer->buffer);
        }
    }
clean_and_return:
    if(transceive_info.sRecvData.buffer != NULL)
    {
      free(transceive_info.sRecvData.buffer);
    }
    if (technologies != NULL) {
      e->ReleaseIntArrayElements(techtypes, technologies, JNI_ABORT);
    }

    if ((outbuf != buf) && (outbuf != NULL)) {
        // Buf was extended and re-alloced with crc bytes, free separately
        free(outbuf);
    }

    e->ReleaseByteArrayElements(data,
      (jbyte *)buf, JNI_ABORT);

    nfc_cb_data_deinit(&cb_data);

    CONCURRENCY_UNLOCK();

    return result;
}

static bool com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintArray ndefinfo)
{
   phLibNfc_Handle handle = 0;
   NFCSTATUS status;
   bool result = JNI_FALSE;
   phLibNfc_ChkNdef_Info_t sNdefInfo;
   struct nfc_jni_callback_data cb_data;
   jint *ndef = e->GetIntArrayElements(ndefinfo, 0);
   int apiCardState = NDEF_MODE_UNKNOWN;

   CONCURRENCY_LOCK();

   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, NULL))
   {
      goto clean_and_return;
   }
   cb_data.pContext = &sNdefInfo;

   handle = nfc_jni_get_nfc_tag_handle(e, o);

   TRACE("phLibNfc_Ndef_CheckNdef()");
   REENTRANCE_LOCK();
   status = phLibNfc_Ndef_CheckNdef(handle, nfc_jni_checkndef_callback,(void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
      goto clean_and_return;
   }

   if (cb_data.status != NFCSTATUS_SUCCESS)
   {
      goto clean_and_return;
   }

   result = JNI_TRUE;

   ndef[0] = sNdefInfo.MaxNdefMsgLength;
   // Translate the card state to know values for the NFC API
   switch (sNdefInfo.NdefCardState) {
       case PH_NDEFMAP_CARD_STATE_INITIALIZED:
           apiCardState = NDEF_MODE_READ_WRITE;
           break;
       case PH_NDEFMAP_CARD_STATE_READ_ONLY:
           apiCardState = NDEF_MODE_READ_ONLY;
           break;
       case PH_NDEFMAP_CARD_STATE_READ_WRITE:
           apiCardState = NDEF_MODE_READ_WRITE;
           break;
       case PH_NDEFMAP_CARD_STATE_INVALID:
           apiCardState = NDEF_MODE_UNKNOWN;
           break;
   }
   ndef[1] = apiCardState;

clean_and_return:
   e->ReleaseIntArrayElements(ndefinfo, ndef, 0);
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();
   return result;
}

static jboolean com_android_nfc_NativeNfcTag_doPresenceCheck(JNIEnv *e, jobject o)
{
   phLibNfc_Handle handle = 0;
   NFCSTATUS status;
   jboolean result = JNI_FALSE;
   struct nfc_jni_callback_data cb_data;

   CONCURRENCY_LOCK();

   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, NULL))
   {
      goto clean_and_return;
   }

   handle = nfc_jni_get_nfc_tag_handle(e, o);

   TRACE("phLibNfc_RemoteDev_CheckPresence()");
   REENTRANCE_LOCK();
   status = phLibNfc_RemoteDev_CheckPresence(handle, nfc_jni_presencecheck_callback, (void *)&cb_data);
   REENTRANCE_UNLOCK();

   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
      goto clean_and_return;
   }

   if (cb_data.status == NFCSTATUS_SUCCESS)
   {
       result = JNI_TRUE;
   }

clean_and_return:
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();

   return result;
}

static jboolean com_android_nfc_NativeNfcTag_doNdefFormat(JNIEnv *e, jobject o, jbyteArray key)
{
   phLibNfc_Handle handle = 0;
   NFCSTATUS status;
   phNfc_sData_t keyBuffer;
   jboolean result = JNI_FALSE;
   struct nfc_jni_callback_data cb_data;

   CONCURRENCY_LOCK();

   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, NULL))
   {
      goto clean_and_return;
   }

   handle = nfc_jni_get_nfc_tag_handle(e, o);

   keyBuffer.buffer = (uint8_t *)e->GetByteArrayElements(key, NULL);
   keyBuffer.length = e->GetArrayLength(key);
   TRACE("phLibNfc_RemoteDev_FormatNdef()");
   REENTRANCE_LOCK();
   status = phLibNfc_RemoteDev_FormatNdef(handle, &keyBuffer, nfc_jni_formatndef_callback, (void *)&cb_data);
   REENTRANCE_UNLOCK();

   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
      goto clean_and_return;
   }

   if (cb_data.status == NFCSTATUS_SUCCESS)
   {
       result = JNI_TRUE;
   }

clean_and_return:
   e->ReleaseByteArrayElements(key, (jbyte *)keyBuffer.buffer, JNI_ABORT);
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();
   return result;
}

/*
 * JNI registration.
 */
static JNINativeMethod gMethods[] =
{
   {"doConnect", "()Z",
      (void *)com_android_nfc_NativeNfcTag_doConnect},
   {"doDisconnect", "()Z",
      (void *)com_android_nfc_NativeNfcTag_doDisconnect},
   {"doReconnect", "()Z",
      (void *)com_android_nfc_NativeNfcTag_doReconnect},
   {"doTransceive", "([BZ)[B",
      (void *)com_android_nfc_NativeNfcTag_doTransceive},
   {"doCheckNdef", "([I)Z",
      (void *)com_android_nfc_NativeNfcTag_doCheckNdef},
   {"doRead", "()[B",
      (void *)com_android_nfc_NativeNfcTag_doRead},
   {"doWrite", "([B)Z",
      (void *)com_android_nfc_NativeNfcTag_doWrite},
   {"doPresenceCheck", "()Z",
      (void *)com_android_nfc_NativeNfcTag_doPresenceCheck},
   {"doNdefFormat", "([B)Z",
      (void *)com_android_nfc_NativeNfcTag_doNdefFormat},
};

int register_com_android_nfc_NativeNfcTag(JNIEnv *e)
{
   return jniRegisterNativeMethods(e,
      "com/android/nfc/NativeNfcTag",
      gMethods, NELEM(gMethods));
}

} // namespace android
