/*******************************************************************************
**
** Function         phTmlNfc_InitiateTimer
**
** Description      Start a timer for Tx and Rx thread.
**
** Parameters       void
**
** Returns          NFC status
**
*******************************************************************************/
static NFCSTATUS phTmlNfc_InitiateTimer(void)
{
    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;

    /* Start Timer once Nci packet is sent */
    wStatus = phOsalNfc_Timer_Start(gpphTmlNfc_Context->dwTimerId,
            (uint32_t) PHTMLNFC_MAXTIME_RETRANSMIT,
            phTmlNfc_ReTxTimerCb, NULL);

    return wStatus;
}
/*******************************************************************************
**
** 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         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;
}
static 
void 
phLlcNfc_ConnectionTimeoutCb (
    uint32_t TimerId,
    void *pContext
)
{
    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
    phNfc_sCompletionInfo_t     notifyinfo = {0};
    pphNfcIF_Notification_CB_t  notifyul = NULL;
    void                        *p_upperctxt = NULL;
    phLlcNfc_Frame_t            *ps_frame_info = NULL;
    phLlcNfc_Timerinfo_t        *ps_timer_info = NULL;
    PHNFC_UNUSED_VARIABLE(pContext);
    
    PH_LLCNFC_PRINT("\n\nLLC : CONNECTION TIMEOUT CB CALLED\n\n");
    if ((NULL != gpphLlcNfc_Ctxt) && (TimerId == 
        gpphLlcNfc_Ctxt->s_timerinfo.timer_id[PH_LLCNFC_CONNECTIONTIMER]) 
        && (PH_LLCNFC_CON_TO_BIT_VAL == 
        (gpphLlcNfc_Ctxt->s_timerinfo.timer_flag & 
        PH_LLCNFC_CON_TO_BIT_VAL)))
    {
        ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo);
        ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo);
        if (ps_timer_info->con_to_value > 0)
        {
#if !defined (CYCLIC_TIMER)
            phOsalNfc_Timer_Stop(
                    ps_timer_info->timer_id[PH_LLCNFC_CONNECTIONTIMER]);
            /* phLlcNfc_StopTimers(PH_LLCNFC_CONNECTIONTIMER, 0); */
#endif
            ps_timer_info->con_to_value = 0;
        
            if (0 == ps_timer_info->con_to_value)
            {
                PH_LLCNFC_DEBUG("TIMER EXPIRED RETRY COUNT : %02X\n", ps_frame_info->retry_cnt);
                phLlcNfc_StopTimers (PH_LLCNFC_CONNECTIONTIMER, 0);
                
                if (ps_frame_info->retry_cnt < PH_LLCNFC_MAX_RETRY_COUNT)
                {
                    /* Create a U frame */
                    result = phLlcNfc_H_CreateUFramePayload(gpphLlcNfc_Ctxt, 
                                        &(ps_frame_info->s_llcpacket),
                                        &(ps_frame_info->s_llcpacket.llcbuf_len), 
                                        phLlcNfc_e_rset);

                    if (NFCSTATUS_SUCCESS == result)
                    {
                        /* Call DAL write */
                        result = phLlcNfc_Interface_Write (gpphLlcNfc_Ctxt, 
                                (uint8_t*)&(ps_frame_info->s_llcpacket.s_llcbuf), 
                                (uint32_t)(ps_frame_info->s_llcpacket.llcbuf_len));
                    }
                    if (NFCSTATUS_PENDING == result)
                    {
                        /* Start the timer */
                        result = phLlcNfc_StartTimers(PH_LLCNFC_CONNECTIONTIMER, 0);
                        if (NFCSTATUS_SUCCESS == result)
                        {
                            ps_frame_info->retry_cnt++;
                            result = NFCSTATUS_PENDING;
                        }
                    }
                    else
                    {
                        if (NFCSTATUS_BUSY == PHNFCSTATUS(result))
                        {
                            result = NFCSTATUS_PENDING;
                        }
                    }
                }
                else
                {
                    PH_LLCNFC_PRINT("RETRY COUNT LIMIT REACHED \n");
                    if ((ps_frame_info->retry_cnt == PH_LLCNFC_MAX_RETRY_COUNT) 
                        && (NULL != gpphLlcNfc_Ctxt->cb_for_if.notify))
                    {
                        void            *p_hw_info = NULL;
                        uint8_t         type = 0;
                        
                        p_hw_info = gpphLlcNfc_Ctxt->phwinfo;
                        notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, 
                                            NFCSTATUS_BOARD_COMMUNICATION_ERROR);
                        
                        notifyul = gpphLlcNfc_Ctxt->cb_for_if.notify;
                        p_upperctxt = gpphLlcNfc_Ctxt->cb_for_if.pif_ctxt;
                        type = NFC_NOTIFY_ERROR;
                        if (init_u_rset_frame == ps_frame_info->sent_frame_type)
                        {
                            type = NFC_NOTIFY_INIT_FAILED;
                            /* Release if, the initialisation is not complete */
                            result = phLlcNfc_Release(gpphLlcNfc_Ctxt, p_hw_info);
                            gpphLlcNfc_Ctxt = NULL;
                        }
                        else
                        {
                            type = NFC_NOTIFY_DEVICE_ERROR;
                            notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, 
                                            NFCSTATUS_BOARD_COMMUNICATION_ERROR);
#if 0
                            phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); 
#endif /* #if 0 */
                        }
                        /* Notify the upper layer */
                        notifyul(p_upperctxt, p_hw_info, type, &notifyinfo);
                    }
                }
            }
