/******************************************************************************
*
* Copyright (C) 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include "gki_int.h"
#ifndef BT_ERROR_TRACE_0
#define BT_ERROR_TRACE_0(l, m)
#endif
/* Make sure that this has been defined in target.h */
#ifndef GKI_NUM_TIMERS
#error NO TIMERS: Must define at least 1 timer in the system!
#endif
/* Largest signed positive timer count */
#define GKI_NO_NEW_TMRS_STARTED (0x7fffffffL)
/* Marks an unused timer list entry (initial value) */
#define GKI_UNUSED_LIST_ENTRY (0x80000000L)
#define GKI_MAX_INT32 (0x7fffffffL)
/*******************************************************************************
**
** Function gki_timers_init
**
** Description This internal function is called once at startup to
*initialize
** all the timer structures.
**
** Returns void
**
*******************************************************************************/
void gki_timers_init(void) {
uint8_t tt;
gki_cb.com.OSTicksTilExp =
0; /* Remaining time (of OSTimeCurTimeout) before next timer expires */
gki_cb.com.OSNumOrigTicks = 0;
#if (GKI_DELAY_STOP_SYS_TICK > 0)
gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */
#endif
for (tt = 0; tt < GKI_MAX_TASKS; tt++) {
gki_cb.com.OSWaitTmr[tt] = 0;
#if (GKI_NUM_TIMERS > 0)
gki_cb.com.OSTaskTmr0[tt] = 0;
gki_cb.com.OSTaskTmr0R[tt] = 0;
#endif
#if (GKI_NUM_TIMERS > 1)
gki_cb.com.OSTaskTmr1[tt] = 0;
gki_cb.com.OSTaskTmr1R[tt] = 0;
#endif
#if (GKI_NUM_TIMERS > 2)
gki_cb.com.OSTaskTmr2[tt] = 0;
gki_cb.com.OSTaskTmr2R[tt] = 0;
#endif
#if (GKI_NUM_TIMERS > 3)
gki_cb.com.OSTaskTmr3[tt] = 0;
gki_cb.com.OSTaskTmr3R[tt] = 0;
#endif
}
for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
gki_cb.com.timer_queues[tt] = NULL;
}
gki_cb.com.p_tick_cb = NULL;
gki_cb.com.system_tick_running = false;
return;
}
/*******************************************************************************
**
** Function gki_timers_is_timer_running
**
** Description This internal function is called to test if any gki timer
*are running
**
**
** Returns TRUE if at least one time is running in the system, FALSE
*else.
**
*******************************************************************************/
bool gki_timers_is_timer_running(void) {
uint8_t tt;
for (tt = 0; tt < GKI_MAX_TASKS; tt++) {
#if (GKI_NUM_TIMERS > 0)
if (gki_cb.com.OSTaskTmr0[tt]) {
return true;
}
#endif
#if (GKI_NUM_TIMERS > 1)
if (gki_cb.com.OSTaskTmr1[tt]) {
return true;
}
#endif
#if (GKI_NUM_TIMERS > 2)
if (gki_cb.com.OSTaskTmr2[tt]) {
return true;
}
#endif
#if (GKI_NUM_TIMERS > 3)
if (gki_cb.com.OSTaskTmr3[tt]) {
return true;
}
#endif
}
return false;
}
/*******************************************************************************
**
** Function GKI_get_tick_count
**
** Description This function returns the current system ticks
**
** Returns The current number of system ticks
**
*******************************************************************************/
uint32_t GKI_get_tick_count(void) { return gki_cb.com.OSTicks; }
/*******************************************************************************
**
** Function GKI_ready_to_sleep
**
** Description This function returns the number of system ticks until the
** next timer will expire. It is typically called by a power
** savings manager to find out how long it can have the system
** sleep before it needs to service the next entry.
**
** Parameters: None
**
** Returns Number of ticks til the next timer expires
** Note: the value is a signed value. This value should be
** compared to x > 0, to avoid misinterpreting negative
*tick
** values.
**
*******************************************************************************/
int32_t GKI_ready_to_sleep(void) { return (gki_cb.com.OSTicksTilExp); }
/*******************************************************************************
**
** Function GKI_start_timer
**
** Description An application can call this function to start one of
** it's four general purpose timers. Any of the four timers
** can be 1-shot or continuous. If a timer is already running,
** it will be reset to the new parameters.
**
** Parameters tnum - (input) timer number to be started
*(TIMER_0,
** TIMER_1, TIMER_2, or TIMER_3)
** ticks - (input) the number of system ticks til the
** timer expires.
** is_continuous - (input) TRUE if timer restarts
*automatically,
** else FALSE if it is a
*'one-shot'.
**
** Returns void
**
*******************************************************************************/
void GKI_start_timer(uint8_t tnum, int32_t ticks, bool is_continuous) {
int32_t reload;
int32_t orig_ticks;
uint8_t task_id = GKI_get_taskid();
bool bad_timer = false;
if (ticks <= 0) ticks = 1;
orig_ticks = ticks; /* save the ticks in case adjustment is necessary */
/* If continuous timer, set reload, else set it to 0 */
if (is_continuous)
reload = ticks;
else
reload = 0;
GKI_disable();
if (gki_timers_is_timer_running() == false) {
#if (GKI_DELAY_STOP_SYS_TICK > 0)
/* if inactivity delay timer is not running, start system tick */
if (gki_cb.com.OSTicksTilStop == 0) {
#endif
if (gki_cb.com.p_tick_cb) {
/* start system tick */
gki_cb.com.system_tick_running = true;
(gki_cb.com.p_tick_cb)(true);
}
#if (GKI_DELAY_STOP_SYS_TICK > 0)
} else {
/* clear inactivity delay timer */
gki_cb.com.OSTicksTilStop = 0;
}
#endif
}
/* Add the time since the last task timer update.
** Note that this works when no timers are active since
** both OSNumOrigTicks and OSTicksTilExp are 0.
*/
if (GKI_MAX_INT32 - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) >
ticks) {
ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp;
} else
ticks = GKI_MAX_INT32;
switch (tnum) {
#if (GKI_NUM_TIMERS > 0)
case TIMER_0:
gki_cb.com.OSTaskTmr0R[task_id] = reload;
gki_cb.com.OSTaskTmr0[task_id] = ticks;
break;
#endif
#if (GKI_NUM_TIMERS > 1)
case TIMER_1:
gki_cb.com.OSTaskTmr1R[task_id] = reload;
gki_cb.com.OSTaskTmr1[task_id] = ticks;
break;
#endif
#if (GKI_NUM_TIMERS > 2)
case TIMER_2:
gki_cb.com.OSTaskTmr2R[task_id] = reload;
gki_cb.com.OSTaskTmr2[task_id] = ticks;
break;
#endif
#if (GKI_NUM_TIMERS > 3)
case TIMER_3:
gki_cb.com.OSTaskTmr3R[task_id] = reload;
gki_cb.com.OSTaskTmr3[task_id] = ticks;
break;
#endif
default:
bad_timer = true; /* Timer number is bad, so do not use */
}
/* Update the expiration timeout if a legitimate timer */
if (!bad_timer) {
/* Only update the timeout value if it is less than any other newly started
* timers */
gki_adjust_timer_count(orig_ticks);
}
GKI_enable();
}
/*******************************************************************************
**
** Function GKI_stop_timer
**
** Description An application can call this function to stop one of
** it's four general purpose timers. There is no harm in
** stopping a timer that is already stopped.
**
** Parameters tnum - (input) timer number to be started
*(TIMER_0,
** TIMER_1, TIMER_2, or TIMER_3)
** Returns void
**
*******************************************************************************/
void GKI_stop_timer(uint8_t tnum) {
uint8_t task_id = GKI_get_taskid();
GKI_disable();
switch (tnum) {
#if (GKI_NUM_TIMERS > 0)
case TIMER_0:
gki_cb.com.OSTaskTmr0R[task_id] = 0;
gki_cb.com.OSTaskTmr0[task_id] = 0;
break;
#endif
#if (GKI_NUM_TIMERS > 1)
case TIMER_1:
gki_cb.com.OSTaskTmr1R[task_id] = 0;
gki_cb.com.OSTaskTmr1[task_id] = 0;
break;
#endif
#if (GKI_NUM_TIMERS > 2)
case TIMER_2:
gki_cb.com.OSTaskTmr2R[task_id] = 0;
gki_cb.com.OSTaskTmr2[task_id] = 0;
break;
#endif
#if (GKI_NUM_TIMERS > 3)
case TIMER_3:
gki_cb.com.OSTaskTmr3R[task_id] = 0;
gki_cb.com.OSTaskTmr3[task_id] = 0;
break;
#endif
}
if (gki_timers_is_timer_running() == false) {
if (gki_cb.com.p_tick_cb) {
#if (GKI_DELAY_STOP_SYS_TICK > 0)
/* if inactivity delay timer is not running */
if ((gki_cb.com.system_tick_running) &&
(gki_cb.com.OSTicksTilStop == 0)) {
/* set inactivity delay timer */
/* when timer expires, system tick will be stopped */
gki_cb.com.OSTicksTilStop = GKI_DELAY_STOP_SYS_TICK;
}
#else
gki_cb.com.system_tick_running = false;
(gki_cb.com.p_tick_cb)(false); /* stop system tick */
#endif
}
}
GKI_enable();
}
/*******************************************************************************
**
** Function GKI_timer_update
**
** Description This function is called by an OS to drive the GKI's timers.
** It is typically called at every system tick to
** update the timers for all tasks, and check for timeouts.
**
** Note: It has been designed to also allow for variable tick
*updates
** so that systems with strict power savings requirements
*can
** have the update occur at variable intervals.
**
** Parameters: ticks_since_last_update - (input) This is the number of
*TICKS that have
** occurred since the last time GKI_timer_update was
*called.
**
** Returns void
**
*******************************************************************************/
void GKI_timer_update(int32_t ticks_since_last_update) {
uint8_t task_id;
long next_expiration; /* Holds the next soonest expiration time after this
update */
/* Increment the number of ticks used for time stamps */
gki_cb.com.OSTicks += ticks_since_last_update;
/* If any timers are running in any tasks, decrement the remaining time til
* the timer updates need to take place (next expiration occurs)
*/
gki_cb.com.OSTicksTilExp -= ticks_since_last_update;
/* Don't allow timer interrupt nesting */
if (gki_cb.com.timer_nesting) return;
gki_cb.com.timer_nesting = 1;
#if (GKI_DELAY_STOP_SYS_TICK > 0)
/* if inactivity delay timer is set and expired */
if (gki_cb.com.OSTicksTilStop) {
if (gki_cb.com.OSTicksTilStop <= (uint32_t)ticks_since_last_update) {
if (gki_cb.com.p_tick_cb) {
gki_cb.com.system_tick_running = false;
(gki_cb.com.p_tick_cb)(false); /* stop system tick */
}
gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */
gki_cb.com.timer_nesting = 0;
return;
} else
gki_cb.com.OSTicksTilStop -= ticks_since_last_update;
}
#endif
/* No need to update the ticks if no timeout has occurred */
if (gki_cb.com.OSTicksTilExp > 0) {
gki_cb.com.timer_nesting = 0;
return;
}
GKI_disable();
next_expiration = GKI_NO_NEW_TMRS_STARTED;
/* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase
gki_cb.com.OSNumOrigTicks
to account for the difference so timer updates below are decremented by the
full number
of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function
so changing this
value only affects the timer updates below
*/
gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp;
/* Check for OS Task Timers */
for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++) {
if (gki_cb.com.OSRdyTbl[task_id] == TASK_DEAD) {
// task is shutdown do not try to service timers
continue;
}
if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */
{
gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks;
if (gki_cb.com.OSWaitTmr[task_id] <= 0) {
/* Timer Expired */
gki_cb.com.OSRdyTbl[task_id] = TASK_READY;
}
}
#if (GKI_NUM_TIMERS > 0)
/* If any timer is running, decrement */
if (gki_cb.com.OSTaskTmr0[task_id] > 0) {
gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;
if (gki_cb.com.OSTaskTmr0[task_id] <= 0) {
/* Set Timer 0 Expired event mask and reload timer */
#if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
GKI_isend_event(task_id, TIMER_0_EVT_MASK);
#else
GKI_send_event(task_id, TIMER_0_EVT_MASK);
#endif
gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id];
}
}
/* Check to see if this timer is the next one to expire */
if (gki_cb.com.OSTaskTmr0[task_id] > 0 &&
gki_cb.com.OSTaskTmr0[task_id] < next_expiration)
next_expiration = gki_cb.com.OSTaskTmr0[task_id];
#endif
#if (GKI_NUM_TIMERS > 1)
/* If any timer is running, decrement */
if (gki_cb.com.OSTaskTmr1[task_id] > 0) {
gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks;
if (gki_cb.com.OSTaskTmr1[task_id] <= 0) {
/* Set Timer 1 Expired event mask and reload timer */
#if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
GKI_isend_event(task_id, TIMER_1_EVT_MASK);
#else
GKI_send_event(task_id, TIMER_1_EVT_MASK);
#endif
gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id];
}
}
/* Check to see if this timer is the next one to expire */
if (gki_cb.com.OSTaskTmr1[task_id] > 0 &&
gki_cb.com.OSTaskTmr1[task_id] < next_expiration)
next_expiration = gki_cb.com.OSTaskTmr1[task_id];
#endif
#if (GKI_NUM_TIMERS > 2)
/* If any timer is running, decrement */
if (gki_cb.com.OSTaskTmr2[task_id] > 0) {
gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks;
if (gki_cb.com.OSTaskTmr2[task_id] <= 0) {
/* Set Timer 2 Expired event mask and reload timer */
#if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
GKI_isend_event(task_id, TIMER_2_EVT_MASK);
#else
GKI_send_event(task_id, TIMER_2_EVT_MASK);
#endif
gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id];
}
}
/* Check to see if this timer is the next one to expire */
if (gki_cb.com.OSTaskTmr2[task_id] > 0 &&
gki_cb.com.OSTaskTmr2[task_id] < next_expiration)
next_expiration = gki_cb.com.OSTaskTmr2[task_id];
#endif
#if (GKI_NUM_TIMERS > 3)
/* If any timer is running, decrement */
if (gki_cb.com.OSTaskTmr3[task_id] > 0) {
gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks;
if (gki_cb.com.OSTaskTmr3[task_id] <= 0) {
/* Set Timer 3 Expired event mask and reload timer */
#if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
GKI_isend_event(task_id, TIMER_3_EVT_MASK);
#else
GKI_send_event(task_id, TIMER_3_EVT_MASK);
#endif
gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id];
}
}
/* Check to see if this timer is the next one to expire */
if (gki_cb.com.OSTaskTmr3[task_id] > 0 &&
gki_cb.com.OSTaskTmr3[task_id] < next_expiration)
next_expiration = gki_cb.com.OSTaskTmr3[task_id];
#endif
}
/* Set the next timer experation value if there is one to start */
if (next_expiration < GKI_NO_NEW_TMRS_STARTED) {
gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration;
} else {
gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0;
}
gki_cb.com.timer_nesting = 0;
GKI_enable();
return;
}
/*******************************************************************************
**
** Function GKI_timer_queue_empty
**
** Description This function is called by applications to see whether the
*timer
** queue is empty
**
** Parameters
**
** Returns bool
**
*******************************************************************************/
bool GKI_timer_queue_empty(void) {
uint8_t tt;
for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
if (gki_cb.com.timer_queues[tt]) return false;
}
return true;
}
/*******************************************************************************
**
** Function GKI_timer_queue_register_callback
**
** Description This function is called by applications to register system
*tick
** start/stop callback for time queues
**
**
** Parameters p_callback - (input) pointer to the system tick callback
**
** Returns bool
**
*******************************************************************************/
void GKI_timer_queue_register_callback(SYSTEM_TICK_CBACK* p_callback) {
gki_cb.com.p_tick_cb = p_callback;
return;
}
/*******************************************************************************
**
** Function GKI_init_timer_list
**
** Description This function is called by applications when they
** want to initialize a timer list.
**
** Parameters p_timer_listq - (input) pointer to the timer list queue
*object
**
** Returns void
**
*******************************************************************************/
void GKI_init_timer_list(TIMER_LIST_Q* p_timer_listq) {
p_timer_listq->p_first = NULL;
p_timer_listq->p_last = NULL;
p_timer_listq->last_ticks = 0;
return;
}
/*******************************************************************************
**
** Function GKI_init_timer_list_entry
**
** Description This function is called by the applications when they
** want to initialize a timer list entry. This must be
** done prior to first use of the entry.
**
** Parameters p_tle - (input) pointer to a timer list queue
*entry
**
** Returns void
**
*******************************************************************************/
void GKI_init_timer_list_entry(TIMER_LIST_ENT* p_tle) {
p_tle->p_next = NULL;
p_tle->p_prev = NULL;
p_tle->ticks = GKI_UNUSED_LIST_ENTRY;
p_tle->in_use = false;
}
/*******************************************************************************
**
** Function GKI_update_timer_list
**
** Description This function is called by the applications when they
** want to update a timer list. This should be at every
** timer list unit tick, e.g. once per sec, once per minute
*etc.
**
** Parameters p_timer_listq - (input) pointer to the timer list queue
*object
** num_units_since_last_update - (input) number of units since
*the last update
** (allows for variable unit update)
**
** NOTE: The following timer list update routines should not be used for
*exact time
** critical purposes. The timer tasks should be used when exact
*timing is needed.
**
** Returns the number of timers that have expired
**
*******************************************************************************/
uint16_t GKI_update_timer_list(TIMER_LIST_Q* p_timer_listq,
int32_t num_units_since_last_update) {
TIMER_LIST_ENT* p_tle;
uint16_t num_time_out = 0;
int32_t rem_ticks;
int32_t temp_ticks;
p_tle = p_timer_listq->p_first;
/* First, get the guys who have previously timed out */
/* Note that the tick value of the timers should always be '0' */
while ((p_tle) && (p_tle->ticks <= 0)) {
num_time_out++;
p_tle = p_tle->p_next;
}
/* Timer entriy tick values are relative to the preceeding entry */
rem_ticks = num_units_since_last_update;
/* Now, adjust remaining timer entries */
while ((p_tle != NULL) && (rem_ticks > 0)) {
temp_ticks = p_tle->ticks;
p_tle->ticks -= rem_ticks;
/* See if this timer has just timed out */
if (p_tle->ticks <= 0) {
/* We set the number of ticks to '0' so that the legacy code
* that assumes a '0' or nonzero value will still work as coded. */
p_tle->ticks = 0;
num_time_out++;
}
rem_ticks -= temp_ticks; /* Decrement the remaining ticks to process */
p_tle = p_tle->p_next;
}
if (p_timer_listq->last_ticks > 0) {
p_timer_listq->last_ticks -= num_units_since_last_update;
/* If the last timer has expired set last_ticks to 0 so that other list
* update
* functions will calculate correctly
*/
if (p_timer_listq->last_ticks < 0) p_timer_listq->last_ticks = 0;
}
return (num_time_out);
}
/*******************************************************************************
**
** Function GKI_get_remaining_ticks
**
** Description This function is called by an application to get remaining
** ticks to expire
**
** Parameters p_timer_listq - (input) pointer to the timer list queue
*object
** p_target_tle - (input) pointer to a timer list queue
*entry
**
** Returns 0 if timer is not used or timer is not in the list
** remaining ticks if success
**
*******************************************************************************/
uint32_t GKI_get_remaining_ticks(TIMER_LIST_Q* p_timer_listq,
TIMER_LIST_ENT* p_target_tle) {
TIMER_LIST_ENT* p_tle;
uint32_t rem_ticks = 0;
if (p_target_tle->in_use) {
p_tle = p_timer_listq->p_first;
/* adding up all of ticks in previous entries */
while ((p_tle) && (p_tle != p_target_tle)) {
rem_ticks += p_tle->ticks;
p_tle = p_tle->p_next;
}
/* if found target entry */
if (p_tle == p_target_tle) {
rem_ticks += p_tle->ticks;
} else {
BT_ERROR_TRACE_0(TRACE_LAYER_GKI,
"GKI_get_remaining_ticks: No timer entry in the list");
return (0);
}
} else {
BT_ERROR_TRACE_0(TRACE_LAYER_GKI,
"GKI_get_remaining_ticks: timer entry is not active");
}
return (rem_ticks);
}
/*******************************************************************************
**
** Function GKI_add_to_timer_list
**
** Description This function is called by an application to add a timer
** entry to a timer list.
**
** Note: A timer value of '0' will effectively insert an
*already
** expired event. Negative tick values will be ignored.
**
** Parameters p_timer_listq - (input) pointer to the timer list queue
*object
** p_tle - (input) pointer to a timer list queue
*entry
**
** Returns void
**
*******************************************************************************/
void GKI_add_to_timer_list(TIMER_LIST_Q* p_timer_listq, TIMER_LIST_ENT* p_tle) {
uint32_t nr_ticks_total;
uint8_t tt;
TIMER_LIST_ENT* p_temp;
if (p_tle == NULL || p_timer_listq == NULL) {
GKI_TRACE_3("%s: invalid argument %x, %x****************************<<",
__func__, p_timer_listq, p_tle);
return;
}
/* Only process valid tick values */
if (p_tle->ticks >= 0) {
/* If this entry is the last in the list */
if (p_tle->ticks >= p_timer_listq->last_ticks) {
/* If this entry is the only entry in the list */
if (p_timer_listq->p_first == NULL)
p_timer_listq->p_first = p_tle;
else {
/* Insert the entry onto the end of the list */
if (p_timer_listq->p_last != NULL)
p_timer_listq->p_last->p_next = p_tle;
p_tle->p_prev = p_timer_listq->p_last;
}
p_tle->p_next = NULL;
p_timer_listq->p_last = p_tle;
nr_ticks_total = p_tle->ticks;
p_tle->ticks -= p_timer_listq->last_ticks;
p_timer_listq->last_ticks = nr_ticks_total;
} else /* This entry needs to be inserted before the last entry */
{
/* Find the entry that the new one needs to be inserted in front of */
p_temp = p_timer_listq->p_first;
while (p_tle->ticks > p_temp->ticks) {
/* Update the tick value if looking at an unexpired entry */
if (p_temp->ticks > 0) p_tle->ticks -= p_temp->ticks;
p_temp = p_temp->p_next;
}
/* The new entry is the first in the list */
if (p_temp == p_timer_listq->p_first) {
p_tle->p_next = p_timer_listq->p_first;
p_timer_listq->p_first->p_prev = p_tle;
p_timer_listq->p_first = p_tle;
} else {
p_temp->p_prev->p_next = p_tle;
p_tle->p_prev = p_temp->p_prev;
p_temp->p_prev = p_tle;
p_tle->p_next = p_temp;
}
p_temp->ticks -= p_tle->ticks;
}
p_tle->in_use = true;
/* if we already add this timer queue to the array */
for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
if (gki_cb.com.timer_queues[tt] == p_timer_listq) return;
}
/* add this timer queue to the array */
for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
if (gki_cb.com.timer_queues[tt] == NULL) break;
}
if (tt < GKI_MAX_TIMER_QUEUES) {
gki_cb.com.timer_queues[tt] = p_timer_listq;
}
}
return;
}
/*******************************************************************************
**
** Function GKI_remove_from_timer_list
**
** Description This function is called by an application to remove a timer
** entry from a timer list.
**
** Parameters p_timer_listq - (input) pointer to the timer list queue
*object
** p_tle - (input) pointer to a timer list queue
*entry
**
** Returns void
**
*******************************************************************************/
void GKI_remove_from_timer_list(TIMER_LIST_Q* p_timer_listq,
TIMER_LIST_ENT* p_tle) {
uint8_t tt;
/* Verify that the entry is valid */
if (p_tle == NULL || p_tle->in_use == false ||
p_timer_listq->p_first == NULL) {
return;
}
/* Add the ticks remaining in this timer (if any) to the next guy in the list.
** Note: Expired timers have a tick value of '0'.
*/
if (p_tle->p_next != NULL) {
p_tle->p_next->ticks += p_tle->ticks;
} else {
p_timer_listq->last_ticks -= p_tle->ticks;
}
/* Unlink timer from the list.
*/
if (p_timer_listq->p_first == p_tle) {
p_timer_listq->p_first = p_tle->p_next;
if (p_timer_listq->p_first != NULL) p_timer_listq->p_first->p_prev = NULL;
if (p_timer_listq->p_last == p_tle) p_timer_listq->p_last = NULL;
} else {
if (p_timer_listq->p_last == p_tle) {
p_timer_listq->p_last = p_tle->p_prev;
if (p_timer_listq->p_last != NULL) p_timer_listq->p_last->p_next = NULL;
} else {
if (p_tle->p_next != NULL && p_tle->p_next->p_prev == p_tle)
p_tle->p_next->p_prev = p_tle->p_prev;
else {
/* Error case - chain messed up ?? */
return;
}
if (p_tle->p_prev != NULL && p_tle->p_prev->p_next == p_tle)
p_tle->p_prev->p_next = p_tle->p_next;
else {
/* Error case - chain messed up ?? */
return;
}
}
}
p_tle->p_next = p_tle->p_prev = NULL;
p_tle->ticks = GKI_UNUSED_LIST_ENTRY;
p_tle->in_use = false;
/* if timer queue is empty */
if (p_timer_listq->p_first == NULL && p_timer_listq->p_last == NULL) {
for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
if (gki_cb.com.timer_queues[tt] == p_timer_listq) {
gki_cb.com.timer_queues[tt] = NULL;
break;
}
}
}
return;
}
/*******************************************************************************
**
** Function gki_adjust_timer_count
**
** Description This function is called whenever a new timer or GKI_wait
*occurs
** to adjust (if necessary) the current time til the first
*expiration.
** This only needs to make an adjustment if the new timer (in
*ticks) is
** less than the number of ticks remaining on the current
*timer.
**
** Parameters: ticks - (input) number of system ticks of the new timer
*entry
**
** NOTE: This routine MUST be called while interrupts are
*disabled to
** avoid updates while adjusting the timer variables.
**
** Returns void
**
*******************************************************************************/
void gki_adjust_timer_count(int32_t ticks) {
if (ticks > 0) {
/* See if the new timer expires before the current first expiration */
if (gki_cb.com.OSNumOrigTicks == 0 ||
(ticks < gki_cb.com.OSTicksTilExp && gki_cb.com.OSTicksTilExp > 0)) {
gki_cb.com.OSNumOrigTicks =
(gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) + ticks;
gki_cb.com.OSTicksTilExp = ticks;
}
}
return;
}