/*******************************************************************************
**
** Function         GKI_igetpoolbuf
**
** Description      Called by an interrupt service routine to get a free buffer from
**                  a specific buffer pool.
**
** Parameters       pool_id - (input) pool ID to get a buffer out of.
**
** Returns          A pointer to the buffer, or NULL if none available
**
*******************************************************************************/
void *GKI_igetpoolbuf (UINT8 pool_id)
{
    FREE_QUEUE_T  *Q;
    BUFFER_HDR_T  *p_hdr;

    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
        return (NULL);


    Q = &gki_cb.com.freeq[pool_id];
    if(Q->cur_cnt < Q->total)
    {
        p_hdr = Q->p_first;
        Q->p_first = p_hdr->p_next;

        if (!Q->p_first)
            Q->p_last = NULL;

        if(++Q->cur_cnt > Q->max_cnt)
            Q->max_cnt = Q->cur_cnt;

        p_hdr->task_id = GKI_get_taskid();

        p_hdr->status  = BUF_STATUS_UNLINKED;
        p_hdr->p_next  = NULL;
        p_hdr->Type    = 0;

        return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
    }

    return (NULL);
}
예제 #2
0
/*******************************************************************************
**
** 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 tnum)
{
    UINT8  task_id = GKI_get_taskid();

    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
    }
}
/*******************************************************************************
**
** Function         GKI_read_mbox
**
** Description      Called by applications to read a buffer from one of
**                  the task mailboxes.  A task can only read its own mailbox.
**
** Parameters:      mbox  - (input) mailbox ID to read (0, 1, 2, or 3)
**
** Returns          NULL if the mailbox was empty, else the address of a buffer
**
*******************************************************************************/
void *GKI_read_mbox (UINT8 mbox)
{
    UINT8           task_id = GKI_get_taskid();
    void            *p_buf = NULL;
    BUFFER_HDR_T    *p_hdr;

    if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX))
        return (NULL);

    GKI_disable();

    if (gki_cb.com.OSTaskQFirst[task_id][mbox])
    {
        p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox];
        gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next;

        p_hdr->p_next = NULL;
        p_hdr->status = BUF_STATUS_UNLINKED;

        p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE;
    }

    GKI_enable();

    return (p_buf);
}
/*******************************************************************************
**
** Function         nfc_hal_main_start_quick_timer
**
** Description      Start a timer for the specified amount of time.
**                  NOTE: The timeout resolution depends on including modules.
**                  QUICK_TIMER_TICKS_PER_SEC should be used to convert from
**                  time to ticks.
**
**
** Returns          void
**
*******************************************************************************/
void nfc_hal_main_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
{
    NFC_HDR *p_msg;

    /* if timer list is currently empty, start periodic GKI timer */
    if (nfc_hal_cb.quick_timer_queue.p_first == NULL)
    {
        /* if timer starts on other than NCIT task (script wrapper) */
        if(GKI_get_taskid () != NFC_HAL_TASK)
        {
            /* post event to start timer in NCIT task */
            if ((p_msg = (NFC_HDR *) GKI_getbuf (NFC_HDR_SIZE)) != NULL)
            {
                p_msg->event = NFC_HAL_EVT_TO_START_QUICK_TIMER;
                GKI_send_msg (NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg);
            }
        }
        else
        {
            GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE);
        }
    }

    GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle);

    p_tle->event = type;
    p_tle->ticks = timeout; /* Save the number of ticks for the timer */

    GKI_add_to_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle);
}
예제 #5
0
/*******************************************************************************
**
** Function         nfc_start_timer
**
** Description      Start a timer for the specified amount of time.
**                  NOTE: The timeout resolution is in SECONDS! (Even
**                          though the timer structure field is ticks)
**
** Returns          void
**
*******************************************************************************/
void nfc_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
{
    BT_HDR *p_msg;

    /* if timer list is currently empty, start periodic GKI timer */
    if (nfc_cb.timer_queue.p_first == NULL)
    {
        /* if timer starts on other than NFC task (scritp wrapper) */
        if (GKI_get_taskid () != NFC_TASK)
        {
            /* post event to start timer in NFC task */
            if ((p_msg = (BT_HDR *) GKI_getbuf (BT_HDR_SIZE)) != NULL)
            {
                p_msg->event = BT_EVT_TO_START_TIMER;
                GKI_send_msg (NFC_TASK, NFC_MBOX_ID, p_msg);
            }
        }
        else
        {
            /* Start nfc_task 1-sec resolution timer */
            GKI_start_timer (NFC_TIMER_ID, GKI_SECS_TO_TICKS (1), TRUE);
        }
    }

    GKI_remove_from_timer_list (&nfc_cb.timer_queue, p_tle);

    p_tle->event = type;
    p_tle->ticks = timeout;         /* Save the number of seconds for the timer */

    GKI_add_to_timer_list (&nfc_cb.timer_queue, p_tle);
}
void GKI_delay (UINT32 timeout)
{
    UINT8 rtask = GKI_get_taskid();
    struct timespec delay;
    int err;

    GKI_TRACE("GKI_delay %d %d", (int)rtask, (int)timeout);

    delay.tv_sec = timeout / 1000;
    delay.tv_nsec = 1000 * 1000 * (timeout%1000);

    /* [u]sleep can't be used because it uses SIGALRM */

    do {
        err = nanosleep(&delay, &delay);
    } while (err < 0 && errno ==EINTR);

    /* Check if task was killed while sleeping */

     /* NOTE : if you do not implement task killing, you do not need this check */

    if (rtask && gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD)
    {
    }

    GKI_TRACE("GKI_delay %d %d done", (int)rtask, (int)timeout);

    return;
}
예제 #7
0
/*******************************************************************************
**
** Function         btu_start_quick_timer
**
** Description      Start a timer for the specified amount of time.
**                  NOTE: The timeout resolution depends on including modules.
**                  QUICK_TIMER_TICKS_PER_SEC should be used to convert from
**                  time to ticks.
**
**
** Returns          void
**
*******************************************************************************/
void btu_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
{
    BT_HDR *p_msg;

    /* if timer list is currently empty, start periodic GKI timer */
    if (btu_cb.quick_timer_queue.p_first == NULL)
    {
        /* script test calls stack API without posting event */
        if (GKI_get_taskid() != BTU_TASK)
        {
            /* post event to start timer in BTU task */
            if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
            {
                p_msg->event = BT_EVT_TO_START_QUICK_TIMER;
                GKI_send_msg (BTU_TASK, TASK_MBOX_0, p_msg);
            }
        }
        else
            GKI_start_timer(TIMER_2, QUICK_TIMER_TICKS, TRUE);
    }

    GKI_remove_from_timer_list (&btu_cb.quick_timer_queue, p_tle);

    p_tle->event = type;
    p_tle->ticks = timeout; /* Save the number of ticks for the timer */

    GKI_add_to_timer_list (&btu_cb.quick_timer_queue, p_tle);
}
예제 #8
0
/*******************************************************************************
**
** Function         btu_start_timer
**
** Description      Start a timer for the specified amount of time.
**                  NOTE: The timeout resolution is in SECONDS! (Even
**                          though the timer structure field is ticks)
**
** Returns          void
**
*******************************************************************************/
void btu_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
{
    BT_HDR *p_msg;
    /* if timer list is currently empty, start periodic GKI timer */
    if (btu_cb.timer_queue.p_first == NULL)
    {
        /* if timer starts on other than BTU task */
        if (GKI_get_taskid() != BTU_TASK)
        {
            /* post event to start timer in BTU task */
            if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
            {
                p_msg->event = BT_EVT_TO_START_TIMER;
                GKI_send_msg (BTU_TASK, TASK_MBOX_0, p_msg);
            }
        }
        else
        {
            /* Start free running 1 second timer for list management */
            GKI_start_timer (TIMER_0, GKI_SECS_TO_TICKS (1), TRUE);
        }
    }

    GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle);

    p_tle->event = type;
    p_tle->ticks = timeout;         /* Save the number of seconds for the timer */

    GKI_add_to_timer_list (&btu_cb.timer_queue, p_tle);
}
예제 #9
0
/*******************************************************************************
**
** 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 tnum)
{
    UINT8  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 (defined(GKI_DELAY_STOP_SYS_TICK) && (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();


}
예제 #10
0
/*******************************************************************************
**
** Function         GKI_getpoolbuf
**
** Description      Called by an application to get a free buffer from
**                  a specific buffer pool.
**
**                  Note: If there are no more buffers available from the pool,
**                        the public buffers are searched for an available buffer.
**
** Parameters       pool_id - (input) pool ID to get a buffer out of.
**
** Returns          A pointer to the buffer, or NULL if none available
**
*******************************************************************************/
void *GKI_getpoolbuf (UINT8 pool_id)
{
    FREE_QUEUE_T  *Q;
    BUFFER_HDR_T  *p_hdr;
    tGKI_COM_CB *p_cb = &gki_cb.com;

    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
    {
        GKI_exception(GKI_ERROR_GETPOOLBUF_BAD_QID, "getpoolbuf bad pool");
        return (NULL);
    }

    /* Make sure the buffers aren't disturbed til finished with allocation */
    GKI_disable();

    Q = &p_cb->freeq[pool_id];
    if(Q->cur_cnt < Q->total)
    {
// btla-specific ++
#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
        if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE)
        {
            GKI_enable();
            return NULL;
        }
#endif
// btla-specific --
        p_hdr = Q->p_first;
        Q->p_first = p_hdr->p_next;

        if (!Q->p_first)
            Q->p_last = NULL;

        if(++Q->cur_cnt > Q->max_cnt)
            Q->max_cnt = Q->cur_cnt;

        GKI_enable();


        p_hdr->task_id = GKI_get_taskid();

        p_hdr->status  = BUF_STATUS_UNLINKED;
        p_hdr->p_next  = NULL;
        p_hdr->Type    = 0;

        return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
    }

    /* If here, no buffers in the specified pool */
    GKI_enable();

    /* try for free buffers in public pools */
    return (GKI_getbuf(p_cb->freeq[pool_id].size));

}
void GKI_exception (UINT16 code, char *msg)
{
    UINT8 task_id;
    int i = 0;
    FREE_QUEUE_T  *Q;
    tGKI_COM_CB *p_cb = &gki_cb.com;

    ALOGE( "GKI_exception(): Task State Table");

    for(task_id = 0; task_id < GKI_MAX_TASKS; task_id++)
    {
        ALOGE( "TASK ID [%d] task name [%s] state [%d]",
                         task_id,
                         gki_cb.com.OSTName[task_id],
                         gki_cb.com.OSRdyTbl[task_id]);
    }

    ALOGE("GKI_exception %d %s", code, msg);
    ALOGE( "********************************************************************");
    ALOGE( "* GKI_exception(): %d %s", code, msg);
    ALOGE( "********************************************************************");

#if 0//(GKI_DEBUG == TRUE)
    GKI_disable();

    if (gki_cb.com.ExceptionCnt < GKI_MAX_EXCEPTION)
    {
        EXCEPTION_T *pExp;

        pExp =  &gki_cb.com.Exception[gki_cb.com.ExceptionCnt++];
        pExp->type = code;
        pExp->taskid = GKI_get_taskid();
        strncpy((char *)pExp->msg, msg, GKI_MAX_EXCEPTION_MSGLEN - 1);
    }

    GKI_enable();
#endif
    if (code == GKI_ERROR_OUT_OF_BUFFERS)
    {
        for(i=0; i<p_cb->curr_total_no_of_pools; i++)
        {
            Q = &p_cb->freeq[p_cb->pool_list[i]];
            if (Q !=NULL)
                ALOGE("GKI_exception Buffer current cnt:%x, Total:%x", Q->cur_cnt, Q->total);
        }
    }

    GKI_TRACE("GKI_exception %d %s done", code, msg);
    return;
}
/*******************************************************************************
**
** Function         GKI_task_self_cleanup
**
** Description      This function is used in the case when the calling thread
**                  is exiting itself. The GKI_destroy_task function can not be
**                  used in this case due to the pthread_join call. The function
**                  cleans up GKI control block associated to the terminating
**                  thread.
**
** Parameters:      task_id     - (input) Task id is used for sanity check to
**                                 make sure the calling thread is in the right
**                                 context.
**
** Returns          None
**
*******************************************************************************/
void GKI_task_self_cleanup(UINT8 task_id)
{
    UINT8 my_task_id = GKI_get_taskid();

    if (task_id != my_task_id)
    {
        GKI_ERROR_LOG("%s: Wrong context - current task %d is not the given task id %d",\
                      __FUNCTION__, my_task_id, task_id);
        return;
    }

    if (gki_cb.com.OSRdyTbl[task_id] != TASK_DEAD)
    {
        /* paranoi settings, make sure that we do not execute any mailbox events */
        gki_cb.com.OSWaitEvt[task_id] &= ~(TASK_MBOX_0_EVT_MASK|TASK_MBOX_1_EVT_MASK|
                                            TASK_MBOX_2_EVT_MASK|TASK_MBOX_3_EVT_MASK);

#if (GKI_NUM_TIMERS > 0)
        gki_cb.com.OSTaskTmr0R[task_id] = 0;
        gki_cb.com.OSTaskTmr0 [task_id] = 0;
#endif

#if (GKI_NUM_TIMERS > 1)
        gki_cb.com.OSTaskTmr1R[task_id] = 0;
        gki_cb.com.OSTaskTmr1 [task_id] = 0;
#endif

#if (GKI_NUM_TIMERS > 2)
        gki_cb.com.OSTaskTmr2R[task_id] = 0;
        gki_cb.com.OSTaskTmr2 [task_id] = 0;
#endif

#if (GKI_NUM_TIMERS > 3)
        gki_cb.com.OSTaskTmr3R[task_id] = 0;
        gki_cb.com.OSTaskTmr3 [task_id] = 0;
#endif

        GKI_exit_task(task_id);

        /* Calling pthread_detach here to mark the thread as detached.
           Once the thread terminates, the system can reclaim its resources
           without waiting for another thread to join with.
        */
        pthread_detach(gki_cb.os.thread_id[task_id]);
    }
}
예제 #13
0
/*******************************************************************************
**
** Function:    NfcAdaptation::Thread()
**
** Description: Creates work threads
**
** Returns:     none
**
*******************************************************************************/
UINT32 NfcAdaptation::Thread (UINT32 arg)
{
    const char* func = "NfcAdaptation::Thread";
    ALOGD ("%s: enter", func);

    {
        ThreadCondVar    CondVar;
        AutoThreadMutex  guard(CondVar);
        GKI_create_task ((TASKPTR)nfc_task, NFC_TASK, (INT8*)"NFC_TASK", 0, 0, (pthread_cond_t*)CondVar, (pthread_mutex_t*)CondVar);
        CondVar.wait();
    }

    NfcAdaptation::GetInstance().signal();

    GKI_exit_task (GKI_get_taskid ());
    ALOGD ("%s: exit", func);
    return NULL;
}
INT8 *GKI_map_taskname (UINT8 task_id)
{
    GKI_TRACE("GKI_map_taskname %d", task_id);

    if (task_id < GKI_MAX_TASKS)
    {
        GKI_TRACE("GKI_map_taskname %d %s done", task_id, gki_cb.com.OSTName[task_id]);
         return (gki_cb.com.OSTName[task_id]);
    }
    else if (task_id == GKI_MAX_TASKS )
    {
        return (gki_cb.com.OSTName[GKI_get_taskid()]);
    }
    else
    {
        return (INT8*)"BAD";
    }
}
예제 #15
0
void GKI_exception (UINT16 code, char *msg)
{
    UINT8 task_id;
    int i = 0;

    GKI_TRACE_ERROR_0( "GKI_exception(): Task State Table");

    for(task_id = 0; task_id < GKI_MAX_TASKS; task_id++)
    {
        GKI_TRACE_ERROR_3( "TASK ID [%d] task name [%s] state [%d]",
                         task_id,
                         gki_cb.com.OSTName[task_id],
                         gki_cb.com.OSRdyTbl[task_id]);
    }

    GKI_TRACE_ERROR_2("GKI_exception %d %s", code, msg);
    GKI_TRACE_ERROR_0( "********************************************************************");
    GKI_TRACE_ERROR_2( "* GKI_exception(): %d %s", code, msg);
    GKI_TRACE_ERROR_0( "********************************************************************");

#if (GKI_DEBUG == TRUE)
    GKI_disable();

    if (gki_cb.com.ExceptionCnt < GKI_MAX_EXCEPTION)
    {
        EXCEPTION_T *pExp;

        pExp =  &gki_cb.com.Exception[gki_cb.com.ExceptionCnt++];
        pExp->type = code;
        pExp->taskid = GKI_get_taskid();
        strncpy((char *)pExp->msg, msg, GKI_MAX_EXCEPTION_MSGLEN - 1);
    }

    GKI_enable();
#endif

    GKI_TRACE_ERROR_2("GKI_exception %d %s done", code, msg);


    return;
}
/*******************************************************************************
**
** Function         GKI_getbuf
**
** Description      Called by an application to get a free buffer which
**                  is of size greater or equal to the requested size.
**
**                  Note: This routine only takes buffers from public pools.
**                        It will not use any buffers from pools
**                        marked GKI_RESTRICTED_POOL.
**
** Parameters       size - (input) number of bytes needed.
**
** Returns          A pointer to the buffer, or NULL if none available
**
*******************************************************************************/
void *GKI_getbuf (UINT16 size)
{
    UINT8         i;
    FREE_QUEUE_T  *Q;
    BUFFER_HDR_T  *p_hdr;
    tGKI_COM_CB *p_cb = &gki_cb.com;

    if (size == 0)
    {
        GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
        return (NULL);
    }

    /* Find the first buffer pool that is public that can hold the desired size */
    for (i=0; i < p_cb->curr_total_no_of_pools; i++)
    {
        if ( size <= p_cb->freeq[p_cb->pool_list[i]].size )
            break;
    }

    if(i == p_cb->curr_total_no_of_pools)
    {
        GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big");
        return (NULL);
    }

    /* Make sure the buffers aren't disturbed til finished with allocation */
    GKI_disable();

    /* search the public buffer pools that are big enough to hold the size
     * until a free buffer is found */
    for ( ; i < p_cb->curr_total_no_of_pools; i++)
    {
        /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
        if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask)
            continue;

        Q = &p_cb->freeq[p_cb->pool_list[i]];
        if(Q->cur_cnt < Q->total)
        {
// btla-specific ++
        #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
            if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE)
                return NULL;
        #endif
// btla-specific --
            p_hdr = Q->p_first;
            Q->p_first = p_hdr->p_next;

            if (!Q->p_first)
                Q->p_last = NULL;

            if(++Q->cur_cnt > Q->max_cnt)
                Q->max_cnt = Q->cur_cnt;

            GKI_enable();

            p_hdr->task_id = GKI_get_taskid();

            p_hdr->status  = BUF_STATUS_UNLINKED;
            p_hdr->p_next  = NULL;
            p_hdr->Type    = 0;

            return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
        }
    }

    GKI_enable();

    GKI_exception (GKI_ERROR_OUT_OF_BUFFERS, "getbuf: out of buffers");
    return (NULL);
}
예제 #17
0
/*******************************************************************************
**
** 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 tnum, INT32 ticks, BOOLEAN is_continuous)
{
    INT32   reload;
    INT32   orig_ticks;
    UINT8   task_id = GKI_get_taskid();
    BOOLEAN 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 (defined(GKI_DELAY_STOP_SYS_TICK) && (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 (defined(GKI_DELAY_STOP_SYS_TICK) && (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_wait
**
** Description      This function is called by tasks to wait for a specific
**                  event or set of events. The task may specify the duration
**                  that it wants to wait for, or 0 if infinite.
**
** Parameters:      flag -    (input) the event or set of events to wait for
**                  timeout - (input) the duration that the task wants to wait
**                                    for the specific events (in system ticks)
**
**
** Returns          the event mask of received events or zero if timeout
**
*******************************************************************************/
UINT16 GKI_wait (UINT16 flag, UINT32 timeout)
{
    UINT16 evt;
    UINT8 rtask;
    struct timespec abstime = { 0, 0 };

    int sec;
    int nano_sec;

    rtask = GKI_get_taskid();

    GKI_TRACE("GKI_wait %d %x %d", (int)rtask, (int)flag, (int)timeout);

    gki_cb.com.OSWaitForEvt[rtask] = flag;

    /* protect OSWaitEvt[rtask] from modification from an other thread */
    pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[rtask]);

    if (!(gki_cb.com.OSWaitEvt[rtask] & flag))
    {
        if (timeout)
        {
            clock_gettime(CLOCK_MONOTONIC, &abstime);

            /* add timeout */
            sec = timeout / 1000;
            nano_sec = (timeout % 1000) * NANOSEC_PER_MILLISEC;
            abstime.tv_nsec += nano_sec;
            if (abstime.tv_nsec > NSEC_PER_SEC)
            {
                abstime.tv_sec += (abstime.tv_nsec / NSEC_PER_SEC);
                abstime.tv_nsec = abstime.tv_nsec % NSEC_PER_SEC;
            }
            abstime.tv_sec += sec;

            pthread_cond_timedwait_monotonic(&gki_cb.os.thread_evt_cond[rtask],
                    &gki_cb.os.thread_evt_mutex[rtask], &abstime);

        }
        else
        {
            pthread_cond_wait(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask]);
        }

        /* TODO: check, this is probably neither not needed depending on phtread_cond_wait() implmentation,
         e.g. it looks like it is implemented as a counter in which case multiple cond_signal
         should NOT be lost! */

        /* we are waking up after waiting for some events, so refresh variables
           no need to call GKI_disable() here as we know that we will have some events as we've been waking
           up after condition pending or timeout */

        if (gki_cb.com.OSTaskQFirst[rtask][0])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK;
        if (gki_cb.com.OSTaskQFirst[rtask][1])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK;
        if (gki_cb.com.OSTaskQFirst[rtask][2])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK;
        if (gki_cb.com.OSTaskQFirst[rtask][3])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK;

        if (gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD)
        {
            gki_cb.com.OSWaitEvt[rtask] = 0;
            /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock when cond is met */
            pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]);
            return (EVENT_MASK(GKI_SHUTDOWN_EVT));
        }
    }

    /* Clear the wait for event mask */
    gki_cb.com.OSWaitForEvt[rtask] = 0;

    /* Return only those bits which user wants... */
    evt = gki_cb.com.OSWaitEvt[rtask] & flag;

    /* Clear only those bits which user wants... */
    gki_cb.com.OSWaitEvt[rtask] &= ~flag;

    /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock mutex when cond is met */
    pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]);

    GKI_TRACE("GKI_wait %d %x %d %x done", (int)rtask, (int)flag, (int)timeout, (int)evt);
    return (evt);
}
예제 #19
0
void *GKI_getbuf (UINT16 size)
#endif
{
    UINT8         i;
    FREE_QUEUE_T  *Q;
    BUFFER_HDR_T  *p_hdr;
    tGKI_COM_CB *p_cb = &gki_cb.com;
#if GKI_BUFFER_DEBUG
    UINT8         x;
#endif

    if (size == 0)
    {
        GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
        return (NULL);
    }

#if GKI_BUFFER_DEBUG
    LOGD("GKI_getbuf() requesting %d func:%s(line=%d)", size, _function_, _line_);
#endif
    /* Find the first buffer pool that is public that can hold the desired size */
    for (i=0; i < p_cb->curr_total_no_of_pools; i++)
    {
        if ( size <= p_cb->freeq[p_cb->pool_list[i]].size )
            break;
    }

    if(i == p_cb->curr_total_no_of_pools)
    {
        GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big");
        return (NULL);
    }

    /* Make sure the buffers aren't disturbed til finished with allocation */
    GKI_disable();

    /* search the public buffer pools that are big enough to hold the size
     * until a free buffer is found */
    for ( ; i < p_cb->curr_total_no_of_pools; i++)
    {
        /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
        if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask)
            continue;

        Q = &p_cb->freeq[p_cb->pool_list[i]];
        if(Q->cur_cnt < Q->total)
        {
        #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
            if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE)
            {
                GKI_TRACE_ERROR_0("GKI_getbuf() out of buffer");
                GKI_enable();
                return NULL;
            }
        #endif

            if(Q->p_first == 0)
            {
                /* gki_alloc_free_queue() failed to alloc memory */
                GKI_TRACE_ERROR_0("GKI_getbuf() fail alloc free queue");
                GKI_enable();
                return NULL;
            }

            p_hdr = Q->p_first;
            Q->p_first = p_hdr->p_next;

            if (!Q->p_first)
                Q->p_last = NULL;

            if(++Q->cur_cnt > Q->max_cnt)
                Q->max_cnt = Q->cur_cnt;

            GKI_enable();

            p_hdr->task_id = GKI_get_taskid();

            p_hdr->status  = BUF_STATUS_UNLINKED;
            p_hdr->p_next  = NULL;
            p_hdr->Type    = 0;
#if GKI_BUFFER_DEBUG
            LOGD("GKI_getbuf() allocated, %x, %x (%d of %d used) %d", (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, Q->cur_cnt, Q->total, p_cb->freeq[i].total);

            strncpy(p_hdr->_function, _function_, _GKI_MAX_FUNCTION_NAME_LEN);
            p_hdr->_function[_GKI_MAX_FUNCTION_NAME_LEN] = '\0';
            p_hdr->_line = _line_;
#endif
            return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
        }
    }

    GKI_TRACE_ERROR_0("GKI_getbuf() unable to allocate buffer!!!!!");