#if !defined (CYCLIC_TIMER)
            else
            {
                /* Start the timer again */
                phOsalNfc_Timer_Start(
                            ps_timer_info->timer_id[PH_LLCNFC_CONNECTIONTIMER], 
                            ps_timer_info->con_to_value, phLlcNfc_ConnectionTimeoutCb, NULL);
            }
#endif
        }
    }
    PH_LLCNFC_PRINT("\n\nLLC : CONNECTION TIMEOUT CB END\n\n");
}
static 
void 
phLlcNfc_GuardTimeoutCb (
    uint32_t TimerId,
    void *pContext
)
{
    NFCSTATUS                   result = NFCSTATUS_SUCCESS;
    phLlcNfc_Timerinfo_t        *ps_timer_info = NULL;
    phLlcNfc_Frame_t            *ps_frame_info = NULL;
    phLlcNfc_LlcPacket_t        *ps_packet_info = NULL;
    uint8_t                     index = 0;
    uint8_t                     zero_to_index = 0;
#if defined (GUARD_TO_ERROR)
    phNfc_sCompletionInfo_t     notifyinfo = {0};
#endif /* #if defined (GUARD_TO_ERROR) */
    PHNFC_UNUSED_VARIABLE(pContext);

    PH_LLCNFC_PRINT("\n\nLLC : GUARD TIMEOUT CB CALLED \n\n");

    if ((NULL != gpphLlcNfc_Ctxt) && (TimerId == 
        gpphLlcNfc_Ctxt->s_timerinfo.timer_id[PH_LLCNFC_GUARDTIMER]) && 
        (PH_LLCNFC_GUARD_TO_BIT_VAL == 
        (gpphLlcNfc_Ctxt->s_timerinfo.timer_flag & 
        PH_LLCNFC_GUARD_TO_BIT_VAL)))
    {
        uint8_t                 timer_expired = FALSE;
        ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo);
        ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo);

#if !defined (CYCLIC_TIMER)
        phOsalNfc_Timer_Stop(
                    ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER]);
#endif

        PH_LLCNFC_DEBUG("NO OF TIMEOUT COUNT : 0x%02X\n", ps_timer_info->guard_to_count);
        /* Loop is completely depending on the number of different LLC  
           send called */
        while (index < ps_timer_info->guard_to_count) 
        {
            if (0 != ps_timer_info->guard_to_value[index])
            {
                if (ps_timer_info->guard_to_value[index] > 0)
                {
                    if (ps_timer_info->guard_to_value[index] >= 
                        PH_LLCNFC_RESOLUTION)
                    {
                        ps_timer_info->guard_to_value[index] = (uint16_t)
                            (ps_timer_info->guard_to_value[index] - 
                            PH_LLCNFC_RESOLUTION);
                    }
                    else
                    {
                        ps_timer_info->guard_to_value[index] = 0;
                    }
                }

                if (0 == ps_timer_info->guard_to_value[index])
                {
                    zero_to_index = index;
                    timer_expired = TRUE;
                }
            }
            index = (uint8_t)(index + 1);
        }

