/*******************************************************************************
**
** Function         nfa_hciu_find_active_pipe_on_gate
**
** Description      Find the first active pipe associated with the given gate
**
** Returns          pointer to pipe, or NULL if none found
**
*******************************************************************************/
tNFA_HCI_DYN_PIPE *nfa_hciu_find_active_pipe_on_gate (UINT8 gate_id)
{
    tNFA_HCI_DYN_GATE   *pg;
    tNFA_HCI_DYN_PIPE   *pp;
    int                 xx;

    NFA_TRACE_DEBUG1 ("nfa_hciu_find_active_pipe_on_gate () Gate:0x%x", gate_id);

    /* Loop through all pipes looking for the owner */
    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
    {
        if (  (pp->pipe_id != 0)
            &&(pp->pipe_id >= NFA_HCI_FIRST_DYNAMIC_PIPE)
            &&(pp->pipe_id <= NFA_HCI_LAST_DYNAMIC_PIPE)
            &&(nfa_hciu_is_active_host (pp->dest_host))  )
        {
            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
                &&(pg->gate_id == gate_id) )
                return (pp);
        }
    }

    /* If here, not found */
    return (NULL);
}
/*******************************************************************************
**
** Function         nfa_hciu_add_pipe_to_gate
**
** Description      Add pipe to generic gate
**
** Returns          NFA_STATUS_OK, if successfully add the pipe on to the gate
**                  NFA_HCI_ADM_E_NO_PIPES_AVAILABLE, otherwise
**
*******************************************************************************/
tNFA_HCI_RESPONSE nfa_hciu_add_pipe_to_gate (UINT8 pipe_id,   UINT8 local_gate,
                                             UINT8 dest_host, UINT8 dest_gate)
{
    tNFA_HCI_DYN_GATE   *p_gate;
    tNFA_HCI_DYN_PIPE   *p_pipe;
    UINT8               pipe_index;

    p_gate = nfa_hciu_find_gate_by_gid (local_gate);

    if (p_gate != NULL)
    {
        /* Allocate a pipe control block */
        if ((p_pipe = nfa_hciu_alloc_pipe (pipe_id)) != NULL)
        {
            p_pipe->pipe_id     = pipe_id;
            p_pipe->pipe_state  = NFA_HCI_PIPE_CLOSED;
            p_pipe->dest_host   = dest_host;
            p_pipe->dest_gate   = dest_gate;
            p_pipe->local_gate  = local_gate;

            /* Save the pipe in the gate that it belongs to */
            pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes);
            p_gate->pipe_inx_mask |= (UINT32) (1 << pipe_index);

            NFA_TRACE_DEBUG4 ("nfa_hciu_add_pipe_to_gate  Gate ID: 0x%02x  Pipe ID: 0x%02x  pipe_index: %u  App Handle: 0x%08x",
                              local_gate, pipe_id, pipe_index, p_gate->gate_owner);
            return (NFA_HCI_ANY_OK);
        }
    }

    NFA_TRACE_DEBUG1 ("nfa_hciu_add_pipe_to_gate: 0x%02x  NOT FOUND", local_gate);

    return (NFA_HCI_ADM_E_NO_PIPES_AVAILABLE);
}
/*******************************************************************************
**
** Function         nfa_hciu_alloc_pipe
**
** Description      Allocate a pipe control block
**
** Returns          pointer to the pipe control block, or NULL if
**                  cannot allocate
**
*******************************************************************************/
tNFA_HCI_DYN_PIPE *nfa_hciu_alloc_pipe (UINT8 pipe_id)
{
    UINT8               xx;
    tNFA_HCI_DYN_PIPE   *pp;

    /* If we already have a pipe of the same ID, release it first it */
    if ((pp = nfa_hciu_find_pipe_by_pid (pipe_id)) != NULL)
    {
        if (pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE)
            return pp;
        nfa_hciu_release_pipe (pipe_id);
    }

    /* Look for a free pipe control block */
    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes ; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
    {
        if (pp->pipe_id == 0)
        {
            NFA_TRACE_DEBUG2 ("nfa_hciu_alloc_pipe:%d, index:%d", pipe_id, xx);
            pp->pipe_id = pipe_id;

            nfa_hci_cb.nv_write_needed = TRUE;
            return (pp);
        }
    }

    NFA_TRACE_DEBUG1 ("nfa_hciu_alloc_pipe:%d, NO free entries !!", pipe_id);
    return (NULL);
}
示例#4
0
/*******************************************************************************
**
** Function         nfa_sys_ptim_timer_update
**
** Description      Update the protocol timer list and handle expired timers.
**                  This function is called from the task running the protocol
**                  timers when the periodic GKI timer expires.
**
** Returns          void
**
*******************************************************************************/
void nfa_sys_ptim_timer_update (tPTIM_CB *p_cb)
{
    TIMER_LIST_ENT *p_tle;
    BT_HDR *p_msg;
    UINT32 new_ticks_count;
    INT32  period_in_ticks;

    /* To handle the case when the function is called less frequently than the period
       we must convert determine the number of ticks since the last update, then
       convert back to milliseconds before updating timer list */
    new_ticks_count = GKI_get_tick_count ();

    /* Check for wrapped condition */
    if (new_ticks_count >= p_cb->last_gki_ticks)
    {
        period_in_ticks = (INT32) (new_ticks_count - p_cb->last_gki_ticks);
    }
    else
    {
        period_in_ticks = (INT32) (((UINT32) 0xffffffff - p_cb->last_gki_ticks)
                            + new_ticks_count + 1);
    }

    /* update timer list */
    GKI_update_timer_list (&p_cb->timer_queue, GKI_TICKS_TO_MS (period_in_ticks));

    p_cb->last_gki_ticks = new_ticks_count;

    /* while there are expired timers */
    while ((p_cb->timer_queue.p_first) && (p_cb->timer_queue.p_first->ticks <= 0))
    {
        /* removed expired timer from list */
        p_tle = p_cb->timer_queue.p_first;
        NFA_TRACE_DEBUG1 ("nfa_sys_ptim_timer_update expired: %08x", p_tle);
        GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle);

        /* call timer callback */
        if (p_tle->p_cback)
        {
            (*p_tle->p_cback) (p_tle);
        }
        else if (p_tle->event)
        {
            if ((p_msg = (BT_HDR *) GKI_getbuf (sizeof (BT_HDR))) != NULL)
            {
                p_msg->event = p_tle->event;
                p_msg->layer_specific = 0;
                nfa_sys_sendmsg (p_msg);
            }
        }
    }

    /* if timer list is empty stop periodic GKI timer */
    if (p_cb->timer_queue.p_first == NULL)
    {
        NFA_TRACE_DEBUG0 ("ptim timer stop");
        GKI_stop_timer (p_cb->timer_id);
    }
}
/*******************************************************************************
**
** Function         nfa_hciu_send_delete_pipe_cmd
**
** Description      Delete the dynamic pipe
**
** Returns          None
**
*******************************************************************************/
tNFA_STATUS nfa_hciu_send_delete_pipe_cmd (UINT8 pipe)
{
    tNFA_STATUS status;

    NFA_TRACE_DEBUG1 ("nfa_hciu_send_delete_pipe_cmd: %d", pipe);

    if (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)
    {
        NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe);
        return (NFA_HCI_ANY_E_NOK);
    }
    nfa_hci_cb.pipe_in_use = pipe;

    status = nfa_hciu_send_msg (NFA_HCI_ADMIN_PIPE, NFA_HCI_COMMAND_TYPE, NFA_HCI_ADM_DELETE_PIPE, 1, &pipe);

    return status;
}
示例#6
0
/*******************************************************************************
**
** Function         nfa_dm_is_active
**
** Description      check if all modules of NFA is done with enable process and
**                  NFA is not restoring NFCC.
**
** Returns          TRUE, if NFA_DM_ENABLE_EVT is reported and it is not restoring NFCC
**
*******************************************************************************/
BOOLEAN nfa_dm_is_active (void)
{
    NFA_TRACE_DEBUG1 ("nfa_dm_is_active () flags:0x%x", nfa_dm_cb.flags);
    if (  (nfa_dm_cb.flags  & NFA_DM_FLAGS_DM_IS_ACTIVE)
            &&((nfa_dm_cb.flags & (NFA_DM_FLAGS_ENABLE_EVT_PEND | NFA_DM_FLAGS_NFCC_IS_RESTORING | NFA_DM_FLAGS_POWER_OFF_SLEEP)) == 0)  )
    {
        return TRUE;
    }
    else
        return FALSE;
}
/*******************************************************************************
**
** Function         nfa_ee_proc_nfcc_power_mode
**
** Description      Restore NFA EE sub-module
**
** Returns          None
**
*******************************************************************************/
void nfa_ee_proc_nfcc_power_mode (UINT8 nfcc_power_mode)
{
    UINT32          xx;
    tNFA_EE_ECB     *p_cb;
    BOOLEAN         proc_complete = TRUE;

    NFA_TRACE_DEBUG1 ("nfa_ee_proc_nfcc_power_mode (): nfcc_power_mode=%d", nfcc_power_mode);
    /* if NFCC power state is change to full power */
    if (nfcc_power_mode == NFA_DM_PWR_MODE_FULL)
    {
        if (nfa_ee_max_ee_cfg)
        {
            p_cb = nfa_ee_cb.ecb;
            for (xx = 0; xx < NFA_EE_MAX_EE_SUPPORTED; xx++, p_cb++)
            {
                p_cb->ee_old_status = 0;
                if (xx >= nfa_ee_cb.cur_ee)
                    p_cb->nfcee_id = NFA_EE_INVALID;

                if ((p_cb->nfcee_id != NFA_EE_INVALID) && (p_cb->ee_interface[0] != NFC_NFCEE_INTERFACE_HCI_ACCESS) && (p_cb->ee_status  != NFA_EE_STATUS_REMOVED))
                {
                    proc_complete       = FALSE;
                    /* NFA_EE_STATUS_RESTORING bit makes sure the ee_status restore to ee_old_status
                     * NFA_EE_STATUS_RESTORING bit is cleared in ee_status at NFCEE_DISCOVER NTF.
                     * NFA_EE_STATUS_RESTORING bit is cleared in ee_old_status at restoring the activate/inactive status after NFCEE_DISCOVER NTF */
                    p_cb->ee_status    |= NFA_EE_STATUS_RESTORING;
                    p_cb->ee_old_status = p_cb->ee_status;
                    /* NFA_EE_FLAGS_RESTORE bit makes sure the routing/nci logical connection is restore to prior to entering low power mode */
                    p_cb->ecb_flags    |= NFA_EE_ECB_FLAGS_RESTORE;
                }
            }
            nfa_ee_cb.em_state          = NFA_EE_EM_STATE_RESTORING;
            nfa_ee_cb.num_ee_expecting  = 0;
            if (nfa_sys_is_register (NFA_ID_HCI))
            {
                nfa_ee_cb.ee_flags   |= NFA_EE_FLAG_WAIT_HCI;
                nfa_ee_cb.ee_flags   |= NFA_EE_FLAG_NOTIFY_HCI;
            }
            NFC_NfceeDiscover (TRUE);
            nfa_sys_start_timer (&nfa_ee_cb.discv_timer, NFA_EE_DISCV_TIMEOUT_EVT, NFA_EE_DISCV_TIMEOUT_VAL);
        }
    }
    else
    {
        nfa_sys_stop_timer (&nfa_ee_cb.timer);
        nfa_sys_stop_timer (&nfa_ee_cb.discv_timer);
        nfa_ee_cb.num_ee_expecting = 0;
    }

    if (proc_complete)
        nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_EE);
}
示例#8
0
/*******************************************************************************
**
** Function         nfa_sys_ptim_stop_timer
**
** Description      Stop a protocol timer.
**
** Returns          void
**
*******************************************************************************/
void nfa_sys_ptim_stop_timer (tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle)
{
    NFA_TRACE_DEBUG1 ("nfa_sys_ptim_stop_timer %08x", p_tle);

    GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle);

    /* if timer list is empty stop periodic GKI timer */
    if (p_cb->timer_queue.p_first == NULL)
    {
        NFA_TRACE_DEBUG0 ("ptim timer stop");
        GKI_stop_timer (p_cb->timer_id);
    }
}
示例#9
0
/*******************************************************************************
**
** Function         NFA_EeGetInfo
**
** Description      This function retrieves the NFCEE information from NFA.
**                  The actual number of NFCEE is returned in p_num_nfcee
**                  and NFCEE information is returned in p_info
**
** Returns          NFA_STATUS_OK if information is retrieved successfully
**                  NFA_STATUS_FAILED If wrong state (retry later)
**                  NFA_STATUS_INVALID_PARAM If bad parameter
**
*******************************************************************************/
tNFA_STATUS NFA_EeGetInfo(UINT8        *p_num_nfcee,
                          tNFA_EE_INFO *p_info)
{
    int   xx, ret = nfa_ee_cb.cur_ee;
    tNFA_EE_ECB  *p_cb = nfa_ee_cb.ecb;
    UINT8   max_ret;
    UINT8   num_ret  = 0;

    NFA_TRACE_DEBUG2 ("NFA_EeGetInfo em_state:%d cur_ee:%d", nfa_ee_cb.em_state, nfa_ee_cb.cur_ee);
    /* validate parameters */
    if (p_info == NULL || p_num_nfcee == NULL)
    {
        NFA_TRACE_ERROR0 ("NFA_EeGetInfo bad parameter");
        return (NFA_STATUS_INVALID_PARAM);
    }
    max_ret         = *p_num_nfcee;
    *p_num_nfcee = 0;
    if (nfa_ee_cb.em_state == NFA_EE_EM_STATE_INIT)
    {
        NFA_TRACE_ERROR1 ("NFA_EeGetInfo bad em state: %d", nfa_ee_cb.em_state);
        return (NFA_STATUS_FAILED);
    }

    /* compose output */
    for (xx = 0; (xx < ret) && (num_ret < max_ret); xx++, p_cb++)
    {
        NFA_TRACE_DEBUG4 ("xx:%d max_ret:%d, num_ret:%d ee_status:0x%x", xx, max_ret, num_ret, p_cb->ee_status);
        if ((p_cb->ee_status & NFA_EE_STATUS_INT_MASK) || (p_cb->ee_status == NFA_EE_STATUS_REMOVED))
        {
            continue;
        }
        p_info->ee_handle       = NFA_HANDLE_GROUP_EE | (tNFA_HANDLE)p_cb->nfcee_id;
        p_info->ee_status       = p_cb->ee_status;
        p_info->num_interface   = p_cb->num_interface;
        p_info->num_tlvs        = p_cb->num_tlvs;
        memcpy(p_info->ee_interface, p_cb->ee_interface, p_cb->num_interface);
        memcpy(p_info->ee_tlv, p_cb->ee_tlv, p_cb->num_tlvs * sizeof(tNFA_EE_TLV));
        p_info++;
        num_ret++;
    }
    NFA_TRACE_DEBUG1 ("num_ret:%d", num_ret);
    *p_num_nfcee = num_ret;
    return (NFA_STATUS_OK);
}
/*******************************************************************************
**
** Function         nfa_hciu_get_allocated_gate_list
**
** Description      fills in a list of allocated gates
**
** Returns          the number of gates
**
*******************************************************************************/
UINT8 nfa_hciu_get_allocated_gate_list (UINT8 *p_gate_list)
{
    tNFA_HCI_DYN_GATE   *p_cb;
    int                 xx;
    UINT8               count = 0;

    for (xx = 0, p_cb = nfa_hci_cb.cfg.dyn_gates; xx < NFA_HCI_MAX_GATE_CB; xx++, p_cb++)
    {
        if (p_cb->gate_id != 0)
        {
            *p_gate_list++ = p_cb->gate_id;
            count++;
        }
    }

    NFA_TRACE_DEBUG1 ("nfa_hciu_get_allocated_gate_list () returns: %u", count);

    return (count);
}
示例#11
0
/*******************************************************************************
**
** Function         nfa_sys_ptim_start_timer
**
** Description      Start a protocol timer for the specified amount
**                  of time in seconds.
**
** Returns          void
**
*******************************************************************************/
void nfa_sys_ptim_start_timer (tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout)
{
    NFA_TRACE_DEBUG1 ("nfa_sys_ptim_start_timer %08x", p_tle);

    /* if timer list is currently empty, start periodic GKI timer */
    if (p_cb->timer_queue.p_first == NULL)
    {
        NFA_TRACE_DEBUG0 ("ptim timer start");
        p_cb->last_gki_ticks = GKI_get_tick_count ();
        GKI_start_timer (p_cb->timer_id, GKI_MS_TO_TICKS (p_cb->period), TRUE);
    }

    GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle);

    p_tle->event = type;
    p_tle->ticks = timeout;

    GKI_add_to_timer_list (&p_cb->timer_queue, p_tle);
}
/*******************************************************************************
**
** Function         nfa_hciu_release_pipe
**
** Description      remove the specified pipe
**
** Returns          NFA_HCI_ANY_OK, if removed
**                  NFA_HCI_ANY_E_NOK, if otherwise
**
*******************************************************************************/
tNFA_HCI_RESPONSE nfa_hciu_release_pipe (UINT8 pipe_id)
{
    tNFA_HCI_DYN_GATE   *p_gate;
    tNFA_HCI_DYN_PIPE   *p_pipe;
    UINT8               pipe_index;

    NFA_TRACE_EVENT1 ("nfa_hciu_release_pipe: %u", pipe_id);

    if ((p_pipe = nfa_hciu_find_pipe_by_pid (pipe_id)) == NULL)
        return (NFA_HCI_ANY_E_NOK);

    if (pipe_id > NFA_HCI_LAST_DYNAMIC_PIPE)
    {
        NFA_TRACE_DEBUG1 ("ignore pipe: %d", pipe_id);
        return (NFA_HCI_ANY_E_NOK);
    }

    pipe_index = (UINT8) (p_pipe - nfa_hci_cb.cfg.dyn_pipes);

    if (p_pipe->local_gate == NFA_HCI_IDENTITY_MANAGEMENT_GATE)
    {
        /* Remove pipe from ID management gate */
        nfa_hci_cb.cfg.id_mgmt_gate.pipe_inx_mask &= ~ (UINT32) (1 << pipe_index);
    }
    else
    {
        if ((p_gate = nfa_hciu_find_gate_by_gid (p_pipe->local_gate)) == NULL)
        {
            /* Mark the pipe control block as free */
            p_pipe->pipe_id = 0;
            return (NFA_HCI_ANY_E_NOK);
        }

        /* Remove pipe from gate */
        p_gate->pipe_inx_mask &= ~ (UINT32) (1 << pipe_index);
    }

    /* Reset pipe control block */
    memset (p_pipe,0,sizeof (tNFA_HCI_DYN_PIPE));
    nfa_hci_cb.nv_write_needed = TRUE;
    return NFA_HCI_ANY_OK;
}
/*******************************************************************************
**
** Function         nfa_hciu_find_pipe_by_owner
**
** Description      Find the first pipe associated with the given app
**
** Returns          pointer to pipe, or NULL if none found
**
*******************************************************************************/
tNFA_HCI_DYN_PIPE *nfa_hciu_find_pipe_by_owner (tNFA_HANDLE app_handle)
{
    tNFA_HCI_DYN_GATE   *pg;
    tNFA_HCI_DYN_PIPE   *pp;
    int                 xx;

    NFA_TRACE_DEBUG1 ("nfa_hciu_find_pipe_by_owner () app_handle:0x%x", app_handle);

    /* Loop through all pipes looking for the owner */
    for (xx = 0, pp = nfa_hci_cb.cfg.dyn_pipes; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++)
    {
        if (pp->pipe_id != 0)
        {
            if (  ((pg = nfa_hciu_find_gate_by_gid (pp->local_gate)) != NULL)
                &&(pg->gate_owner == app_handle) )
                return (pp);
        }
    }

    /* If here, not found */
    return (NULL);
}