/*
* Copyright (C) 2010 NXP Semiconductors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*!
* \file phLlcNfc_Timer.c
* \brief To create, start, stop and destroy timer.
*
* Project: NFC-FRI-1.1
*
* $Date: Mon Jun 14 11:47:54 2010 $
* $Author: ing02260 $
* $Revision: 1.55 $
* $Aliases: NFC_FRI1.1_WK1023_R35_2,NFC_FRI1.1_WK1023_R35_1 $
*
*/
/*************************** Includes *******************************/
#include <phNfcTypes.h>
#include <phNfcStatus.h>
#include <phOsalNfc.h>
#include <phOsalNfc_Timer.h>
#include <phNfcInterface.h>
#include <phLlcNfc.h>
#include <phLlcNfc_DataTypes.h>
#include <phLlcNfc_Interface.h>
#include <phLlcNfc_Frame.h>
#include <phLlcNfc_Timer.h>
/*********************** End of includes ****************************/
/***************************** Macros *******************************/
/**< Timer for connection timer index */
#define PH_LLCNFC_CONNECTION_TO_INDEX (0x00)
/**< Maximum guard timer can be present */
#define PH_LLCNFC_MAX_GUARD_TIMER (0x04)
/** Connection time out bit to set */
#define PH_LLCNFC_CON_TO_BIT (0)
/** Guard time out bit to set */
#define PH_LLCNFC_GUARD_TO_BIT (1)
/** Ack time out bit to set */
#define PH_LLCNFC_ACK_TO_BIT (2)
/** No of bits to set */
#define PH_LLCNFC_TO_NOOFBITS (1)
/** Connection time out bit value */
#define PH_LLCNFC_CON_TO_BIT_VAL (0x01)
/** Guard time out bit to set */
#define PH_LLCNFC_GUARD_TO_BIT_VAL (0x02)
/** ACK time out bit to set */
#define PH_LLCNFC_ACK_TO_BIT_VAL (0x04)
#define GUARD_TO_URSET
/************************ End of macros *****************************/
/*********************** Local functions ****************************/
/* This callback is for guard time out */
#ifdef LLC_TIMER_ENABLE
static
void
phLlcNfc_GuardTimeoutCb (
uint32_t TimerId,
void *pContext
);
#ifdef PIGGY_BACK
/* This callback is for acknowledge time out */
static
void
phLlcNfc_AckTimeoutCb (
uint32_t TimerId
);
#endif /* #ifdef PIGGY_BACK */
/* This callback is for connection time out */
static
void
phLlcNfc_ConnectionTimeoutCb (
uint32_t TimerId,
void *pContext
);
#endif /* #ifdef LLC_TIMER_ENABLE */
/******************** End of Local functions ************************/
/********************** Global variables ****************************/
static phLlcNfc_Context_t *gpphLlcNfc_Ctxt = NULL;
/******************** End of Global Variables ***********************/
NFCSTATUS
phLlcNfc_TimerInit(
phLlcNfc_Context_t *psLlcCtxt
)
{
NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC,
NFCSTATUS_INVALID_PARAMETER);
uint8_t index = 0;
if (NULL != psLlcCtxt)
{
result = NFCSTATUS_SUCCESS;
gpphLlcNfc_Ctxt = psLlcCtxt;
while (index < PH_LLCNFC_MAX_TIMER_USED)
{
#ifdef LLC_TIMER_ENABLE
gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index] =
PH_OSALNFC_INVALID_TIMER_ID;
#endif /* #ifdef LLC_TIMER_ENABLE */
index++;
}
}
return result;
}
void
phLlcNfc_TimerUnInit(
phLlcNfc_Context_t *psLlcCtxt
)
{
uint8_t index = 0;
if ((NULL != gpphLlcNfc_Ctxt) &&
(gpphLlcNfc_Ctxt == psLlcCtxt))
{
while (index <= PH_LLCNFC_ACKTIMER)
{
if (PH_LLCNFC_GUARDTIMER == index)
{
phLlcNfc_StopTimers (index,
gpphLlcNfc_Ctxt->s_timerinfo.guard_to_count);
}
else
{
phLlcNfc_StopTimers (index, 0);
}
index++;
}
phLlcNfc_DeleteTimer();
}
}
void
phLlcNfc_CreateTimers(void)
{
uint8_t index = 0;
while (index < PH_LLCNFC_MAX_TIMER_USED)
{
#ifdef LLC_TIMER_ENABLE
gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index] =
phOsalNfc_Timer_Create();
#endif /* #ifdef LLC_TIMER_ENABLE */
index++;
}
return;
}
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_ACK_TO_BIT,
PH_LLCNFC_TO_NOOFBITS);
if (FALSE == timerstarted)
{
/* Timer not started, so start the timer */
ps_timer_info->timer_flag = (uint8_t)
SET_BITS8 (ps_timer_info->timer_flag,
PH_LLCNFC_ACK_TO_BIT,
PH_LLCNFC_TO_NOOFBITS,
(PH_LLCNFC_ACK_TO_BIT - 1));
}
timer_resolution = ps_timer_info->ack_to_value = (uint16_t)
PH_LLCNFC_ACK_TO_VALUE;
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;
}
void
phLlcNfc_StopTimers (
uint8_t TimerType,
uint8_t no_of_guard_to_del
)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
#ifdef LLC_TIMER_ENABLE
uint32_t timerid = 0,
timerflag = FALSE;
uint8_t timer_count = 0;
phLlcNfc_Timerinfo_t *ps_timer_info = NULL;
ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo);
timerflag = ps_timer_info->timer_flag;
PHNFC_UNUSED_VARIABLE (result);
PH_LLCNFC_PRINT("\n\nLLC : STOP TIMER CALLED\n\n");
switch(TimerType)
{
case PH_LLCNFC_CONNECTIONTIMER:
{
ps_timer_info->timer_flag = (uint8_t)
SET_BITS8(ps_timer_info->timer_flag,
PH_LLCNFC_CON_TO_BIT,
PH_LLCNFC_TO_NOOFBITS, 0);
timerid = ps_timer_info->timer_id
[PH_LLCNFC_CONNECTION_TO_INDEX];
break;
}
case PH_LLCNFC_GUARDTIMER:
{
uint8_t start_index = 0;
timer_count = ps_timer_info->guard_to_count;
PH_LLCNFC_DEBUG("GUARD TIMER COUNT BEFORE DELETE: 0x%02X\n", timer_count);
PH_LLCNFC_DEBUG("GUARD TIMER TO DELETE: 0x%02X\n", no_of_guard_to_del);
if (timer_count > no_of_guard_to_del)
{
/* The number of guard timer count is more than the
guard timer to delete */
while (start_index < (timer_count - no_of_guard_to_del))
{
/* Copy the previous stored timer values to the present */
ps_timer_info->guard_to_value[start_index] = (uint16_t)
(ps_timer_info->guard_to_value[
(no_of_guard_to_del + start_index)]);
ps_timer_info->iframe_send_count[start_index] = (uint8_t)
(ps_timer_info->iframe_send_count[
(no_of_guard_to_del + start_index)]);
PH_LLCNFC_DEBUG("GUARD TIMER NS INDEX DELETED : 0x%02X\n", ps_timer_info->timer_ns_value[start_index]);
ps_timer_info->timer_ns_value[start_index] = (uint8_t)
(ps_timer_info->timer_ns_value[
(no_of_guard_to_del + start_index)]);
ps_timer_info->frame_type[start_index] = (uint8_t)
(ps_timer_info->frame_type[
(no_of_guard_to_del + start_index)]);
start_index = (uint8_t)(start_index + 1);
}
}
else
{
while (start_index < no_of_guard_to_del)
{
ps_timer_info->guard_to_value[start_index] = 0;
ps_timer_info->iframe_send_count[start_index] = 0;
PH_LLCNFC_DEBUG("GUARD TIMER NS INDEX DELETED ELSE : 0x%02X\n", ps_timer_info->timer_ns_value[start_index]);
ps_timer_info->timer_ns_value[start_index] = 0;
ps_timer_info->frame_type[start_index] = 0;
start_index = (uint8_t)(start_index + 1);
}
}
if (timer_count >= no_of_guard_to_del)
{
timer_count = (uint8_t)(timer_count - no_of_guard_to_del);
}
else
{
if (0 != no_of_guard_to_del)
{
timer_count = 0;
}
}
timerid = ps_timer_info->timer_id[PH_LLCNFC_GUARDTIMER];
ps_timer_info->guard_to_count = timer_count;
PH_LLCNFC_DEBUG("GUARD TIMER COUNT AFTER DELETE: 0x%02X\n", timer_count);
if (0 == ps_timer_info->guard_to_count)
{
/* This means that there are no frames to run guard
timer, so set the timer flag to 0 */
ps_timer_info->timer_flag = (uint8_t)
SET_BITS8 (ps_timer_info->timer_flag,
PH_LLCNFC_GUARD_TO_BIT,
PH_LLCNFC_TO_NOOFBITS, 0);
}
else
{
timerflag = 0;
}
break;
}
#ifdef PIGGY_BACK
case PH_LLCNFC_ACKTIMER:
{
timerflag = (timerflag & PH_LLCNFC_ACK_TO_BIT_VAL);
ps_timer_info->timer_flag = (uint8_t)
SET_BITS8 (ps_timer_info->timer_flag,
PH_LLCNFC_ACK_TO_BIT,
PH_LLCNFC_TO_NOOFBITS, 0);
timerid = ps_timer_info->timer_id[PH_LLCNFC_ACKTIMER];
ps_timer_info->ack_to_value = 0;
break;
}
#endif /* #ifdef PIGGY_BACK */
default:
{
result = PHNFCSTVAL(CID_NFC_LLC,
NFCSTATUS_INVALID_PARAMETER);
break;
}
}
if ((NFCSTATUS_SUCCESS == result) && (timerflag > 0))
{
PH_LLCNFC_DEBUG("OSAL STOP TIMER CALLED TIMER ID : 0x%02X\n", timerid);
phOsalNfc_Timer_Stop (timerid);
}
PH_LLCNFC_PRINT("\n\nLLC : STOP TIMER END\n\n");
#else /* #ifdef LLC_TIMER_ENABLE */
PHNFC_UNUSED_VARIABLE (result);
PHNFC_UNUSED_VARIABLE (TimerType);
PHNFC_UNUSED_VARIABLE (no_of_guard_to_del);
#endif /* #ifdef LLC_TIMER_ENABLE */
}
void
phLlcNfc_StopAllTimers (void)
{
#ifdef LLC_TIMER_ENABLE
phLlcNfc_Timerinfo_t *ps_timer_info = NULL;
uint8_t timer_started = 0;
uint32_t timerid = 0;
uint8_t timer_index = 0;
ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo);
PH_LLCNFC_PRINT("\n\nLLC : STOP ALL TIMERS CALLED \n\n");
timerid = ps_timer_info->timer_id[timer_index];
timer_started = (uint8_t)
GET_BITS8(ps_timer_info->timer_flag,
PH_LLCNFC_CON_TO_BIT,
PH_LLCNFC_TO_NOOFBITS);
PH_LLCNFC_DEBUG("CONNECTION TIMER ID: 0x%02X\n", timerid);
if (0 != timer_started)
{
/* Connection timer is started, so now stop it */
ps_timer_info->timer_flag = (uint8_t)
SET_BITS8 (ps_timer_info->timer_flag,
PH_LLCNFC_CON_TO_BIT,
PH_LLCNFC_TO_NOOFBITS, 0);
#if 0
ps_timer_info->con_to_value = 0;
#endif /* #if 0 */
phOsalNfc_Timer_Stop (timerid);
}
timer_index = (uint8_t)(timer_index + 1);
timerid = ps_timer_info->timer_id[timer_index];
timer_started = (uint8_t)GET_BITS8 (ps_timer_info->timer_flag,
PH_LLCNFC_GUARD_TO_BIT,
PH_LLCNFC_TO_NOOFBITS);
if (0 != timer_started)
{
/* Guard timer is already started */
ps_timer_info->timer_flag = (uint8_t)
SET_BITS8 (ps_timer_info->timer_flag,
PH_LLCNFC_GUARD_TO_BIT,
PH_LLCNFC_TO_NOOFBITS, 0);
timer_index = 0;
ps_timer_info->guard_to_count = 0;
#if 0
/* Reset all the guard timer related variables */
while (timer_index < ps_timer_info->guard_to_count)
{
ps_timer_info->guard_to_value[timer_index] = 0;
ps_timer_info->iframe_send_count[timer_index] = 0;
timer_index = (uint8_t)(timer_index + 1);
}
#endif /* #if 0 */
PH_LLCNFC_DEBUG("GUARD TIMER ID: 0x%02X\n", timerid);
/* Stop the timer */
phOsalNfc_Timer_Stop (timerid);
PH_LLCNFC_PRINT("\n\nLLC : STOP ALL TIMERS END \n\n");
}
#endif /* #ifdef LLC_TIMER_ENABLE */
}
void
phLlcNfc_DeleteTimer (void)
{
uint8_t index = 0;
while (index < PH_LLCNFC_MAX_TIMER_USED)
{
#ifdef LLC_TIMER_ENABLE
phOsalNfc_Timer_Delete(
gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index]);
gpphLlcNfc_Ctxt->s_timerinfo.timer_id[index] =
PH_OSALNFC_INVALID_TIMER_ID;
#endif /* #ifdef LLC_TIMER_ENABLE */
index++;
}
}
#ifdef LLC_TIMER_ENABLE
#define LLC_GUARD_TIMER_RETRIES (0x03U)
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 s_packet_info;
uint8_t index = 0;
/* zero_to_index = Time out index has become 0 */
uint8_t zero_to_index = 0;
#if defined (GUARD_TO_ERROR)
phNfc_sCompletionInfo_t notifyinfo = {0,0,0};
#endif /* #if defined (GUARD_TO_ERROR) */
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)
{
/* This loop runs for all the timer present in the data structure.
This means if there are 2 I frame has been sent and
response is not received for the I frames sent then the
each time this timer expires, the time out value is decremented
by the PH_LLCNFC_RESOLUTION value */
if (0 != ps_timer_info->guard_to_value[index])
{
/* If timer value is not zero then enter,
this means that the value is not zero */
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])
{
/* Timer value has expired, so resend has to be done
Timer value is 0 */
ps_timer_info->frame_type[index] = (uint8_t)resend_i_frame;
if (FALSE == timer_expired)
{
/* As the statement is in the loop, so there are possibilities
of more than 1 timer value can be 0, so if previous timer
value has already been 0, then again dont change the
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 (FALSE == while_exit)
{
/* This " ps_timer_info->index_to_send " member is
useful, when 2 time out values are 0, then
only first timed out value has to be resent and
other has to wait until the the first timed out
I frame is resent
This statement is executed only if, none of the timer
has expires previously, this is the first timer in the
list that has time out value has 0
*/
ps_timer_info->index_to_send = zero_to_index;
}
else
{
/* This statement is executed only if, any one of the time
out value was 0 previously, so first resend has to be done
for the previous I frame, so the index is set to the previous
I frame
*/
ps_timer_info->index_to_send = start_index;
}
/* 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,
¬ifyinfo);
#endif /* #if defined (GUARD_TO_ERROR) */
#if (!defined (GUARD_TO_ERROR) && defined (GUARD_TO_URSET))
PH_LLCNFC_PRINT("U-RSET IS SENT \n");
result = phLlcNfc_H_CreateUFramePayload(gpphLlcNfc_Ctxt,
&(s_packet_info),
&(s_packet_info.llcbuf_len),
phLlcNfc_e_rset);
result = phLlcNfc_Interface_Write(gpphLlcNfc_Ctxt,
(uint8_t*)&(s_packet_info.s_llcbuf),
(uint32_t)s_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");
}
#ifdef PIGGY_BACK
static
void
phLlcNfc_AckTimeoutCb (
uint32_t TimerId
)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
phLlcNfc_Frame_t *ps_frame_info = NULL;
phLlcNfc_Timerinfo_t *ps_timer_info = NULL;
phLlcNfc_LlcPacket_t s_packet_info;
PH_LLCNFC_PRINT("\n\nLLC : ACK TIMEOUT CB CALLED\n\n");
if ((NULL != gpphLlcNfc_Ctxt) && (TimerId ==
gpphLlcNfc_Ctxt->s_timerinfo.timer_id[PH_LLCNFC_ACKTIMER])
&& (PH_LLCNFC_ACK_TO_BIT_VAL ==
(gpphLlcNfc_Ctxt->s_timerinfo.timer_flag &
PH_LLCNFC_ACK_TO_BIT_VAL)))
{
ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo);
ps_timer_info = &(gpphLlcNfc_Ctxt->s_timerinfo);
phLlcNfc_StopTimers (PH_LLCNFC_ACKTIMER, 0);
if (NFCSTATUS_BUSY == PHNFCSTATUS (ps_frame_info->write_status))
{
/* Any how write cannot be done and some frame is ready to be sent
so this frame will act as the ACK */
result = phLlcNfc_H_WriteWaitCall (gpphLlcNfc_Ctxt);
}
else
{
/* Create S frame */
(void)phLlcNfc_H_CreateSFramePayload (ps_frame_info, &(s_packet_info), phLlcNfc_e_rr);
result = phLlcNfc_Interface_Write(gpphLlcNfc_Ctxt,
(uint8_t *)&(s_packet_info.s_llcbuf),
(uint32_t)(s_packet_info.llcbuf_len));
if (NFCSTATUS_PENDING == result)
{
if (0 == ps_frame_info->send_error_count)
{
ps_frame_info->write_wait_call = invalid_frame;
}
ps_frame_info->sent_frame_type = s_frame;
}
else
{
if (invalid_frame == ps_frame_info->write_wait_call)
{
ps_frame_info->write_wait_call = s_frame;
}
}
}
}
/* ACK is sent, so reset the response received count */
gpphLlcNfc_Ctxt->s_frameinfo.resp_recvd_count = 0;
PH_LLCNFC_PRINT("\n\nLLC : ACK TIMEOUT CB END\n\n");
}
#endif /* #ifdef PIGGY_BACK */
static
void
phLlcNfc_ConnectionTimeoutCb (
uint32_t TimerId,
void *pContext
)
{
NFCSTATUS result = NFCSTATUS_SUCCESS;
phNfc_sCompletionInfo_t notifyinfo = {0,0,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;
phLlcNfc_LlcPacket_t s_packet_info;
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,
&(s_packet_info),
&(s_packet_info.llcbuf_len),
phLlcNfc_e_rset);
if (NFCSTATUS_SUCCESS == result)
{
/* Call DAL write */
result = phLlcNfc_Interface_Write (gpphLlcNfc_Ctxt,
(uint8_t*)&(s_packet_info.s_llcbuf),
(uint32_t)(s_packet_info.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, ¬ifyinfo);
}
}
}
#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");
}
#endif /* #ifdef LLC_TIMER_ENABLE */
#ifdef LLC_URSET_NO_DELAY
/* NO definition required */
#else /* #ifdef LLC_URSET_NO_DELAY */
void
phLlcNfc_URSET_Delay_Notify (
uint32_t delay_id,
void *pContext)
{
phLlcNfc_Frame_t *ps_frame_info = NULL;
phNfc_sCompletionInfo_t notifyinfo = {0,0,0};
if (NULL != gpphLlcNfc_Ctxt)
{
ps_frame_info = &(gpphLlcNfc_Ctxt->s_frameinfo);
phOsalNfc_Timer_Stop (delay_id);
phOsalNfc_Timer_Delete (delay_id);
if (ps_frame_info->s_send_store.winsize_cnt > 0)
{
#if 0
/* Resend I frame */
(void)phLlcNfc_H_SendTimedOutIFrame (gpphLlcNfc_Ctxt,
&(ps_frame_info->s_send_store), 0);
#else
(void)phLlcNfc_H_SendUserIFrame (gpphLlcNfc_Ctxt,
&(ps_frame_info->s_send_store));
#endif /* #if 0 */
gpphLlcNfc_Ctxt->state = phLlcNfc_Resend_State;
}
else
{
if ((init_u_rset_frame == ps_frame_info->sent_frame_type) &&
(NULL != gpphLlcNfc_Ctxt->cb_for_if.notify))
{
ps_frame_info->sent_frame_type = write_resp_received;
notifyinfo.status = NFCSTATUS_SUCCESS;
/* Send the notification to the upper layer */
gpphLlcNfc_Ctxt->cb_for_if.notify (
gpphLlcNfc_Ctxt->cb_for_if.pif_ctxt,
gpphLlcNfc_Ctxt->phwinfo,
NFC_NOTIFY_INIT_COMPLETED,
¬ifyinfo);
}
}
}
}
#endif /* #ifdef LLC_URSET_NO_DELAY */