void phNxpNciHal_TestMode_close ()
{

    NFCSTATUS status = NFCSTATUS_SUCCESS;

    CONCURRENCY_LOCK();

    if (NULL != gpphTmlNfc_Context->pDevHandle)
    {
        /* Abort any pending read and write */
        status = phTmlNfc_ReadAbort();
        status = phTmlNfc_WriteAbort();

        phOsalNfc_Timer_Cleanup();

        status = phTmlNfc_Shutdown();

        NXPLOG_NCIHAL_D("phNxpNciHal_close return status = %d", status);

        thread_running = 0;

        phDal4Nfc_msgrelease(gDrvCfg.nClientId);

        status = phOsalNfc_Timer_Delete(timeoutTimerId);
    }

    CONCURRENCY_UNLOCK();

    phNxpNciHal_cleanup_monitor();

    /* Return success always */
    return;
}
static jboolean com_android_nfc_NativeP2pDevice_doSend(
   JNIEnv *e, jobject o, jbyteArray buf)
{
   NFCSTATUS status;
   phNfc_sData_t data;
   jboolean result = JNI_FALSE;
   struct nfc_jni_callback_data cb_data;
   
   phLibNfc_Handle handle = nfc_jni_get_p2p_device_handle(e, o);
   
   CONCURRENCY_LOCK();

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

   /* Send */
   TRACE("Send data to the Initiator (handle = 0x%x)", handle);

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

   TRACE("phLibNfc_RemoteDev_Send()");
   REENTRANCE_LOCK();
   status = phLibNfc_RemoteDev_Send(handle, &data, nfc_jni_send_callback,(void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_RemoteDev_Send() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;   
   }
   TRACE("phLibNfc_RemoteDev_Send() 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:
   if (result != JNI_TRUE)
   {
      e->ReleaseByteArrayElements(buf, (jbyte *)data.buffer, JNI_ABORT);
   }
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();
   return result;
}
static jbyteArray com_android_nfc_NativeP2pDevice_doReceive(
   JNIEnv *e, jobject o)
{
   NFCSTATUS status;
   struct timespec ts;
   phLibNfc_Handle handle;
   jbyteArray buf = NULL;
   static phNfc_sData_t *data;
   struct nfc_jni_callback_data cb_data;

   CONCURRENCY_LOCK();

   handle = nfc_jni_get_p2p_device_handle(e, o);
   
   /* Create the local semaphore */
   if (!nfc_cb_data_init(&cb_data, (void*)data))
   {
      goto clean_and_return;
   }

   /* Receive */
   TRACE("phLibNfc_RemoteDev_Receive()");
   REENTRANCE_LOCK();
   status = phLibNfc_RemoteDev_Receive(handle, nfc_jni_receive_callback,(void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      LOGE("phLibNfc_RemoteDev_Receive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;   
   }
   TRACE("phLibNfc_RemoteDev_Receive() 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(data == NULL)
   {
      goto clean_and_return;
   }

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

clean_and_return:
   nfc_cb_data_deinit(&cb_data);
   CONCURRENCY_UNLOCK();
   return buf;
}
static jbyteArray com_android_nfc_NativeNdefTag_doRead(JNIEnv *e,
   jobject o)
{
   phLibNfc_Handle handle = 0;
   jbyteArray buf = NULL;
   NFCSTATUS         status;
   
   CONCURRENCY_LOCK();

   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 *)e);
   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 */
   sem_wait(nfc_jni_ndef_tag_sem);

   if(nfc_jni_cb_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:
   CONCURRENCY_UNLOCK();
   return buf;
}
static jboolean com_android_nfc_NativeNdefTag_doWrite(JNIEnv *e,
   jobject o, jbyteArray buf)
{
   NFCSTATUS      status;
   jboolean       result = JNI_FALSE;

   CONCURRENCY_LOCK();

   phLibNfc_Handle handle = nfc_jni_get_nfc_tag_handle(e, o);

   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()");
   REENTRANCE_LOCK();
   status  = phLibNfc_Ndef_Write(handle, &nfc_jni_ndef_rw,nfc_jni_tag_rw_callback, (void *)e);
   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 */
   sem_wait(nfc_jni_ndef_tag_sem);

   if(nfc_jni_cb_status != NFCSTATUS_SUCCESS)
   {
      goto clean_and_return;
   }

   result = JNI_TRUE;

clean_and_return:
   if (result != JNI_TRUE)
   {
      e->ReleaseByteArrayElements(buf, (jbyte *)nfc_jni_ndef_rw.buffer, JNI_ABORT);
   }

   CONCURRENCY_UNLOCK();

   return result;
}
/*******************************************************************************
**
** Function         phNxpNciHal_performTest
**
** Description      Performs a single cycle of command,response and
**                  notification.
**
** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED,
**
*******************************************************************************/
NFCSTATUS phNxpNciHal_performTest(nci_test_data_t *pData )
{
    NFCSTATUS status = NFCSTATUS_SUCCESS;

    if(NULL == pData)
    {
        return NFCSTATUS_FAILED;
    }

    CONCURRENCY_LOCK();

    status = phNxpNciHal_writeLocked(pData);

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

    status = phNxpNciHal_readLocked(pData);

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

    if(0 != pData->exp_ntf.len)
    {
        status = phNxpNciHal_readLocked(pData);

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

clean_and_return:
    CONCURRENCY_UNLOCK();
    return status;
}
static jbyteArray com_android_nfc_NativeP2pDevice_doTransceive(JNIEnv *e,
   jobject o, jbyteArray data)
{
   NFCSTATUS status;
   uint8_t offset = 2;
   uint8_t *buf;
   uint32_t buflen;
   phLibNfc_sTransceiveInfo_t transceive_info;
   jbyteArray result = NULL;
   phLibNfc_Handle handle = nfc_jni_get_p2p_device_handle(e, o);
   phNfc_sData_t * receive_buffer = NULL;
   struct nfc_jni_callback_data cb_data;

   CONCURRENCY_LOCK();

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

   /* Transceive*/
   TRACE("Transceive data to target (handle = 0x%x)", handle);

   buf = (uint8_t *)e->GetByteArrayElements(data, NULL);
   buflen = (uint32_t)e->GetArrayLength(data);
   
   TRACE("Buffer Length = %d\n", buflen);

   transceive_info.sSendData.buffer = buf; //+ offset;
   transceive_info.sSendData.length = buflen; //- 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(P2P)");
   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(P2P) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_RemoteDev_Transceive(P2P) 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 */
   result = e->NewByteArray(receive_buffer->length);
   if(result != NULL)
      e->SetByteArrayRegion(result, 0,
         receive_buffer->length,
         (jbyte *)receive_buffer->buffer);

clean_and_return:
   if(transceive_info.sRecvData.buffer != NULL)
   {
      free(transceive_info.sRecvData.buffer);
   }

   e->ReleaseByteArrayElements(data,
      (jbyte *)transceive_info.sSendData.buffer, JNI_ABORT);

   nfc_cb_data_deinit(&cb_data);

   CONCURRENCY_UNLOCK();

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

    CONCURRENCY_LOCK();

    handle = nfc_jni_get_p2p_device_handle(e, o);

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

    /* Disconnect */
    TRACE("Disconnecting from target (handle = 0x%x)", handle);

    /* NativeNfcTag waits for tag to leave the field here with presence check.
     * We do not in P2P path because presence check is not safe while transceive may be
     * in progress.
     */

    TRACE("phLibNfc_RemoteDev_Disconnect()");
    REENTRANCE_LOCK();
    status = phLibNfc_RemoteDev_Disconnect(handle, NFC_DISCOVERY_CONTINUE,nfc_jni_disconnect_callback, (void *)&cb_data);
    REENTRANCE_UNLOCK();
    if(status != NFCSTATUS_PENDING)
    {
        LOGE("phLibNfc_RemoteDev_Disconnect() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
        if(status == NFCSTATUS_TARGET_NOT_CONNECTED)
        {
            LOGE("phLibNfc_RemoteDev_Disconnect() failed: Target not connected");
        }
        else
        {
            LOGE("phLibNfc_RemoteDev_Disconnect() failed");
            nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
        }

        goto clean_and_return;
    }
    TRACE("phLibNfc_RemoteDev_Disconnect() 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;
    }

    /* Disconnect Status */
    if(cb_data.status != NFCSTATUS_SUCCESS)
    {
        goto clean_and_return;
    }

    result = JNI_TRUE;

clean_and_return:
    /* Reset device connected flag */
    device_connected_flag = 0;
    nfc_cb_data_deinit(&cb_data);
    CONCURRENCY_UNLOCK();
    return result;
}
static jboolean com_android_nfc_NativeP2pDevice_doConnect(JNIEnv *e, jobject o)
{
    phLibNfc_Handle handle = 0;
    NFCSTATUS status;
    jboolean result = JNI_FALSE;
    struct nfc_jni_callback_data cb_data;

    jclass target_cls = NULL;
    jobject tag;
    jmethodID ctor;
    jfieldID f;
    jbyteArray generalBytes = NULL;
    phNfc_sData_t sGeneralBytes;
    unsigned int i;

    CONCURRENCY_LOCK();

    handle = nfc_jni_get_p2p_device_handle(e, o);

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

    TRACE("phLibNfc_RemoteDev_Connect(P2P)");
    REENTRANCE_LOCK();
    status = phLibNfc_RemoteDev_Connect(handle, nfc_jni_connect_callback, (void*)&cb_data);
    REENTRANCE_UNLOCK();
    if(status != NFCSTATUS_PENDING)
    {
      LOGE("phLibNfc_RemoteDev_Connect(P2P) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
    }
    TRACE("phLibNfc_RemoteDev_Connect(P2P) 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;
    }

    /* Set General Bytes */
    target_cls = e->GetObjectClass(o);

    f = e->GetFieldID(target_cls, "mGeneralBytes", "[B");

    TRACE("General Bytes Length = %d", sGeneralBytes.length);
    TRACE("General Bytes =");
    for(i=0;i<sGeneralBytes.length;i++)
    {
      TRACE("0x%02x ", sGeneralBytes.buffer[i]);
    }

    generalBytes = e->NewByteArray(sGeneralBytes.length);

    e->SetByteArrayRegion(generalBytes, 0,
                         sGeneralBytes.length, 
                         (jbyte *)sGeneralBytes.buffer);

    e->SetObjectField(o, f, generalBytes);

    result = JNI_TRUE;

clean_and_return:
    if (result != JNI_TRUE)
    {
       /* Restart the polling loop if the connection failed */
       nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
    }
    nfc_cb_data_deinit(&cb_data);
    CONCURRENCY_UNLOCK();
    return result;
}
static jbyteArray com_android_nfc_NativeNfcSecureElement_doTransceive(JNIEnv *e,
   jobject o,jint handle, jbyteArray data)
{
   uint8_t offset = 0;
   uint8_t *buf;
   uint32_t buflen;
   phLibNfc_sTransceiveInfo_t transceive_info;
   jbyteArray result = NULL;
   int res; 
   
   int tech = SecureElementTech;
   NFCSTATUS status;
   struct nfc_jni_callback_data cb_data;

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

   TRACE("Exchange APDU function ");
   
   CONCURRENCY_LOCK();
   
   TRACE("Secure Element tech: %d\n", tech);

   buf = (uint8_t *)e->GetByteArrayElements(data, NULL);
   buflen = (uint32_t)e->GetArrayLength(data);
 
   /* Prepare transceive info structure */
   if(tech == TARGET_TYPE_MIFARE_CLASSIC || tech == TARGET_TYPE_MIFARE_UL)
   {
      offset = 2;
      transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
      transceive_info.addr = (uint8_t)buf[1];
   }
   else if(tech == TARGET_TYPE_ISO14443_4)
   {
      transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
      transceive_info.addr = 0;
   }
      
   transceive_info.sSendData.buffer = buf + offset;
   transceive_info.sSendData.length = buflen - 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(SMX)");
   REENTRANCE_LOCK();
   status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
		   com_android_nfc_jni_transceive_callback, (void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      ALOGE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
       ALOGE("TRANSCEIVE semaphore error");
       goto clean_and_return;
   }

   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
      ALOGE("TRANSCEIVE error");
      goto clean_and_return;
   }

   /* Copy results back to Java */
   result = e->NewByteArray(com_android_nfc_jni_transceive_buffer->length);
   if(result != NULL)
   {
      e->SetByteArrayRegion(result, 0,
    		  com_android_nfc_jni_transceive_buffer->length,
         (jbyte *)com_android_nfc_jni_transceive_buffer->buffer);
   }

clean_and_return:
   nfc_cb_data_deinit(&cb_data);

   if(transceive_info.sRecvData.buffer != NULL)
   {
      free(transceive_info.sRecvData.buffer);
   }

   e->ReleaseByteArrayElements(data,
      (jbyte *)transceive_info.sSendData.buffer, JNI_ABORT);

   CONCURRENCY_UNLOCK();

   return result;
}
static jboolean com_android_nfc_NativeNfcSecureElement_doDisconnect(JNIEnv *e, jobject o, jint handle)
{
   jclass cls;
   jfieldID f;
   NFCSTATUS status;
   jboolean result = JNI_FALSE;
   phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
   uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
   uint32_t SmartMX_Handle;
   struct nfc_jni_callback_data cb_data;
   phNfc_sData_t    InParam;
   phNfc_sData_t    OutParam;
   uint8_t          Output_Buff[10];
   uint8_t          GpioGetValue[3] = {0x00, 0xF8, 0x2B};
   uint8_t          GpioSetValue[4];
   uint8_t          gpioValue;

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

   TRACE("Close Secure element function ");

   CONCURRENCY_LOCK();
   /* Disconnect */
   TRACE("Disconnecting from SMX (handle = 0x%x)", handle);
   REENTRANCE_LOCK();
   status = phLibNfc_RemoteDev_Disconnect(handle, 
                                          NFC_SMARTMX_RELEASE,
                                          com_android_nfc_jni_disconnect_callback,
                                          (void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status != NFCSTATUS_PENDING)
   {
      ALOGE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
      goto clean_and_return;
   }
   TRACE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
       goto clean_and_return;
   }

   /* Disconnect Status */
   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
     ALOGE("\n> Disconnect SE ERROR \n" );
      goto clean_and_return;
   }
   CONCURRENCY_UNLOCK();

   /* Get GPIO information */
   CONCURRENCY_LOCK();
   InParam.buffer = GpioGetValue;
   InParam.length = 3;
   OutParam.buffer = Output_Buff;
   TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
   REENTRANCE_LOCK();
   status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status!=NFCSTATUS_PENDING)
   {
       ALOGE("IOCTL status error");
       goto clean_and_return;
   }

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      ALOGE("IOCTL semaphore error");
      goto clean_and_return;
   }

   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
      ALOGE("READ MEM ERROR");
      goto clean_and_return;
   }

   gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
   TRACE("GpioValue = Ox%02x",gpioValue);

   /* Set GPIO information */
   GpioSetValue[0] = 0x00;
   GpioSetValue[1] = 0xF8;
   GpioSetValue[2] = 0x2B;
   GpioSetValue[3] = (gpioValue & 0xBF);

   TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);

   for(i=0;i<4;i++)
   {
       TRACE("0x%02x",GpioSetValue[i]);
   }

   InParam.buffer = GpioSetValue;
   InParam.length = 4;
   OutParam.buffer = Output_Buff;
   TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
   REENTRANCE_LOCK();
   status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(status!=NFCSTATUS_PENDING)
   {
       ALOGE("IOCTL status error");
       goto clean_and_return;
   }

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      ALOGE("IOCTL semaphore error");
      goto clean_and_return;
   }

   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
      ALOGE("READ MEM ERROR");
      goto clean_and_return;
   }

   result = JNI_TRUE;