#if GKI_BUFFER_DEBUG
    LOGD("GKI_getbuf() unable to allocate buffer!!!!!");
    LOGD("******************** GKI Memory Pool Dump ********************");

    p_cb = &gki_cb.com;

    LOGD("Dumping total of %d buffer pools", p_cb->curr_total_no_of_pools);

    for (i=0 ; i < p_cb->curr_total_no_of_pools; i++)
    {
        p_hdr = (BUFFER_HDR_T *)p_cb->pool_start[i];

        LOGD("pool %d has a total of %d buffers (start=%p)", i, p_cb->freeq[i].total, p_hdr);

        for (x=0; p_hdr && x < p_cb->freeq[i].total; x++)
        {
            if (p_hdr->status != BUF_STATUS_FREE)
            {
                LOGD("pool:%d, buf[%d]:%x, hdr:%x status=%d func:%s(line=%d)", i, x, (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, p_hdr->status, p_hdr->_function, p_hdr->_line);
            }

            p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_hdr + p_cb->pool_size[i]);
        }
    }
    LOGD("**************************************************************");
#endif

    GKI_TRACE_ERROR_0("Failed to allocate GKI buffer");

    GKI_enable();

    return (NULL);
}
예제 #20
0
void *GKI_getpoolbuf (UINT8 pool_id)
#endif
{
    FREE_QUEUE_T  *Q;
    BUFFER_HDR_T  *p_hdr;
    tGKI_COM_CB *p_cb = &gki_cb.com;

    if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
        return (NULL);

#if GKI_BUFFER_DEBUG
    LOGD("GKI_getpoolbuf() requesting from %d func:%s(line=%d)", pool_id, _function_, _line_);
#endif
    /* Make sure the buffers aren't disturbed til finished with allocation */
    GKI_disable();

    Q = &p_cb->freeq[pool_id];
    if(Q->cur_cnt < Q->total)
    {
#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
        if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE)
            return NULL;
#endif

        if(Q->p_first == 0)
        {
            /* gki_alloc_free_queue() failed to alloc memory */
            GKI_TRACE_ERROR_0("GKI_getpoolbuf() fail alloc free queue");
            return NULL;
        }

        p_hdr = Q->p_first;
        Q->p_first = p_hdr->p_next;

        if (!Q->p_first)
            Q->p_last = NULL;

        if(++Q->cur_cnt > Q->max_cnt)
            Q->max_cnt = Q->cur_cnt;

        GKI_enable();


        p_hdr->task_id = GKI_get_taskid();

        p_hdr->status  = BUF_STATUS_UNLINKED;
        p_hdr->p_next  = NULL;
        p_hdr->Type    = 0;

#if GKI_BUFFER_DEBUG
        LOGD("GKI_getpoolbuf() allocated, %x, %x (%d of %d used) %d", (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, Q->cur_cnt, Q->total, p_cb->freeq[pool_id].total);

        strncpy(p_hdr->_function, _function_, _GKI_MAX_FUNCTION_NAME_LEN);
        p_hdr->_function[_GKI_MAX_FUNCTION_NAME_LEN] = '\0';
        p_hdr->_line = _line_;
#endif
        return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
    }

    /* If here, no buffers in the specified pool */
    GKI_enable();

#if GKI_BUFFER_DEBUG
    /* try for free buffers in public pools */
    return (GKI_getbuf_debug(p_cb->freeq[pool_id].size, _function_, _line_));
#else
    /* try for free buffers in public pools */
    return (GKI_getbuf(p_cb->freeq[pool_id].size));
#endif
}
예제 #21
0
/*******************************************************************************
**
** Function         nfc_task
**
** Description      NFC event processing task
**
** Returns          nothing
**
*******************************************************************************/
UINT32 nfc_task (UINT32 param)
{
    UINT16  event;
    BT_HDR  *p_msg;
    BOOLEAN free_buf;

    /* Initialize the nfc control block */
    memset (&nfc_cb, 0, sizeof (tNFC_CB));
    nfc_cb.trace_level = NFC_INITIAL_TRACE_LEVEL;

    NFC_TRACE_DEBUG0 ("NFC_TASK started.");

    /* main loop */
    while (TRUE)
    {
        event = GKI_wait (0xFFFF, 0);

        /* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */
        if (event & NFC_TASK_EVT_TRANSPORT_READY)
        {
            NFC_TRACE_DEBUG0 ("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY.");

            /* Reset the NFC controller. */
            nfc_set_state (NFC_STATE_CORE_INIT);
            nci_snd_core_reset (NCI_RESET_TYPE_RESET_CFG);
        }

        if (event & NFC_MBOX_EVT_MASK)
        {
            /* Process all incoming NCI messages */
            while ((p_msg = (BT_HDR *) GKI_read_mbox (NFC_MBOX_ID)) != NULL)
            {
                free_buf = TRUE;

                /* Determine the input message type. */
                switch (p_msg->event & BT_EVT_MASK)
                {
                    case BT_EVT_TO_NFC_NCI:
                        free_buf = nfc_ncif_process_event (p_msg);
                        break;

                    case BT_EVT_TO_START_TIMER :
                        /* Start nfc_task 1-sec resolution timer */
                        GKI_start_timer (NFC_TIMER_ID, GKI_SECS_TO_TICKS (1), TRUE);
                        break;

                    case BT_EVT_TO_START_QUICK_TIMER :
                        /* Quick-timer is required for LLCP */
                        GKI_start_timer (NFC_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE);
                        break;

                    case BT_EVT_TO_NFC_MSGS:
                        nfc_main_handle_hal_evt ((tNFC_HAL_EVT_MSG*)p_msg);
                        break;

                    default:
                        NFC_TRACE_DEBUG1 ("nfc_task: unhandle mbox message, event=%04x", p_msg->event);
                        break;
                }

                if (free_buf)
                {
                    GKI_freebuf (p_msg);
                }
            }
        }

        /* Process gki timer tick */
        if (event & NFC_TIMER_EVT_MASK)
        {
            nfc_process_timer_evt ();
        }

        /* Process quick timer tick */
        if (event & NFC_QUICK_TIMER_EVT_MASK)
        {
            nfc_process_quick_timer_evt ();
        }

#if (defined (NFA_INCLUDED) && NFA_INCLUDED == TRUE)
        if (event & NFA_MBOX_EVT_MASK)
        {
            while ((p_msg = (BT_HDR *) GKI_read_mbox (NFA_MBOX_ID)) != NULL)
            {
                nfa_sys_event (p_msg);
            }
        }

        if (event & NFA_TIMER_EVT_MASK)
        {
            nfa_sys_timer_update ();
        }
#endif

    }


    NFC_TRACE_DEBUG0 ("nfc_task terminated");

    GKI_exit_task (GKI_get_taskid ());
    return 0;
}
/*******************************************************************************
**
** Function         nfc_hal_main_task
**
** Description      NFC HAL NCI transport event processing task
**
** Returns          0
**
*******************************************************************************/
UINT32 nfc_hal_main_task (UINT32 param)
{
    UINT16   event;
    UINT8    byte;
    UINT8    num_interfaces;
    UINT8    *p;
    NFC_HDR  *p_msg;
    BOOLEAN  free_msg;

    HAL_TRACE_DEBUG0 ("NFC_HAL_TASK started");

    /* Main loop */
    while (TRUE)
    {
        event = GKI_wait (0xFFFF, 0);

        /* Handle NFC_HAL_TASK_EVT_INITIALIZE (for initializing NCI transport) */
        if (event & NFC_HAL_TASK_EVT_INITIALIZE)
        {
            HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_INITIALIZE signal. Opening NFC transport...");

            nfc_hal_main_open_transport ();
        }

        /* Check for terminate event */
        if (event & NFC_HAL_TASK_EVT_TERMINATE)
        {
            HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_TERMINATE");
            nfc_hal_main_handle_terminate ();

            /* Close uart */
            USERIAL_Close (USERIAL_NFC_PORT);

            if (nfc_hal_cb.p_stack_cback)
            {
                nfc_hal_cb.p_stack_cback (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK);
                nfc_hal_cb.p_stack_cback = NULL;
            }
            continue;
        }

        /* Check for power cycle event */
        if (event & NFC_HAL_TASK_EVT_POWER_CYCLE)
        {
            HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_POWER_CYCLE");
            nfc_hal_main_handle_terminate ();

            /* Close uart */
            USERIAL_Close (USERIAL_NFC_PORT);

            /* power cycle timeout */
            nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_POWER_CYCLE,
                                            (NFC_HAL_POWER_CYCLE_DELAY*QUICK_TIMER_TICKS_PER_SEC)/1000);
            continue;
        }

        /* NCI message ready to be sent to NFCC */
        if (event & NFC_HAL_TASK_EVT_MBOX)
        {
            while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL)
            {
                free_msg = TRUE;
                switch (p_msg->event & NFC_EVT_MASK)
                {
                case NFC_HAL_EVT_TO_NFC_NCI:
                    nfc_hal_main_send_message (p_msg);
                    /* do not free buffer. NCI VS code may keep it for processing later */
                    free_msg = FALSE;
                    break;

                case NFC_HAL_EVT_POST_CORE_RESET:
                    NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_POST_INIT_DONE);

                    /* set NCI Control packet size from CORE_INIT_RSP */
                    p = (UINT8 *) (p_msg + 1) + p_msg->offset + NCI_MSG_HDR_SIZE;
                    p += 5;
                    STREAM_TO_UINT8 (num_interfaces, p);
                    p += (num_interfaces + 3);
                    nfc_hal_cb.ncit_cb.nci_ctrl_size = *p;

                    /* start post initialization */
                    nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_LPTD;
                    nfc_hal_cb.dev_cb.next_startup_vsc = 1;

                    nfc_hal_dm_config_nfcc ();
                    break;

                case NFC_HAL_EVT_TO_START_QUICK_TIMER:
                    GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE);
                    break;

                case NFC_HAL_EVT_HCI:
                    nfc_hal_hci_evt_hdlr ((tNFC_HAL_HCI_EVENT_DATA *) p_msg);
                    break;

                case NFC_HAL_EVT_PRE_DISCOVER:
                    NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE);
                    nfa_hal_send_pre_discover_cfg ();
                    break;

                case NFC_HAL_EVT_CONTROL_GRANTED:
                    nfc_hal_dm_send_pend_cmd ();
                    break;

                default:
                    break;
                }

                if (free_msg)
                    GKI_freebuf (p_msg);
            }
        }

        /* Data waiting to be read from serial port */
        if (event & NFC_HAL_TASK_EVT_DATA_RDY)
        {
            while (TRUE)
            {
                /* Read one byte to see if there is anything waiting to be read */
                if (USERIAL_Read (USERIAL_NFC_PORT, &byte, 1) == 0)
                {
                    break;
                }

                if (nfc_hal_nci_receive_msg (byte))
                {
                    /* complete of receiving NCI message */
                    nfc_hal_nci_assemble_nci_msg ();
                    if (nfc_hal_cb.ncit_cb.p_rcv_msg)
                    {
                        if (nfc_hal_nci_preproc_rx_nci_msg (nfc_hal_cb.ncit_cb.p_rcv_msg))
                        {
                            /* Send NCI message to the stack */
                            nfc_hal_send_nci_msg_to_nfc_task (nfc_hal_cb.ncit_cb.p_rcv_msg);
                        }
                        else
                        {
                            if (nfc_hal_cb.ncit_cb.p_rcv_msg)
                                GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg);
                        }
                        nfc_hal_cb.ncit_cb.p_rcv_msg = NULL;
                    }
                }
            } /* while (TRUE) */
        }

        /* Process quick timer tick */
        if (event & NFC_HAL_QUICK_TIMER_EVT_MASK)
        {
            nfc_hal_main_process_quick_timer_evt ();
        }
    }

    HAL_TRACE_DEBUG0 ("nfc_hal_main_task terminated");

    GKI_exit_task (GKI_get_taskid ());
    return 0;
}
예제 #23
0
/*******************************************************************************
**
** Function         GKI_wait
**
** Description      This function is called by tasks to wait for a specific
**                  event or set of events. The task may specify the duration
**                  that it wants to wait for, or 0 if infinite.
**
** Parameters:      flag -    (input) the event or set of events to wait for
**                  timeout - (input) the duration that the task wants to wait
**                                    for the specific events (in system ticks)
**
**
** Returns          the event mask of received events or zero if timeout
**
*******************************************************************************/
UINT16 GKI_wait (UINT16 flag, UINT32 timeout)
{
    UINT16 evt;
    UINT8 rtask;
    struct timespec abstime = { 0, 0 };
    int sec;
    int nano_sec;

    rtask = GKI_get_taskid();
    GKI_TRACE_3("GKI_wait %d %x %d", rtask, flag, timeout);
    if (rtask >= GKI_MAX_TASKS) {
        pthread_exit(NULL);
        return 0;
    }

    gki_pthread_info_t* p_pthread_info = &gki_pthread_info[rtask];
    if (p_pthread_info->pCond != NULL && p_pthread_info->pMutex != NULL) {
        int ret;
        GKI_TRACE_3("GKI_wait task=%i, pCond/pMutex = %x/%x", rtask, p_pthread_info->pCond, p_pthread_info->pMutex);
        ret = pthread_mutex_lock(p_pthread_info->pMutex);
        ret = pthread_cond_signal(p_pthread_info->pCond);
        ret = pthread_mutex_unlock(p_pthread_info->pMutex);
        p_pthread_info->pMutex = NULL;
        p_pthread_info->pCond = NULL;
    }
    gki_cb.com.OSWaitForEvt[rtask] = flag;

    /* protect OSWaitEvt[rtask] from modification from an other thread */
    pthread_mutex_lock(&gki_cb.os.thread_evt_mutex[rtask]);

#if 0 /* for clean scheduling we probably should always call pthread_cond_wait() */
    /* Check if anything in any of the mailboxes. There is a potential race condition where OSTaskQFirst[rtask]
     has been modified. however this should only result in addtional call to  pthread_cond_wait() but as
     the cond is met, it will exit immediately (depending on schedulling) */
    if (gki_cb.com.OSTaskQFirst[rtask][0])
    gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK;
    if (gki_cb.com.OSTaskQFirst[rtask][1])
    gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK;
    if (gki_cb.com.OSTaskQFirst[rtask][2])
    gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK;
    if (gki_cb.com.OSTaskQFirst[rtask][3])
    gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK;
#endif

    if (!(gki_cb.com.OSWaitEvt[rtask] & flag))
    {
        if (timeout)
        {
            //            timeout = GKI_MS_TO_TICKS(timeout);     /* convert from milliseconds to ticks */

            /* get current system time */
            //            clock_gettime(CLOCK_MONOTONIC, &currSysTime);
            //            abstime.tv_sec = currSysTime.time;
            //            abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
            clock_gettime(CLOCK_MONOTONIC, &abstime);

            /* add timeout */
            sec = timeout / 1000;
            nano_sec = (timeout % 1000) * NANOSEC_PER_MILLISEC;
            abstime.tv_nsec += nano_sec;
            if (abstime.tv_nsec > NSEC_PER_SEC)
            {
                abstime.tv_sec += (abstime.tv_nsec / NSEC_PER_SEC);
                abstime.tv_nsec = abstime.tv_nsec % NSEC_PER_SEC;
            }
            abstime.tv_sec += sec;

            pthread_cond_timedwait_monotonic(&gki_cb.os.thread_evt_cond[rtask],
                    &gki_cb.os.thread_evt_mutex[rtask], &abstime);

        }
        else
        {
            pthread_cond_wait(&gki_cb.os.thread_evt_cond[rtask], &gki_cb.os.thread_evt_mutex[rtask]);
        }

        /* TODO: check, this is probably neither not needed depending on phtread_cond_wait() implmentation,
         e.g. it looks like it is implemented as a counter in which case multiple cond_signal
         should NOT be lost! */
        // we are waking up after waiting for some events, so refresh variables
        // no need to call GKI_disable() here as we know that we will have some events as we've been waking up after condition pending or timeout
        if (gki_cb.com.OSTaskQFirst[rtask][0])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_0_EVT_MASK;
        if (gki_cb.com.OSTaskQFirst[rtask][1])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_1_EVT_MASK;
        if (gki_cb.com.OSTaskQFirst[rtask][2])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_2_EVT_MASK;
        if (gki_cb.com.OSTaskQFirst[rtask][3])
            gki_cb.com.OSWaitEvt[rtask] |= TASK_MBOX_3_EVT_MASK;

        if (gki_cb.com.OSRdyTbl[rtask] == TASK_DEAD)
        {
            gki_cb.com.OSWaitEvt[rtask] = 0;
            /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock when cond is met */
            pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]);
            BT_TRACE_1( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, "GKI TASK_DEAD received. exit thread %d...", rtask );

            gki_cb.os.thread_id[rtask] = 0;
            pthread_exit(NULL);
            return (EVENT_MASK(GKI_SHUTDOWN_EVT));
        }
    }

    /* Clear the wait for event mask */
    gki_cb.com.OSWaitForEvt[rtask] = 0;

    /* Return only those bits which user wants... */
    evt = gki_cb.com.OSWaitEvt[rtask] & flag;

    /* Clear only those bits which user wants... */
    gki_cb.com.OSWaitEvt[rtask] &= ~flag;

    /* unlock thread_evt_mutex as pthread_cond_wait() does auto lock mutex when cond is met */
    pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]);
    GKI_TRACE_4("GKI_wait %d %x %d %x resumed", rtask, flag, timeout, evt);

    return (evt);
}
예제 #24
0
/*******************************************************************************
**
** 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 tnum, INT32 ticks, BOOLEAN is_continuous)
{
    INT32   reload;
    INT32   orig_ticks;
    UINT8   task_id = GKI_get_taskid();
    BOOLEAN 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();

    /* 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 (INT32_MAX - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) > ticks)
    {
        ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp;
    }
    else
        ticks = INT32_MAX;

    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();

}