#if !defined (CYCLIC_TIMER)        
        /* Start the timer again */
        phOsalNfc_Timer_Start(
                    ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER], 
                    PH_LLCNFC_RESOLUTION, phLlcNfc_GuardTimeoutCb, NULL);
#endif
        PH_LLCNFC_DEBUG("TIMER EXPIRED : 0x%02X\n", timer_expired);        

        if (TRUE == timer_expired)
        {
            PH_LLCNFC_DEBUG("TIMER EXPIRED INDEX: 0x%02X\n", zero_to_index);
            PH_LLCNFC_DEBUG("TIMER EXPIRED NS INDEX: 0x%02X\n", ps_timer_info->timer_ns_value[zero_to_index]);
            PH_LLCNFC_DEBUG("TIMER EXPIRED RETRIES : 0x%02X\n", ps_timer_info->iframe_send_count[zero_to_index]);

            PH_LLCNFC_DEBUG("TIMER EXPIRED GUARD TIME-OUT COUNT: 0x%02X\n", ps_timer_info->guard_to_value[zero_to_index]);

            if ((0 == ps_timer_info->guard_to_value[zero_to_index]) && 
                (ps_timer_info->iframe_send_count[zero_to_index] < 
                LLC_GUARD_TIMER_RETRIES))
            {
                if (ps_frame_info->s_send_store.winsize_cnt > 0)
                {
                    uint8_t             start_index = 0;
                    uint8_t             timer_count = 0;
                    uint8_t             while_exit = FALSE;

                    timer_count = ps_timer_info->guard_to_count;

                    
                    /* Check before changing the index to resend, if index 
                        already exist then dont set the index */
                    while ((FALSE == while_exit) && (start_index < timer_count))
                    {
                        if (resend_i_frame == 
                            ps_timer_info->frame_type[start_index])
                        {
                            while_exit = TRUE;
                        }
                        else
                        {                     
                            start_index = (uint8_t)(start_index + 1);
                        }
                    }

                    if (TRUE == while_exit)
                    {
                        ps_timer_info->index_to_send = zero_to_index;
                    }

                    ps_timer_info->frame_type[zero_to_index] = (uint8_t)
                                                            resend_i_frame;
                    /* Now resend the frame stored */
                    result = phLlcNfc_H_SendTimedOutIFrame (gpphLlcNfc_Ctxt, 
                                            &(ps_frame_info->s_send_store), 
                                            0);
                }
            }
            else
            {
                if ((LLC_GUARD_TIMER_RETRIES == 
                    ps_timer_info->iframe_send_count[zero_to_index]) && 
                    (NULL != gpphLlcNfc_Ctxt->cb_for_if.notify))
                {
                    phLlcNfc_StopAllTimers ();
#if defined (GUARD_TO_ERROR)
                    
                    notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, 
                                        NFCSTATUS_BOARD_COMMUNICATION_ERROR);
#if 0
                    phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); 
#endif /* #if 0 */
                    /* Resend done, no answer from the device */
                    gpphLlcNfc_Ctxt->cb_for_if.notify (
                                    gpphLlcNfc_Ctxt->cb_for_if.pif_ctxt,
                                    gpphLlcNfc_Ctxt->phwinfo, 
                                    NFC_NOTIFY_DEVICE_ERROR, 
                                    &notifyinfo);

#endif /* #if defined (GUARD_TO_ERROR) */

#if (!defined (GUARD_TO_ERROR) && defined (GUARD_TO_URSET))

                    PH_LLCNFC_PRINT("U-RSET IS SENT \n");
                    ps_packet_info = &(gpphLlcNfc_Ctxt->s_frameinfo.s_llcpacket);

                    result = phLlcNfc_H_CreateUFramePayload(gpphLlcNfc_Ctxt, 
                                        ps_packet_info, 
                                        &(ps_packet_info->llcbuf_len), 
                                        phLlcNfc_e_rset);

                    result = phLlcNfc_Interface_Write(gpphLlcNfc_Ctxt, 
                                    (uint8_t*)&(ps_packet_info->s_llcbuf), 
                                    (uint32_t)ps_packet_info->llcbuf_len);

                    ps_frame_info->write_status = result;
                    if (NFCSTATUS_PENDING == result)
                    {
                        /* Start the timer */
                        result = phLlcNfc_StartTimers (PH_LLCNFC_CONNECTIONTIMER, 0);
                        if (NFCSTATUS_SUCCESS == result)
                        {
                            ps_frame_info->retry_cnt = 0;
                            gpphLlcNfc_Ctxt->s_frameinfo.sent_frame_type = 
                                                                    u_rset_frame;
                            result = NFCSTATUS_PENDING;
                        }
                    }
                    else
                    {
                        if (NFCSTATUS_BUSY == PHNFCSTATUS (result))
                        {                        
                            ps_frame_info->write_wait_call = u_rset_frame;
                        }
                    }

#endif /* #if defined (GUARD_TO_ERROR) */
                }
            }
        }
    }
    PH_LLCNFC_PRINT("\n\nLLC : GUARD TIMEOUT CB END\n\n");
}
NFCSTATUS 
phLlcNfc_StartTimers (
    uint8_t             TimerType, 
    uint8_t             ns_value
)
{
    NFCSTATUS               result = NFCSTATUS_SUCCESS;
#ifdef LLC_TIMER_ENABLE

    uint32_t                timerid = 0;
    uint8_t                 timerstarted = 0;
    uint8_t                 timer_count = 0;
    uint16_t                timer_resolution = 0;
    ppCallBck_t             Callback = NULL;
    phLlcNfc_Timerinfo_t    *ps_timer_info = NULL;

    ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo);
    PHNFC_UNUSED_VARIABLE(result);

    PH_LLCNFC_PRINT("\n\nLLC : START TIMER CALLED\n\n");
    /* Depending on the timer type, use the Osal callback */
    switch(TimerType)
    {
        case PH_LLCNFC_CONNECTIONTIMER:
        {
            /* Get the connection timer flag */
            timerstarted = (uint8_t)
                GET_BITS8(ps_timer_info->timer_flag, 
                        PH_LLCNFC_CON_TO_BIT, 
                        PH_LLCNFC_TO_NOOFBITS);
            if (0 == timerstarted)
            {
                /* Timer not started, so start the timer */
                gpphLlcNfc_Ctxt->s_timerinfo.timer_flag = (uint8_t)
                                SET_BITS8 (ps_timer_info->timer_flag,
                                        PH_LLCNFC_CON_TO_BIT, 
                                        PH_LLCNFC_TO_NOOFBITS, 
                                        (PH_LLCNFC_CON_TO_BIT + 1));
            }
            
            timerid = ps_timer_info->timer_id[PH_LLCNFC_CONNECTION_TO_INDEX];
            Callback = (ppCallBck_t)&phLlcNfc_ConnectionTimeoutCb;
            timer_resolution = ps_timer_info->con_to_value = (uint16_t)
                                            PH_LLCNFC_CONNECTION_TO_VALUE;
            break;
        }

        case PH_LLCNFC_GUARDTIMER:
        {
            if (ps_timer_info->guard_to_count < PH_LLCNFC_MAX_GUARD_TIMER)
            {
                timer_count = ps_timer_info->guard_to_count;
                timer_resolution = (uint16_t)PH_LLCNFC_RESOLUTION;

                PH_LLCNFC_DEBUG("RESOLUTION VALUE : 0x%02X\n", PH_LLCNFC_RESOLUTION);
                PH_LLCNFC_DEBUG("TIME-OUT VALUE : 0x%02X\n", PH_LLCNFC_GUARD_TO_VALUE);
                
                /* Get the guard timer flag */
                timerstarted = (uint8_t)
                    GET_BITS8 (ps_timer_info->timer_flag, 
                            PH_LLCNFC_GUARD_TO_BIT, 
                            PH_LLCNFC_TO_NOOFBITS);

                PH_LLCNFC_DEBUG("GUARD TIMER NS INDEX : 0x%02X\n", ns_value);
                PH_LLCNFC_DEBUG("GUARD TIMER COUNT : 0x%02X\n", timer_count);
                PH_LLCNFC_DEBUG("GUARD TIMER STARTED : 0x%02X\n", timerstarted);

                if (0 == timerstarted)
                {
                    /* Timer not started, so start the timer */
                    ps_timer_info->timer_flag = (uint8_t)
                        SET_BITS8 (ps_timer_info->timer_flag,
                                    PH_LLCNFC_GUARD_TO_BIT, 
                                    PH_LLCNFC_TO_NOOFBITS, 
                                    PH_LLCNFC_GUARD_TO_BIT);
                }
                
                timerid = ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER];
                Callback = (ppCallBck_t)&phLlcNfc_GuardTimeoutCb;

                /* Guard time out value */
                ps_timer_info->guard_to_value[timer_count] = (uint16_t)
                                        PH_LLCNFC_GUARD_TO_VALUE;

                ps_timer_info->timer_ns_value[timer_count] = ns_value;
                ps_timer_info->frame_type[timer_count] = (uint8_t)invalid_frame;
                ps_timer_info->iframe_send_count[timer_count] = 0;

                if ((timer_count > 0) && 
                    (ps_timer_info->guard_to_value[(timer_count - 1)] >= 
                    PH_LLCNFC_GUARD_TO_VALUE))
                {
                    /* If the timer has been started already and the 
                        value is same as the previous means that timer has still 
                        not expired, so the time out value is increased by 
                        a resolution */
                    ps_timer_info->guard_to_value[timer_count] = (uint16_t)
                            (ps_timer_info->guard_to_value[(timer_count - 1)] + 
                            PH_LLCNFC_RESOLUTION);
                }

                PH_LLCNFC_DEBUG("GUARD TIMER VALUE : 0x%04X\n", ps_timer_info->guard_to_value[timer_count]);

                
                ps_timer_info->guard_to_count = (uint8_t)(
                                        ps_timer_info->guard_to_count + 1);
            }
            else
            {
                /* TIMER should not start, because the time out count has readched the limit */
                timerstarted = TRUE;
            }
            break;
        }
        
