Пример #1
0
/* Initialize the callback data */
NFCSTATUS phNxpNciHal_init_cb_data(phNxpNciHal_Sem_t *pCallbackData,
        void *pContext)
{
    /* Create semaphore */
    if (sem_init(&pCallbackData->sem, 0, 0) == -1)
    {
        NXPLOG_NCIHAL_E("Semaphore creation failed (errno=0x%08x)", errno);
        return NFCSTATUS_FAILED;
    }

    /* Set default status value */
    pCallbackData->status = NFCSTATUS_FAILED;

    /* Copy the context */
    pCallbackData->pContext = pContext;

    /* Add to active semaphore list */
    if (listAdd(&phNxpNciHal_get_monitor()->sem_list, pCallbackData) != 1)
    {
        NXPLOG_NCIHAL_E("Failed to add the semaphore to the list");
    }

    return NFCSTATUS_SUCCESS;
}
/*******************************************************************************
 **
 ** Function         phNxpNciHal_select_RF_Discovery
 **
 ** Description     Sends RF_DISCOVER_SELECT_CMD
 ** Parameters    RfID ,  RfProtocolType
 ** Returns          NFCSTATUS_PENDING if success
 **
 *******************************************************************************/
NFCSTATUS phNxpNciHal_select_RF_Discovery(unsigned int RfID,unsigned int RfProtocolType)
{
    NFCSTATUS status = NFCSTATUS_SUCCESS;
    phNxpNciHal_Sem_t cb_data;
    pthread_t pthread;
    discover_type = DISCOVER_SELECT;
    cmd_select_rf_discovery[3]=RfID;
    cmd_select_rf_discovery[4]=RfProtocolType;

    if(pthread_create(&pthread, NULL, tmp_thread, (void*) &discover_type) != 0)
    {
        NXPLOG_NCIHAL_E("phNxpNciHal_resume_polling_loop");
    }

    return status;
}
/*******************************************************************************
**
** Function         listDestroy
**
** Description      List destruction
**
** Returns          1, if list destroyed, 0 if failed
**
*******************************************************************************/
int listDestroy(struct listHead* pList)
{
    int bListNotEmpty = 1;
    while (bListNotEmpty)
    {
        bListNotEmpty = listGetAndRemoveNext(pList, NULL);
    }

    if (pthread_mutex_destroy(&pList->mutex) == -1)
    {
        NXPLOG_NCIHAL_E("Mutex destruction failed (errno=0x%08x)", errno);
        return 0;
    }

    return 1;
}
/*******************************************************************************
**
** Function         hal_write_cb
**
** Description      Callback function for hal write.
**
** Returns          None
**
*******************************************************************************/
static void hal_write_cb(void *pContext, phTmlNfc_TransactInfo_t *pInfo)
{
    phNxpNciHal_Sem_t *p_cb_data = (phNxpNciHal_Sem_t*) pContext;

    if (pInfo->wStatus == NFCSTATUS_SUCCESS)
    {
        NXPLOG_NCIHAL_D("write successful status = 0x%x", pInfo->wStatus);
    }
    else
    {
        NXPLOG_NCIHAL_E("write error status = 0x%x", pInfo->wStatus);
    }

    p_cb_data->status = pInfo->wStatus;
    SEM_POST(p_cb_data);

    return;
}
/*******************************************************************************
**
** Function         listAdd
**
** Description      Add a node to the list
**
** Returns          1, if added, 0 if otherwise
**
*******************************************************************************/
int listAdd(struct listHead* pList, void* pData)
{
    struct listNode* pNode;
    struct listNode* pLastNode;
    int result;

    /* Create node */
    pNode = (struct listNode*) malloc(sizeof(struct listNode));
    if (pNode == NULL)
    {
        result = 0;
        NXPLOG_NCIHAL_E("Failed to malloc");
        goto clean_and_return;
    }
    pNode->pData = pData;
    pNode->pNext = NULL;

    pthread_mutex_lock(&pList->mutex);

    /* Add the node to the list */
    if (pList->pFirst == NULL)
    {
        /* Set the node as the head */
        pList->pFirst = pNode;
    }
    else
    {
        /* Seek to the end of the list */
        pLastNode = pList->pFirst;
        while (pLastNode->pNext != NULL)
        {
            pLastNode = pLastNode->pNext;
        }

        /* Add the node to the current list */
        pLastNode->pNext = pNode;
    }

    result = 1;

clean_and_return:
    pthread_mutex_unlock(&pList->mutex);
    return result;
}
/*******************************************************************************
**
** Function         phNxpNciHal_test_rx_thread
**
** Description      Thread to fetch and process messages from message queue.
**
** Returns          NULL
**
*******************************************************************************/
static void *phNxpNciHal_test_rx_thread(void *arg)
{
    phLibNfc_Message_t msg;

    NXPLOG_NCIHAL_D("Self test thread started");

    thread_running = 1;

    while (thread_running == 1)
    {
        /* Fetch next message from the NFC stack message queue */
        if (phDal4Nfc_msgrcv(gDrvCfg.nClientId,
                &msg, 0, 0) == -1)
        {
            NXPLOG_NCIHAL_E("Received bad message");
            continue;
        }

        if(thread_running == 0)
        {
            break;
        }

        switch (msg.eMsgType)
        {
            case PH_LIBNFC_DEFERREDCALL_MSG:
            {
                phLibNfc_DeferredCall_t *deferCall =
                        (phLibNfc_DeferredCall_t *) (msg.pMsgData);

                REENTRANCE_LOCK();
                deferCall->pCallback(deferCall->pParameter);
                REENTRANCE_UNLOCK();

                break;
            }
        }
    }

    NXPLOG_NCIHAL_D("Self test thread stopped");

    return NULL;
}
/*******************************************************************************
**
** Function         phNxpNciHal_AntennaSelfTest
**
** Description      Test function to validate the Antenna's discrete
**                  components connection.
**
** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED.
**
*******************************************************************************/
NFCSTATUS phNxpNciHal_AntennaSelfTest(phAntenna_St_Resp_t * phAntenna_St_Resp )
{
    NFCSTATUS status = NFCSTATUS_FAILED;
    NFCSTATUS antenna_st_status = NFCSTATUS_FAILED;
    int len = 0;
    int cnt = 0;

    NXPLOG_NCIHAL_D("phNxpNciHal_AntennaSelfTest - start\n");
    memcpy(&phAntenna_resp, phAntenna_St_Resp, sizeof(phAntenna_St_Resp_t));
    len = (sizeof(antenna_self_test_data)/sizeof(antenna_self_test_data[0]));

    for(cnt = 0; cnt < len; cnt++)
    {
        status = phNxpNciHal_performTest(&(antenna_self_test_data[cnt]));
        if(status == NFCSTATUS_RESPONSE_TIMEOUT || status == NFCSTATUS_FAILED)
        {
            NXPLOG_NCIHAL_E("phNxpNciHal_AntennaSelfTest: commnad execution - FAILED\n");
            break;
        }
    }

    if(status == NFCSTATUS_SUCCESS)
    {
        if((gtxldo_status == NFCSTATUS_SUCCESS) && (gagc_value_status == NFCSTATUS_SUCCESS) &&
           (gagc_nfcld_status == NFCSTATUS_SUCCESS) && (gagc_differential_status == NFCSTATUS_SUCCESS))
        {
            antenna_st_status = NFCSTATUS_SUCCESS;
            NXPLOG_NCIHAL_D("phNxpNciHal_AntennaSelfTest - SUCESS\n");
        }
        else
        {
            NXPLOG_NCIHAL_D("phNxpNciHal_AntennaSelfTest - FAILED\n");
        }
    }
    else
    {
        NXPLOG_NCIHAL_D("phNxpNciHal_AntennaSelfTest - FAILED\n");
    }

    NXPLOG_NCIHAL_D("phNxpNciHal_AntennaSelfTest - end\n");

    return antenna_st_status;
}
/*******************************************************************************
**
** Function         phNxpNciHal_readLocked
**
** Description      Reads response and notification from NFCC and waits for
**                  read completion, for a definitive timeout value.
**
** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED,
**                  NFCSTATUS_RESPONSE_TIMEOUT in case of timeout.
**
*******************************************************************************/
static NFCSTATUS phNxpNciHal_readLocked(nci_test_data_t *pData )
{
    NFCSTATUS status = NFCSTATUS_SUCCESS;
    phNxpNciHal_Sem_t cb_data;
    uint16_t read_len = 16;
    /* RX Buffer */
    uint32_t rx_data[NCI_MAX_DATA_LEN];

    /* Create the local semaphore */
    if (phNxpNciHal_init_cb_data(&cb_data, pData) != NFCSTATUS_SUCCESS)
    {
        NXPLOG_NCIHAL_D("phTmlNfc_Read Create cb data failed");
        status = NFCSTATUS_FAILED;
        goto clean_and_return;
    }

    /* call read pending */
    status = phTmlNfc_Read(
            (uint8_t *) rx_data,
            (uint16_t) read_len,
            (pphTmlNfc_TransactCompletionCb_t) &hal_read_cb,
            &cb_data);

    if (status != NFCSTATUS_PENDING)
    {
        NXPLOG_NCIHAL_E("TML Read status error status = %x", status);
        status = NFCSTATUS_FAILED;
        goto clean_and_return;
    }

    status = phOsalNfc_Timer_Start(timeoutTimerId,
            HAL_WRITE_RSP_TIMEOUT,
            &hal_write_rsp_timeout_cb,
            &cb_data);

    if (NFCSTATUS_SUCCESS == status)
    {
        NXPLOG_NCIHAL_D("Response timer started");
    }
    else
    {
        NXPLOG_NCIHAL_E("Response timer not started");
        status = NFCSTATUS_FAILED;
        goto clean_and_return;
    }

    /* Wait for callback response */
    if (SEM_WAIT(cb_data))
    {
        NXPLOG_NCIHAL_E("phTmlNfc_Read semaphore error");
        status = NFCSTATUS_FAILED;
        goto clean_and_return;
    }

    if(cb_data.status == NFCSTATUS_RESPONSE_TIMEOUT)
    {
        NXPLOG_NCIHAL_E("Response timeout!!!");
        status = NFCSTATUS_RESPONSE_TIMEOUT;
        goto clean_and_return;

    }

    if (cb_data.status != NFCSTATUS_SUCCESS)
    {
        NXPLOG_NCIHAL_E("phTmlNfc_Read failed  ");
        status = NFCSTATUS_FAILED;
        goto clean_and_return;
    }

    clean_and_return:
    phNxpNciHal_cleanup_cb_data(&cb_data);

    return status;
}
/*******************************************************************************
**
** Function         hal_read_cb
**
** Description      Callback function for hal read.
**
** Returns          None
**
*******************************************************************************/
static void hal_read_cb(void *pContext, phTmlNfc_TransactInfo_t *pInfo)
{
    phNxpNciHal_Sem_t *p_cb_data = (phNxpNciHal_Sem_t*) pContext;

    if(hal_write_timer_fired == 1)
    {
        NXPLOG_NCIHAL_D("hal_read_cb - response timeout occurred");

        hal_write_timer_fired = 0;
        p_cb_data->status = NFCSTATUS_RESPONSE_TIMEOUT;
    }
    else
    {
        NFCSTATUS status = phOsalNfc_Timer_Stop(timeoutTimerId);

        if (NFCSTATUS_SUCCESS == status)
        {
            NXPLOG_NCIHAL_D("Response timer stopped");
        }
        else
        {
            NXPLOG_NCIHAL_E("Response timer stop ERROR!!!");
            p_cb_data->status  = NFCSTATUS_FAILED;
        }

        if (pInfo->wStatus == NFCSTATUS_SUCCESS)
        {
            NXPLOG_NCIHAL_D("hal_read_cb successful status = 0x%x", pInfo->wStatus);
            p_cb_data->status = NFCSTATUS_SUCCESS;
        }
        else
        {
            NXPLOG_NCIHAL_E("hal_read_cb error status = 0x%x", pInfo->wStatus);
            p_cb_data->status = NFCSTATUS_FAILED;
        }

        p_cb_data->status = pInfo->wStatus;

        nci_test_data_t *test_data = (nci_test_data_t*) p_cb_data->pContext;

        if(test_data->exp_rsp.len == 0)
        {
            /* Compare the actual notification with expected notification.*/
            if( test_data->ntf_validator(&(test_data->exp_ntf),pInfo) == 1 )
            {
                p_cb_data->status = NFCSTATUS_SUCCESS;
            }
            else
            {
                p_cb_data->status = NFCSTATUS_FAILED;

            }
        }

        /* Compare the actual response with expected response.*/
        else if( test_data->rsp_validator(&(test_data->exp_rsp),pInfo) == 1)
        {
            p_cb_data->status = NFCSTATUS_SUCCESS;
        }
        else
        {
            p_cb_data->status = NFCSTATUS_FAILED;
        }
        test_data->exp_rsp.len = 0;
    }

    SEM_POST(p_cb_data);

    return;
}
/*******************************************************************************
**
** Function         hal_write_rsp_timeout_cb
**
** Description      Callback function for hal write response timer.
**
** Returns          None
**
*******************************************************************************/
static void hal_write_rsp_timeout_cb(uint32_t timerId, void *pContext)
{
    NXPLOG_NCIHAL_E("hal_write_rsp_timeout_cb - write timeout!!!");
    hal_write_timer_fired = 1;
    hal_read_cb(pContext,NULL);
}
/*******************************************************************************
**
** Function         st_validator_testAntenna_Txldo
**
** Description      Validator function to validate Antenna TxLDO current measurement.
**
** Returns          One if successful otherwise Zero.
**
*******************************************************************************/
static uint8_t st_validator_testAntenna_Txldo(nci_data_t *exp, phTmlNfc_TransactInfo_t *act)
{
    uint8_t result = 0;
    uint8_t mesuredrange =0;
    long measured_val = 0;
    int tolerance = 0;

    if(NULL == exp || NULL == act)
    {
        return result;
    }

    NXPLOG_NCIHAL_D("st_validator_testAntenna_Txldo = 0x%x", act->pBuff[3]);
    if (0x05 == act->pBuff[2])
    {
        if (NFCSTATUS_SUCCESS == act->pBuff[3])
        {
            result = 1;
            NXPLOG_NCIHAL_D("Antenna: TxLDO current measured raw value in mA : 0x%x", act->pBuff[4]);
            if(0x00 == act->pBuff[5])
            {
                NXPLOG_NCIHAL_D("Measured range : 0x00 = 50 - 100 mA");
                measured_val = ((0.40 * act->pBuff[4]) + 50);
                NXPLOG_NCIHAL_D("TxLDO current absolute value in mA = %ld", measured_val);
            }
            else
            {
                NXPLOG_NCIHAL_D("Measured range : 0x01 = 20 - 70 mA");
                measured_val = ((0.40 * act->pBuff[4]) + 20);
                NXPLOG_NCIHAL_D("TxLDO current absolute value in mA = %ld", measured_val);
            }

            tolerance = (phAntenna_resp.wTxdoMeasuredRangeMax  *
                         phAntenna_resp.wTxdoMeasuredTolerance)/100;
            if ((measured_val <= phAntenna_resp.wTxdoMeasuredRangeMax + tolerance))
            {
                tolerance = (phAntenna_resp.wTxdoMeasuredRangeMin *
                             phAntenna_resp.wTxdoMeasuredTolerance)/100;
                if((measured_val >= phAntenna_resp.wTxdoMeasuredRangeMin - tolerance))
                {
                    gtxldo_status = NFCSTATUS_SUCCESS;
                    NXPLOG_NCIHAL_E("Test Antenna Response for TxLDO measurement PASS");
                }
                else
                {
                    gtxldo_status = NFCSTATUS_FAILED;
                    NXPLOG_NCIHAL_E("Test Antenna Response for TxLDO measurement FAIL");
                }
            }
            else
            {
                gtxldo_status = NFCSTATUS_FAILED;
                NXPLOG_NCIHAL_E("Test Antenna Response for TxLDO measurement FAIL");
            }
        }
        else
        {
            gtxldo_status = NFCSTATUS_FAILED;
            NXPLOG_NCIHAL_E("Test Antenna Response for TxLDO measurement failed: Invalid status");
        }

    }
    else
    {
        gtxldo_status = NFCSTATUS_FAILED;
        NXPLOG_NCIHAL_E("Test Antenna Response for TxLDO measurement failed: Invalid payload length");
    }

    return result;
}
/*******************************************************************************
 **
 ** 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         phTmlNfc_TmlWriterThread
**
** Description      Writes the requested data onto the lower layer driver
**
** Parameters       pParam  - context provided by upper layer
**
** Returns          None
**
*******************************************************************************/
static void phTmlNfc_TmlWriterThread(void *pParam)
{
    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
    /* Transaction info buffer to be passed to Callback Thread */
    static phTmlNfc_TransactInfo_t tTransactionInfo;
    /* Structure containing Tml callback function and parameters to be invoked
       by the callback thread */
    static phLibNfc_DeferredCall_t tDeferredInfo;
    /* Initialize Message structure to post message onto Callback Thread */
    static phLibNfc_Message_t tMsg;
    /* In case of I2C Write Retry */
    static uint16_t retry_cnt;
    UNUSED(pParam);
    NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n");

    /* Writer thread loop shall be running till shutdown is invoked */
    while (gpphTmlNfc_Context->bThreadDone)
    {
        NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n");
        sem_wait(&gpphTmlNfc_Context->txSemaphore);
        /* If Tml write is requested */
        if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable)
        {
            NXPLOG_TML_D("PN54X - Write requested.....\n");
            /* Set the variable to success initially */
            wStatus = NFCSTATUS_SUCCESS;
            if (NFCSTATUS_INVALID_DEVICE != (uintptr_t)gpphTmlNfc_Context->pDevHandle)
            {
                retry:

                gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
                /* Variable to fetch the actual number of bytes written */
                dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
                /* Write the data in the buffer onto the file */
                NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n");
                dwNoBytesWrRd = phTmlNfc_i2c_write(gpphTmlNfc_Context->pDevHandle,
                        gpphTmlNfc_Context->tWriteInfo.pBuffer,
                        gpphTmlNfc_Context->tWriteInfo.wLength
                        );

                /* Try I2C Write Five Times, if it fails : Raju */
                if (-1 == dwNoBytesWrRd)
                {
                    if (getDownloadFlag() == TRUE)
                    {
                        if (retry_cnt++ < MAX_WRITE_RETRY_COUNT)
                        {
                            NXPLOG_NCIHAL_E(
                                    "PN54X - Error in I2C Write  - Retry 0x%x", retry_cnt);
                            goto retry;
                        }
                    }
                    NXPLOG_TML_E("PN54X - Error in I2C Write.....\n");
                    wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
                }
                else
                {
                    phNxpNciHal_print_packet("SEND", gpphTmlNfc_Context->tWriteInfo.pBuffer,
                            gpphTmlNfc_Context->tWriteInfo.wLength);
                }
                retry_cnt = 0;
                if (NFCSTATUS_SUCCESS == wStatus)
                {
                    NXPLOG_TML_D("PN54X - I2C Write successful.....\n");
                    dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE;
                }
                /* Fill the Transaction info structure to be passed to Callback Function */
                tTransactionInfo.wStatus = wStatus;
                tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer;
                /* Actual number of bytes written is filled in the structure */
                tTransactionInfo.wLength = (uint16_t) dwNoBytesWrRd;

                /* Prepare the message to be posted on the User thread */
                tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb;
                tDeferredInfo.pParameter = &tTransactionInfo;
                /* Write operation completed successfully. Post a Message onto Callback Thread*/
                tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
                tMsg.pMsgData = &tDeferredInfo;
                tMsg.Size = sizeof(tDeferredInfo);

                /* Check whether Retransmission needs to be started,
                 * If yes, Post message only if
                 * case 1. Message is not posted &&
                 * case 11. Write status is success ||
                 * case 12. Last retry of write is also failure
                 */
                if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
                        (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0)))
                {
                    if (FALSE == gpphTmlNfc_Context->bWriteCbInvoked)
                    {
                        if ((NFCSTATUS_SUCCESS == wStatus) ||
                                (bCurrentRetryCount == 0))
                        {
                                NXPLOG_TML_D("PN54X - Posting Write message.....\n");
                                phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId,
                                        &tMsg);
                                gpphTmlNfc_Context->bWriteCbInvoked = TRUE;
                        }
                    }
                }
                else
                {
                    NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n");
                    phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
                }
            }
            else
            {
                NXPLOG_TML_D("PN54X - NFCSTATUS_INVALID_DEVICE != gpphTmlNfc_Context->pDevHandle");
            }

            /* If Data packet is sent, then NO retransmission */
            if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
                    (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0)))
            {
                NXPLOG_TML_D("PN54X - Starting timer for Retransmission case");
                wStatus = phTmlNfc_InitiateTimer();
                if (NFCSTATUS_SUCCESS != wStatus)
                {
                    /* Reset Variables used for Retransmission */
                    NXPLOG_TML_D("PN54X - Retransmission timer initiate failed");
                    gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
                    bCurrentRetryCount = 0;
                }
            }
        }
        else
        {
            NXPLOG_TML_D("PN54X - Write request NOT enabled");
            usleep(10000);
        }

    }/* End of While loop */

    return;
}
/*******************************************************************************
 **
 ** 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         phNxpNciHal_NfcDep_rsp_ext
**
** Description      Implements algorithm for NFC-DEP protocol priority over
**                  ISO-DEP protocol.
**                  Following the algorithm:
**                  IF ISO-DEP detected first time,set the ISO-DEP detected flag
**                  and resume polling loop with 60ms timeout value.
**                      a) if than NFC-DEP detected than send the response to
**                       libnfc-nci stack and stop the timer.
**                      b) if NFC-DEP not detected with in 60ms, than restart the
**                          polling loop to give early chance to ISO-DEP with a
**                          cleanup timer.
**                      c) if ISO-DEP detected second time send the response to
**                          libnfc-nci stack and stop the cleanup timer.
**                      d) if ISO-DEP not detected with in cleanup timeout, than
**                          clear the ISO-DEP detection flag.
**
** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED
**
*******************************************************************************/
NFCSTATUS phNxpNciHal_NfcDep_rsp_ext(uint8_t *p_ntf, uint16_t *p_len)
{
    NFCSTATUS status = NFCSTATUS_INVALID_PARAMETER;

    NXPLOG_NCIHAL_D(">> p_ntf[0]=%02x , p_ntf[1]=%02x",p_ntf[0],p_ntf[1]);

    if(p_ntf[0] == 0x41 && p_ntf[1] == 0x04)
    {
        //Tag selected, Disable P2P Prio logic.
        bIgnoreIsoDep = 1;
        NXPLOG_NCIHAL_D(">> Tag selected, Disable P2P Prio logic.");

    }
    else if( ((p_ntf[0] == 0x61 && p_ntf[1] == 0x06) ||
            (p_ntf[0] == 0x41 && p_ntf[1] == 0x06) ) && bIgnoreIsoDep == 1
            )
    {
        //Tag deselected, enable P2P Prio logic.
        bIgnoreIsoDep = 0x00;
        NXPLOG_NCIHAL_D(">> Tag deselected, enable P2P Prio logic.");

    }
    if (bIgnoreIsoDep == 0x00 &&
            p_ntf[0] == 0x61 &&
            p_ntf[1] == 0x05 && *p_len > 5)
    {
        if (p_ntf[5] == 0x04 && p_ntf[6] < 0x80)
        {
            NXPLOG_NCIHAL_D(">> ISO DEP detected.");

            if (iso_dep_detected == 0x00)
            {
                NXPLOG_NCIHAL_D(
                        ">> ISO DEP detected first time. Resume polling loop");

                iso_dep_detected = 0x01;
                status = phNxpNciHal_resume_polling_loop();

                custom_poll_timer = phOsalNfc_Timer_Create();
                NXPLOG_NCIHAL_D("custom poll timer started - %d", custom_poll_timer);

                status = phOsalNfc_Timer_Start(custom_poll_timer,
                        CUSTOM_POLL_TIMEOUT,
                        &custom_poll_timer_handler,
                        NULL);

                if (NFCSTATUS_SUCCESS == status)
                {
                    NXPLOG_NCIHAL_D("custom poll timer started");
                }
                else
                {
                    NXPLOG_NCIHAL_E("custom poll timer not started!!!");
                    status  = NFCSTATUS_FAILED;
                }

                status = NFCSTATUS_FAILED;
            }
            else
            {
                NXPLOG_NCIHAL_D(">> ISO DEP detected second time.");
                /* Store notification */
                phNxpNciHal_NfcDep_store_ntf(p_ntf, *p_len);

                /* Stop Cleanup_timer */
                phOsalNfc_Timer_Stop(cleanup_timer);
                phOsalNfc_Timer_Delete(cleanup_timer);
                cleanup_timer=0;
                EnableP2P_PrioLogic = FALSE;
                iso_dep_detected = 0;
                status = NFCSTATUS_SUCCESS;
            }
        }
        else if (p_ntf[5] == 0x05)
        {
            NXPLOG_NCIHAL_D(">> NFC-DEP Detected - stopping the custom poll timer");

            phOsalNfc_Timer_Stop(custom_poll_timer);
            phOsalNfc_Timer_Delete(custom_poll_timer);
            EnableP2P_PrioLogic = FALSE;
            iso_dep_detected = 0;
            status = NFCSTATUS_SUCCESS;
        }
        else
        {
            NXPLOG_NCIHAL_D(">>  detected other technology- stopping the custom poll timer");
            phOsalNfc_Timer_Stop(custom_poll_timer);
            phOsalNfc_Timer_Delete(custom_poll_timer);
            EnableP2P_PrioLogic = FALSE;
            iso_dep_detected = 0;
            status = NFCSTATUS_INVALID_PARAMETER;
        }
    }
    else if( bIgnoreIsoDep == 0x00 &&
            ((p_ntf[0] == 0x41 && p_ntf[1] == 0x06) || (p_ntf[0] == 0x61
            && p_ntf[1] == 0x06))
            )
    {
        NXPLOG_NCIHAL_D(">> RF disabled");
        if (poll_timer_fired == 0x01)
        {
            poll_timer_fired = 0x00;

            NXPLOG_NCIHAL_D(">>restarting polling loop.");

            /* start polling loop */
            phNxpNciHal_start_polling_loop();
            EnableP2P_PrioLogic = FALSE;
            NXPLOG_NCIHAL_D (">> NFC DEP NOT  detected - custom poll timer expired - RF disabled");

            cleanup_timer = phOsalNfc_Timer_Create();

            /* Start cleanup_timer */
            NFCSTATUS status = phOsalNfc_Timer_Start(cleanup_timer,
                    CLEAN_UP_TIMEOUT,
                    &cleanup_timer_handler,
                    NULL);

            if (NFCSTATUS_SUCCESS == status)
            {
                NXPLOG_NCIHAL_D("cleanup timer started");
            }
            else
            {
                NXPLOG_NCIHAL_E("cleanup timer not started!!!");
                status  = NFCSTATUS_FAILED;
            }

            status = NFCSTATUS_FAILED;
        }
        else
        {
            status = NFCSTATUS_SUCCESS;
        }
    }
    if (bIgnoreIsoDep == 0x00 &&
            iso_dep_detected == 1)
    {
        if ((p_ntf[0] == 0x41 && p_ntf[1] == 0x06) || (p_ntf[0] == 0x61
                && p_ntf[1] == 0x06))
        {
            NXPLOG_NCIHAL_D(">>iso_dep_detected Disconnect related notification");
            status = NFCSTATUS_FAILED;
        }
        else
        {
            NXPLOG_NCIHAL_W("Never come here");
        }
    }

    return status;
}
void phNxpNciHal_emergency_recovery(void)
{
    NXPLOG_NCIHAL_E("%s: abort()", __FUNCTION__);
//    abort();
}
/*******************************************************************************
**
** Function         listRemove
**
** Description      Remove node from the list
**
** Returns          1, if removed, 0 if otherwise
**
*******************************************************************************/
int listRemove(struct listHead* pList, void* pData)
{
    struct listNode* pNode;
    struct listNode* pRemovedNode;
    int result;

    pthread_mutex_lock(&pList->mutex);

    if (pList->pFirst == NULL)
    {
        /* Empty list */
        NXPLOG_NCIHAL_E("Failed to deallocate (list empty)");
        result = 0;
        goto clean_and_return;
    }

    pNode = pList->pFirst;
    if (pList->pFirst->pData == pData)
    {
        /* Get the removed node */
        pRemovedNode = pNode;

        /* Remove the first node */
        pList->pFirst = pList->pFirst->pNext;
    }
    else
    {
        while (pNode->pNext != NULL)
        {
            if (pNode->pNext->pData == pData)
            {
                /* Node found ! */
                break;
            }
            pNode = pNode->pNext;
        }

        if (pNode->pNext == NULL)
        {
            /* Node not found */
            result = 0;
            NXPLOG_NCIHAL_E("Failed to deallocate (not found %8p)", pData);
            goto clean_and_return;
        }

        /* Get the removed node */
        pRemovedNode = pNode->pNext;

        /* Remove the node from the list */
        pNode->pNext = pNode->pNext->pNext;
    }

    /* Deallocate the node */
    free(pRemovedNode);

    result = 1;

clean_and_return:
    pthread_mutex_unlock(&pList->mutex);
    return result;
}