clean_and_return:
   nfc_cb_data_deinit(&cb_data);

   CONCURRENCY_UNLOCK();
   return result;
}
static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection(JNIEnv *e, jobject o)
{
   NFCSTATUS ret;
   int semResult;
   
   phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
   uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
   phLibNfc_sADD_Cfg_t discovery_cfg;
   phLibNfc_Registry_Info_t registry_info;
   phNfc_sData_t        InParam;
   phNfc_sData_t        OutParam;
   uint8_t              ExternalRFDetected[3] = {0x00, 0xFC, 0x01};
   uint8_t              GpioGetValue[3] = {0x00, 0xF8, 0x2B};
   uint8_t              GpioSetValue[4];
   uint8_t              gpioValue;
   uint8_t              Output_Buff[10];
   uint8_t              reg_value;
   uint8_t              mask_value;
   struct nfc_jni_callback_data cb_data;
   struct nfc_jni_callback_data cb_data_SE_Notification;

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

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

   /* Registery */   
   registry_info.MifareUL = TRUE;
   registry_info.MifareStd = TRUE;
   registry_info.ISO14443_4A = TRUE;
   registry_info.ISO14443_4B = TRUE;
   registry_info.Jewel = TRUE;
   registry_info.Felica = TRUE;  
   registry_info.NFC = FALSE;  
     
   CONCURRENCY_LOCK();
   
   TRACE("Open Secure Element");
   
   /* Check if NFC device is already connected to a tag or P2P peer */
   if (device_connected_flag == 1)
   {
       ALOGD("Unable to open SE connection, device already connected to a P2P peer or a Tag");
       goto clean_and_return;
   }

   /* Test if External RF field is detected */
   InParam.buffer = ExternalRFDetected;
   InParam.length = 3;
   OutParam.buffer = Output_Buff;
   TRACE("phLibNfc_Mgt_IoCtl()");
   REENTRANCE_LOCK();
   ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
   REENTRANCE_UNLOCK();
   if(ret!=NFCSTATUS_PENDING)
   {
      ALOGE("IOCTL status error");
      goto clean_and_return;
   }

   /* Wait for callback response */
   if(sem_wait(&cb_data.sem))
   {
      ALOGE("IOCTL semaphore error");
      goto clean_and_return;
   }
      
   if(cb_data.status != NFCSTATUS_SUCCESS)
   {
      ALOGE("READ MEM ERROR");
      goto clean_and_return;
   }

   /* Check the value */   
   reg_value = com_android_nfc_jni_ioctl_buffer->buffer[0];
   mask_value = reg_value & 0x40;

   if(mask_value == 0x40)
   {
      // There is an external RF field present, fail the open request
      ALOGD("Unable to open SE connection, external RF Field detected");
      goto clean_and_return;   
   }   

   /* Get Secure Element List */
   TRACE("phLibNfc_SE_GetSecureElementList()");
   ret = phLibNfc_SE_GetSecureElementList( SE_List, &No_SE);
   if (ret == NFCSTATUS_SUCCESS)
   {
      TRACE("\n> Number of Secure Element(s) : %d\n", No_SE);
      /* Display Secure Element information */
      for (i = 0; i<No_SE; i++)
      {
         if (SE_List[i].eSE_Type == phLibNfc_SE_Type_SmartMX)
         {
           TRACE("> SMX detected");
           TRACE("> Secure Element Handle : %d\n", SE_List[i].hSecureElement);
           /* save SMARTMX index */
           SmartMX_detected = 1;
           SmartMX_index = i;
         }
      }

      if(SmartMX_detected)
      {
         REENTRANCE_LOCK();
         TRACE("phLibNfc_RemoteDev_NtfRegister()");
         ret = phLibNfc_RemoteDev_NtfRegister(&registry_info,
                 com_android_nfc_jni_open_secure_element_notification_callback,
                 (void *)&cb_data_SE_Notification);
         REENTRANCE_UNLOCK();
         if(ret != NFCSTATUS_SUCCESS)
         {
            ALOGE("Register Notification error");
            goto clean_and_return;
         }

         /* Set wired mode */
         REENTRANCE_LOCK();
         TRACE("phLibNfc_SE_SetMode: Wired mode");
         ret = phLibNfc_SE_SetMode( SE_List[SmartMX_index].hSecureElement, 
                                     phLibNfc_SE_ActModeWired,
                                     com_android_nfc_jni_smartMX_setModeCb,
                                     (void *)&cb_data);
         REENTRANCE_UNLOCK();
         if (ret != NFCSTATUS_PENDING )
         {
            ALOGE("\n> SE Set SmartMX mode ERROR \n" );
            goto clean_and_return;
         }

         /* Wait for callback response */
         if(sem_wait(&cb_data.sem))
         {
            ALOGE("Secure Element opening error");
            goto clean_and_return;
         }

         if(cb_data.status != NFCSTATUS_SUCCESS)
         {
            ALOGE("SE set mode failed");
            goto clean_and_return;
         }

         TRACE("Waiting for notification");
         /* Wait for callback response */
         if(sem_wait(&cb_data_SE_Notification.sem))
         {
            ALOGE("Secure Element opening error");
            goto clean_and_return;
         }

         if(cb_data_SE_Notification.status != NFCSTATUS_SUCCESS &&
                 cb_data_SE_Notification.status != NFCSTATUS_MULTIPLE_PROTOCOLS)
         {
            ALOGE("SE detection failed");
            goto clean_and_return;
         }
         CONCURRENCY_UNLOCK();

         /* Connect Tag */
         CONCURRENCY_LOCK();
         TRACE("phLibNfc_RemoteDev_Connect(SMX)");
         REENTRANCE_LOCK();
         ret = phLibNfc_RemoteDev_Connect(secureElementHandle, com_android_nfc_jni_connect_callback,(void *)&cb_data);
         REENTRANCE_UNLOCK();
         if(ret != NFCSTATUS_PENDING)
         {
            ALOGE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
            goto clean_and_return;
         }
         TRACE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));

         /* Wait for callback response */
         if(sem_wait(&cb_data.sem))
         {
             ALOGE("CONNECT semaphore error");
             goto clean_and_return;
         }

         /* Connect Status */
         if(cb_data.status != NFCSTATUS_SUCCESS)
         {
            ALOGE("Secure Element connect error");
            goto clean_and_return;
         }

         CONCURRENCY_UNLOCK();

         /* Get GPIO information */
         CONCURRENCY_LOCK();
         InParam.buffer = GpioGetValue;
         InParam.length = 3;
         OutParam.buffer = Output_Buff;
         TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
         REENTRANCE_LOCK();
         ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
         REENTRANCE_UNLOCK();
         if(ret!=NFCSTATUS_PENDING)
         {
             ALOGE("IOCTL status error");
         }

         /* Wait for callback response */
         if(sem_wait(&cb_data.sem))
         {
            ALOGE("IOCTL semaphore error");
            goto clean_and_return;
         }

         if(cb_data.status != NFCSTATUS_SUCCESS)
         {
            ALOGE("READ MEM ERROR");
            goto clean_and_return;
         }

         gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
         TRACE("GpioValue = Ox%02x",gpioValue);

         /* Set GPIO information */
         GpioSetValue[0] = 0x00;
         GpioSetValue[1] = 0xF8;
         GpioSetValue[2] = 0x2B;
         GpioSetValue[3] = (gpioValue | 0x40);

         TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);

         for(i=0;i<4;i++)
         {
             TRACE("0x%02x",GpioSetValue[i]);
         }

         InParam.buffer = GpioSetValue;
         InParam.length = 4;
         OutParam.buffer = Output_Buff;
         TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
         REENTRANCE_LOCK();
         ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
         REENTRANCE_UNLOCK();
         if(ret!=NFCSTATUS_PENDING)
         {
             ALOGE("IOCTL status error");
             goto clean_and_return;
         }

         /* Wait for callback response */
         if(sem_wait(&cb_data.sem))
         {
            ALOGE("IOCTL semaphore error");
            goto clean_and_return;
         }

         if(cb_data.status != NFCSTATUS_SUCCESS)
         {
            ALOGE("READ MEM ERROR");
            goto clean_and_return;
         }
         CONCURRENCY_UNLOCK();

         nfc_cb_data_deinit(&cb_data);
         nfc_cb_data_deinit(&cb_data_SE_Notification);

         /* Return the Handle of the SecureElement */
         return secureElementHandle;
      }
      else
      {
         ALOGE("phLibNfc_SE_GetSecureElementList(): No SMX detected");
         goto clean_and_return; 
      } 
  }
  else
  {
      ALOGE("phLibNfc_SE_GetSecureElementList(): Error");
      goto clean_and_return;
  }
  