#ifdef PIGGY_BACK

        case PH_LLCNFC_ACKTIMER:
        {
            /* Get the ack timer flag */
            timerstarted = (uint8_t)GET_BITS8 (
                                    ps_timer_info->timer_flag, 
                                    PH_LLCNFC_GUARD_TO_BIT, 
                                    PH_LLCNFC_TO_NOOFBITS);
            if (0 == timerstarted)
            {
                /* Timer not started, so start the timer */
                ps_timer_info->timer_flag = (uint8_t)
                                SET_BITS8 (ps_timer_info->timer_flag, 
                                        PH_LLCNFC_GUARD_TO_BIT
                                        PH_LLCNFC_TO_NOOFBITS
                                        (PH_LLCNFC_GUARD_TO_BIT - 1));
            }
            timerid = ps_timer_info->timer_id[PH_LLCNFC_ACKTIMER];
            Callback = (ppCallBck_t)&phLlcNfc_AckTimeoutCb;
            break;
        }

#endif /* #ifdef PIGGY_BACK */

        default:
        {
            result = PHNFCSTVAL(CID_NFC_LLC, 
                                NFCSTATUS_INVALID_PARAMETER);
            break;
        }
    }
    if ((NFCSTATUS_SUCCESS == result) && 
        (FALSE == timerstarted))
    {
        PH_LLCNFC_DEBUG("OSAL START TIMER CALLED TIMER ID : 0x%02X\n", timerid);
        phOsalNfc_Timer_Start (timerid, timer_resolution, Callback, NULL);
    }

    PH_LLCNFC_PRINT("\n\nLLC : START TIMER END\n\n");

