15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2003-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Protocol timer services.
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_target.h"
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "gki.h"
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "ptim.h"
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bta_sys.h"
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         ptim_init
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Initialize a protocol timer control block.  Parameter
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  period is the GKI timer period in milliseconds.  Parameter
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  timer_id is the GKI timer id.
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid ptim_init(tPTIM_CB *p_cb, UINT16 period, UINT8 timer_id)
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    GKI_init_timer_list(&p_cb->timer_queue);
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_cb->period = period;
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_cb->timer_id = timer_id;
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         ptim_timer_update
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Update the protocol timer list and handle expired timers.
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  This function is called from the task running the protocol
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  timers when the periodic GKI timer expires.
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid ptim_timer_update(tPTIM_CB *p_cb)
605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    TIMER_LIST_ENT *p_tle;
625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    BT_HDR *p_msg;
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    UINT32 new_ticks_count;
645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    INT32  period_in_ticks;
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* To handle the case when the function is called less frequently than the period
675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project       we must convert determine the number of ticks since the last update, then
685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project       convert back to milliseconds before updating timer list */
695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    new_ticks_count = GKI_get_tick_count();
705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* Check for wrapped condition */
725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (new_ticks_count >= p_cb->last_gki_ticks)
735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        period_in_ticks = (INT32)(new_ticks_count - p_cb->last_gki_ticks);
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        period_in_ticks = (INT32)(((UINT32)0xffffffff - p_cb->last_gki_ticks)
795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                            + new_ticks_count + 1);
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* update timer list */
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    GKI_update_timer_list(&p_cb->timer_queue, GKI_TICKS_TO_MS(period_in_ticks));
845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_cb->last_gki_ticks = new_ticks_count;
865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* while there are expired timers */
885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    while((p_cb->timer_queue.p_first) && (p_cb->timer_queue.p_first->ticks <= 0))
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* removed expired timer from list */
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_tle = p_cb->timer_queue.p_first;
925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_remove_from_timer_list(&p_cb->timer_queue, p_tle);
935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* call timer callback */
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        if(p_tle->p_cback)
965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            (*p_tle->p_cback)(p_tle);
985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        else if(p_tle->event)
1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        {
1015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
1025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            {
1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_msg->event = p_tle->event;
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                p_msg->layer_specific = 0;
1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                bta_sys_sendmsg(p_msg);
1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
1085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* if timer list is empty stop periodic GKI timer */
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cb->timer_queue.p_first == NULL)
1125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_stop_timer(p_cb->timer_id);
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         ptim_start_timer
1205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Start a protocol timer for the specified amount
1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  of time in seconds.
1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid ptim_start_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout)
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* if timer list is currently empty, start periodic GKI timer */
1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cb->timer_queue.p_first == NULL)
1315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_cb->last_gki_ticks = GKI_get_tick_count();
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_start_timer(p_cb->timer_id, GKI_MS_TO_TICKS(p_cb->period), TRUE);
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    GKI_remove_from_timer_list(&p_cb->timer_queue, p_tle);
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_tle->event = type;
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_tle->ticks = timeout;
1405ec39bbc74875868ba54e837c6bd30bfa022563fChris Manton    p_tle->ticks_initial = timeout;
1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    GKI_add_to_timer_list(&p_cb->timer_queue, p_tle);
1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         ptim_stop_timer
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      Stop a protocol timer.
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void
1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project*******************************************************************************/
1545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectvoid ptim_stop_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle)
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle);
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    /* if timer list is empty stop periodic GKI timer */
1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if (p_cb->timer_queue.p_first == NULL)
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        GKI_stop_timer(p_cb->timer_id);
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
164