clean_and_return:
   nfc_cb_data_deinit(&cb_data);
   nfc_cb_data_deinit(&cb_data_SE_Notification);

   CONCURRENCY_UNLOCK();
   return 0;
}
/*******************************************************************************
 **
 ** Function         phNxpNciHal_TestMode_open
 **
 ** Description      It opens the physical connection with NFCC (pn547) and
 **                  creates required client thread for operation.
 **
 ** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED.
 **
 *******************************************************************************/
NFCSTATUS phNxpNciHal_TestMode_open (void)
{
    /* Thread */
    pthread_t test_rx_thread;

    phOsalNfc_Config_t tOsalConfig;
    phTmlNfc_Config_t tTmlConfig;
    NFCSTATUS status = NFCSTATUS_SUCCESS;
    uint16_t read_len = 255;

    /* initialize trace level */
    phNxpLog_InitializeLogLevel();

    if (phNxpNciHal_init_monitor() == NULL)
    {
        NXPLOG_NCIHAL_E("Init monitor failed");
        return NFCSTATUS_FAILED;
    }

    CONCURRENCY_LOCK();

    memset(&tOsalConfig, 0x00, sizeof(tOsalConfig));
    memset(&tTmlConfig, 0x00, sizeof(tTmlConfig));

    gDrvCfg.nClientId = phDal4Nfc_msgget(0, 0600);
    gDrvCfg.nLinkType = ENUM_LINK_TYPE_I2C;/* For PN547 */
    tTmlConfig.pDevName = (int8_t *) "/dev/pn544";
    tOsalConfig.dwCallbackThreadId = (uint32_t) gDrvCfg.nClientId;
    tOsalConfig.pLogFile = NULL;
    tTmlConfig.dwGetMsgThreadId = (uint32_t) gDrvCfg.nClientId;
    nxpncihal_ctrl.gDrvCfg.nClientId = (uint32_t) gDrvCfg.nClientId;

    /* Initialize TML layer */
    status = phTmlNfc_Init(&tTmlConfig);
    if (status != NFCSTATUS_SUCCESS)
    {
        NXPLOG_NCIHAL_E("phTmlNfc_Init Failed");
        goto clean_and_return;
    }

    if (pthread_create(&test_rx_thread, NULL,
            phNxpNciHal_test_rx_thread, NULL) != 0)
    {
        NXPLOG_NCIHAL_E("pthread_create failed");
        phTmlNfc_Shutdown();
        goto clean_and_return;
    }

    timeoutTimerId = phOsalNfc_Timer_Create();

    if(timeoutTimerId == 0xFFFF)
    {
        NXPLOG_NCIHAL_E("phOsalNfc_Timer_Create failed");
    }
    else
    {
        NXPLOG_NCIHAL_D("phOsalNfc_Timer_Create SUCCESS");
    }
    CONCURRENCY_UNLOCK();

    return NFCSTATUS_SUCCESS;

clean_and_return:
    CONCURRENCY_UNLOCK();
    phNxpNciHal_cleanup_monitor();
    return NFCSTATUS_FAILED;
}
/*******************************************************************************
 **
 ** Function         tmp_thread
 **
 ** Description      Thread to execute custom poll commands .
 **
 ** Returns          None
 **
 *******************************************************************************/