#else /* #ifdef LLC_TIMER_ENABLE */

    PHNFC_UNUSED_VARIABLE(result);
    PHNFC_UNUSED_VARIABLE(TimerType);
    PHNFC_UNUSED_VARIABLE(ns_value);    

#endif /* #ifdef LLC_TIMER_ENABLE */
    return result;
}
NFCSTATUS phNciNfc_RegForConnCredits(
                                     uint8_t bConnId,
                                     pphNciNfc_ConnCreditsNtf_t pNotify,
                                     void *pContext,
                                     uint32_t CreditTo
                                     )
{
    NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    uint8_t     bConnListIdx;
    uint32_t TimerId;

    PH_LOG_NCI_FUNC_ENTRY();

    if((NULL == pNotify) || (NULL == pContext))
    {
        wStatus = PHNFCSTVAL(CID_NFC_NCI, NFCSTATUS_INVALID_PARAMETER);
        PH_LOG_NCI_INFO_STR(" Invalid Caller Layer Param(s) received ..");
    }
    else
    {
        for(bConnListIdx = 0; bConnListIdx < (MAX_LOGICAL_CONNS+1) ; bConnListIdx++)
        {
            if(bConnId == gphNciNfc_ConnMgmtInt.tConnInfo.tConnList[bConnListIdx].tConn.bConnId)
            {
                if((TRUE == gphNciNfc_ConnMgmtInt.tConnInfo.tConnList[bConnListIdx].bIfActive) ||
                    (CONNTYPE_STATIC == gphNciNfc_ConnMgmtInt.tConnInfo.tConnList[bConnListIdx].tConn.bConnId))
                {
                    wStatus = NFCSTATUS_SUCCESS;
                }
                else
                {
                    PH_LOG_NCI_CRIT_STR(" Interface not active for this connection");
                    wStatus = NFCSTATUS_FAILED;
                }
                break;
            }
        }

        if(NFCSTATUS_SUCCESS == wStatus)
        {
            gphNciNfc_ConnMgmtInt.bConnId = bConnId;
            gphNciNfc_ConnMgmtInt.pCrdtsNotify = pNotify;
            gphNciNfc_ConnMgmtInt.pContext = pContext;

            TimerId = phOsalNfc_Timer_Create();

            if (0 == TimerId)
            {
                PH_LOG_NCI_WARN_STR("Credit wait Timer Create failed!!");
                wStatus = NFCSTATUS_INSUFFICIENT_RESOURCES;
            }
            else
            {
                PH_LOG_NCI_INFO_STR("Credit wait Timer Created Successfully");

                gphNciNfc_ConnMgmtInt.tCWTimerIf.dwTimerId = TimerId;
                gphNciNfc_ConnMgmtInt.tCWTimerIf.TimerStatus = 0;

                PH_LOG_NCI_INFO_STR("Credit timeout set to %d, for ConnId 0x%x",CreditTo, bConnId);

                wStatus = phOsalNfc_Timer_Start(gphNciNfc_ConnMgmtInt.tCWTimerIf.dwTimerId,
                                                CreditTo,
                                                &phNciNfc_WaitCreditTimerCb,
                                                &gphNciNfc_ConnMgmtInt);

                if (NFCSTATUS_SUCCESS == wStatus)
                {
                    PH_LOG_NCI_INFO_STR("Credit wait timer started..");
                    gphNciNfc_ConnMgmtInt.tCWTimerIf.TimerStatus = 1;
                    /* Set the CreditsAwaited flag to indicate credit notif function to call the registered CB */
                    gphNciNfc_ConnMgmtInt.bCreditsAwaited = TRUE;
                }
                else
                {
                     PH_LOG_NCI_WARN_STR("Failed to start credit ntf wait timer!");
                     (void )phOsalNfc_Timer_Delete(gphNciNfc_ConnMgmtInt.tCWTimerIf.dwTimerId);
                     gphNciNfc_ConnMgmtInt.tCWTimerIf.dwTimerId = 0;
                     wStatus = NFCSTATUS_FAILED;
                }
            }
        }
    }

    PH_LOG_NCI_FUNC_EXIT();

    return wStatus;
}
/**Send complete handler*/
void phHal4Nfc_SendCompleteHandler(phHal4Nfc_Hal4Ctxt_t  *Hal4Ctxt,void *pInfo)
{
    pphHal4Nfc_SendCallback_t pUpperSendCb = NULL;
    pphHal4Nfc_TransceiveCallback_t pUpperTrcvCb = NULL;
    NFCSTATUS SendStatus = ((phNfc_sCompletionInfo_t *)pInfo)->status;
    pphHal4Nfc_DiscntCallback_t pUpperDisconnectCb = NULL;
    Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress = FALSE; 
    /*Send status Success or Pending disconnect in HAl4*/
    if((SendStatus != NFCSTATUS_SUCCESS)
        ||(NFC_INVALID_RELEASE_TYPE != Hal4Ctxt->sTgtConnectInfo.ReleaseType))
    {   
        Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
        /*Update Status*/
        SendStatus = (NFCSTATUS)(NFC_INVALID_RELEASE_TYPE != 
          Hal4Ctxt->sTgtConnectInfo.ReleaseType?NFCSTATUS_RELEASED:SendStatus);
        /*Callback For Target Send*/
        if(NULL != Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb)
        {
            pUpperSendCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb;
            Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb = NULL;
            (*pUpperSendCb)(
                Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
                SendStatus
                );
        }
        else/*Callback For Initiator Send*/
        {
            if(NULL !=  Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb)
            {
                Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData->length = 0;
                pUpperTrcvCb = Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb;
                Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL;
                (*pUpperTrcvCb)(
                    Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
                    Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
                    Hal4Ctxt->psTrcvCtxtInfo->psUpperRecvData,
                    SendStatus
                    );
            }
        }
        /*Issue Pending disconnect from HAl4*/
        if(NFC_INVALID_RELEASE_TYPE != Hal4Ctxt->sTgtConnectInfo.ReleaseType)
        {
            SendStatus = phHal4Nfc_Disconnect_Execute(gpphHal4Nfc_Hwref);
            if((NFCSTATUS_PENDING != SendStatus) &&
               (NULL != Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb))
            {
                pUpperDisconnectCb = 
                    Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb;
                Hal4Ctxt->sTgtConnectInfo.pUpperDisconnectCb = NULL;
                (*pUpperDisconnectCb)(
                    Hal4Ctxt->sUpperLayerInfo.psUpperLayerDisconnectCtxt,
                    Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
                    SendStatus                            
                    );/*Notify disconnect failed to upper layer*/       
            }
        }           
    }
    else 
    {
        /*More info remaining in send buffer.continue with sending remaining 
          bytes*/
        if(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length
                                            > PH_HAL4NFC_MAX_SEND_LEN)
        {           
            /*Set more info*/
            Hal4Ctxt->psTrcvCtxtInfo->
                XchangeInfo.params.nfc_info.more_info = TRUE;
            /*copy to tx_buffer ,remaining bytes.NumberOfBytesSent is the 
              number of bytes already sent from current send buffer.*/
            Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer
                = (Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer
                   + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent);
            Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length
                = PH_HAL4NFC_MAX_SEND_LEN;
            Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent
                += PH_HAL4NFC_MAX_SEND_LEN;
            Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length
                -= PH_HAL4NFC_MAX_SEND_LEN;
            PHDBG_INFO("Hal4:Calling Hci_senddata() from sendcompletehandler1");
            SendStatus = phHciNfc_Send_Data (
                Hal4Ctxt->psHciHandle,
                gpphHal4Nfc_Hwref,
                Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
                &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo)
                );
            if(NFCSTATUS_PENDING == SendStatus)
            {
                Hal4Ctxt->psTrcvCtxtInfo->P2P_Send_In_Progress = TRUE;
            }
        }
        /*Remaining bytes is less than PH_HAL4NFC_MAX_SEND_LEN*/
        else if(Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length > 0)
        {
            Hal4Ctxt->psTrcvCtxtInfo->
                XchangeInfo.params.nfc_info.more_info = FALSE;
            Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_length
                = (uint8_t)Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length;
            Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo.tx_buffer
                = (Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->buffer
                + Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent);
            Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent = 0;
            /*No of bytes remaining for next send*/
            Hal4Ctxt->psTrcvCtxtInfo->psUpperSendData->length = 0;
            PHDBG_INFO("Hal4:Calling Hci_senddata() from sendcompletehandler2");
            SendStatus = phHciNfc_Send_Data (
                Hal4Ctxt->psHciHandle,
                gpphHal4Nfc_Hwref,
                Hal4Ctxt->sTgtConnectInfo.psConnectedDevice,
                &(Hal4Ctxt->psTrcvCtxtInfo->XchangeInfo)
                );
        }
        else/*No more Bytes left.Send complete*/
        {
            Hal4Ctxt->psTrcvCtxtInfo->NumberOfBytesSent = 0;
            /*Callback For Target Send*/
            if(NULL != Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb)
            {
                pUpperSendCb = Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb;
                Hal4Ctxt->psTrcvCtxtInfo->pP2PSendCb = NULL;
                (*pUpperSendCb)(
                    Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt,
                     SendStatus
                    );
            }
            else
            {
                /**Start timer to keep track of transceive timeout*/
#ifdef TRANSACTION_TIMER
                phOsalNfc_Timer_Start(
                    Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId,
                    PH_HAL4NFC_TRANSCEIVE_TIMEOUT,
                    phHal4Nfc_TrcvTimeoutHandler
                    );
#endif /*TRANSACTION_TIMER*/
            }
        }
    }
    return;
}
NFCSTATUS 
phHal4Nfc_Receive(                
                  phHal_sHwReference_t                  *psHwReference,
                  phHal4Nfc_TransactInfo_t              *psRecvInfo,
                  pphHal4Nfc_ReceiveCallback_t          pReceiveCallback,
                  void                                  *pContext
                 )
{
    NFCSTATUS RetStatus = NFCSTATUS_PENDING;
    phHal4Nfc_Hal4Ctxt_t *Hal4Ctxt = NULL;
     /*NULL checks*/
    if((NULL == psHwReference) 
        ||( NULL == pReceiveCallback)
        ||( NULL == psRecvInfo))
    {
        phOsalNfc_RaiseException(phOsalNfc_e_PrecondFailed,1);
        RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_INVALID_PARAMETER);
    }
    /*Check initialised state*/
    else if((NULL == psHwReference->hal_context)
                        || (((phHal4Nfc_Hal4Ctxt_t *)
                                psHwReference->hal_context)->Hal4CurrentState 
                                               < eHal4StateOpenAndReady)
                        || (((phHal4Nfc_Hal4Ctxt_t *)
                                psHwReference->hal_context)->Hal4NextState 
                                               == eHal4StateClosed))
    {
        RetStatus = PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_NOT_INITIALISED);     
    }   
    else
    {
        Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)psHwReference->hal_context;
        if(NFC_EVT_ACTIVATED == Hal4Ctxt->sTgtConnectInfo.EmulationState)
        {
            /*Following condition gets satisfied only on target side,if receive
              is not already called*/
            if(NULL == Hal4Ctxt->psTrcvCtxtInfo)
            {
                Hal4Ctxt->psTrcvCtxtInfo= (pphHal4Nfc_TrcvCtxtInfo_t)
                    phOsalNfc_GetMemory((uint32_t)
                    (sizeof(phHal4Nfc_TrcvCtxtInfo_t)));
                if(NULL != Hal4Ctxt->psTrcvCtxtInfo)
                {
                    (void)memset(Hal4Ctxt->psTrcvCtxtInfo,0,
                        sizeof(phHal4Nfc_TrcvCtxtInfo_t));
                    Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
                        = PH_OSALNFC_INVALID_TIMER_ID;
                    Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus = NFCSTATUS_PENDING;
                }
            }
            if(NULL == Hal4Ctxt->psTrcvCtxtInfo)
            {
                phOsalNfc_RaiseException(phOsalNfc_e_NoMemory,0);
                RetStatus= PHNFCSTVAL(CID_NFC_HAL , 
                    NFCSTATUS_INSUFFICIENT_RESOURCES);
            }
            else /*Store callback & Return status pending*/
            {
                Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt = pContext;     
                /*Register upper layer callback*/
                Hal4Ctxt->psTrcvCtxtInfo->pUpperTranceiveCb = NULL;
                Hal4Ctxt->psTrcvCtxtInfo->pP2PRecvCb = pReceiveCallback;
                if(NFCSTATUS_PENDING != 
                    Hal4Ctxt->psTrcvCtxtInfo->RecvDataBufferStatus)
                {               
                    /**Create a timer to send received data in the callback*/
                    if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
                        == PH_OSALNFC_INVALID_TIMER_ID)
                    {
                        PHDBG_INFO("HAL4: Transaction Timer Create for Receive");
                        Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId 
                            = phOsalNfc_Timer_Create();
                    }
                    if(Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId
                        == PH_OSALNFC_INVALID_TIMER_ID)
                    {
                        RetStatus = PHNFCSTVAL(CID_NFC_HAL ,
                            NFCSTATUS_INSUFFICIENT_RESOURCES);                      
                    }
                    else/*start the timer*/
                    {
                        phOsalNfc_Timer_Start(
                            Hal4Ctxt->psTrcvCtxtInfo->TransactionTimerId,
                            PH_HAL4NFC_RECV_CB_TIMEOUT,
							 phHal4Nfc_P2PRecvTimerCb,
							 NULL
                            );
                    }
                }
            }
        }
        else/*deactivated*/
        {
            RetStatus= PHNFCSTVAL(CID_NFC_HAL ,NFCSTATUS_DESELECTED);
        }
    }   
    return RetStatus;
}