void *tmp_thread(void *tmp)
{
    NFCSTATUS status = NFCSTATUS_SUCCESS;
    uint16_t data_len;
    NXPLOG_NCIHAL_E("tmp_thread: enter type=0x0%x",  *((int*)tmp));
    usleep(10*1000);

    switch( *((int*)tmp) )
    {
    case START_POLLING:
    {
        CONCURRENCY_LOCK();
        data_len = phNxpNciHal_write_unlocked(cmd_poll_len, cmd_poll);
        CONCURRENCY_UNLOCK();

        if(data_len != cmd_poll_len)
        {
            NXPLOG_NCIHAL_E("phNxpNciHal_start_polling_loop: data len mismatch");
            status = NFCSTATUS_FAILED;
        }
    }
    break;

    case RESUME_POLLING:
    {
        CONCURRENCY_LOCK();
        data_len = phNxpNciHal_write_unlocked(sizeof(cmd_resume_rf_discovery),
                cmd_resume_rf_discovery);
        CONCURRENCY_UNLOCK();

        if(data_len != sizeof(cmd_resume_rf_discovery))
        {
            NXPLOG_NCIHAL_E("phNxpNciHal_resume_polling_loop: data len mismatch");
            status = NFCSTATUS_FAILED;
        }
    }
    break;

    case STOP_POLLING:
    {
        CONCURRENCY_LOCK();
        data_len = phNxpNciHal_write_unlocked(sizeof(cmd_stop_rf_discovery),
                cmd_stop_rf_discovery);
        CONCURRENCY_UNLOCK();

        if(data_len != sizeof(cmd_stop_rf_discovery))
        {
            NXPLOG_NCIHAL_E("phNxpNciHal_stop_polling_loop: data len mismatch");
            status = NFCSTATUS_FAILED;
        }
    }
    break;

    case DISCOVER_SELECT:
    {
        CONCURRENCY_LOCK();
        data_len = phNxpNciHal_write_unlocked(sizeof(cmd_select_rf_discovery),
                cmd_select_rf_discovery);
        CONCURRENCY_UNLOCK();

        if(data_len != sizeof(cmd_resume_rf_discovery))
        {
            NXPLOG_NCIHAL_E("phNxpNciHal_resume_polling_loop: data len mismatch");
            status = NFCSTATUS_FAILED;
        }
    }
    break;

    default:
        NXPLOG_NCIHAL_E("No Matching case");
        status = NFCSTATUS_FAILED;
        break;
    }

    NXPLOG_NCIHAL_E("tmp_thread: exit");
    return NULL;
}
/******************************************************************************
 * Function         phNxpEseP61_7816_Transceive
 *
 * Description      This function prepares C-APDU and sends to p61 and recives
 *                  response from the p61. also it parses all required fields of
 *                  the response PDU.
 *
 * Returns          On Success ESESTATUS_SUCCESS else proper error code
 *
 ******************************************************************************/
ESESTATUS phNxpEseP61_7816_Transceive(pphNxpEseP61_7816_cpdu_t pCmd, pphNxpEseP61_7816_rpdu_t pRsp)
{
    ESESTATUS status = ESESTATUS_FAILED;
    NXPLOG_SPIHAL_D(" %s Enter \n", __FUNCTION__);
    uint32_t cmd_len = 0;
    uint8_t *pCmd_data = NULL;

    if (phNxpSpiHal_init_cb_data(&cb_data, NULL) != ESESTATUS_SUCCESS)
    {
        NXPLOG_SPIHAL_D("%s Create cb data failed", __FUNCTION__);
        CONCURRENCY_UNLOCK();
        return status;
    }

    if (NULL == pCmd  || NULL == pRsp)
    {
        NXPLOG_SPIHAL_E(" %s Invalid prameter \n", __FUNCTION__);
        status = ESESTATUS_INVALID_PARAMETER;
    }
    else if(pCmd->cpdu_type > 1)
    {
        NXPLOG_SPIHAL_E(" %s Invalid cpdu type \n", __FUNCTION__);
        status = ESESTATUS_INVALID_CPDU_TYPE;
    }
    else if(0 < pCmd->le_type && NULL == pRsp->pdata)
    {
       /* if response is requested, but no valid res buffer
        * provided by application */
        NXPLOG_SPIHAL_E(" %s Invalid response buffer \n", __FUNCTION__);
        status = ESESTATUS_INVALID_BUFFER;
    }
    else
    {
        status = phNxpEseP61_7816_FrameCmd(pCmd, &pCmd_data, &cmd_len);
        if (ESESTATUS_SUCCESS == status)
        {
            status = phNxpEseP61_Transceive(cmd_len, pCmd_data);
            if (ESESTATUS_SUCCESS != status)
            {
                NXPLOG_SPIHAL_E(" %s phNxpEseP61_Transceive Failed \n", __FUNCTION__);
            }
            else
            {
                /* Wait for callback response */
                if (SEM_WAIT(cb_data))
                {
                    NXPLOG_SPIHAL_E("phNxpEseP61_Transceive semaphore error");
                    status = ESESTATUS_FAILED;
                }
                else
                {
                    if ((sTransceiveDataLen > 0) && (sTransceiveData != NULL))
                    {
                        pRsp->sw2 = *(sTransceiveData + (sTransceiveDataLen -1));
                        sTransceiveDataLen--;
                        pRsp->sw1 = *(sTransceiveData + (sTransceiveDataLen -1));
                        sTransceiveDataLen--;
                        pRsp->len = sTransceiveDataLen;
                        ALOGD("pRsp->len %d", pRsp->len);
                        if (sTransceiveDataLen > 0 && NULL != pRsp->pdata)
                        {
                            memcpy(pRsp->pdata, sTransceiveData, sTransceiveDataLen);
                            status = ESESTATUS_SUCCESS;
                        }
                        else if(sTransceiveDataLen == 0)
                        {
                            status = ESESTATUS_SUCCESS;
                        }
                        else
                        {
                           /* if application response buffer is null and data is present */
                            NXPLOG_SPIHAL_E("Invalid Res buffer");
                            status = ESESTATUS_FAILED;
                        }
                        NXPLOG_SPIHAL_D("Freeing memroy sTransceiveData");
                        free(sTransceiveData);
                        sTransceiveData = NULL;
                        sTransceiveDataLen = 0;
                    }
                    else
                    {
                        NXPLOG_SPIHAL_E("sTransceiveDataLen error = %d", sTransceiveDataLen);
                        status = ESESTATUS_FAILED;
                    }
                }
            }
            if (pCmd_data != NULL)
            {
                NXPLOG_SPIHAL_D("Freeing memroy pCmd_data");
                free(pCmd_data);
            }
        }
    }
    phNxpSpiHal_cleanup_cb_data(&cb_data);
    NXPLOG_SPIHAL_D(" %s Exit status 0x%x \n", __FUNCTION__, status);
    return status;
}