Ejemplo n.º 1
0
/*******************************************************************************
**
** Function         L2CA_UCDSetTxPriority
**
** Description      Sets the transmission priority for a connectionless channel.
**
** Returns          TRUE if a valid channel, else FALSE
**
*******************************************************************************/
BOOLEAN L2CA_UCDSetTxPriority ( BD_ADDR rem_bda, tL2CAP_CHNL_PRIORITY priority )
{
    tL2C_LCB        *p_lcb;
    tL2C_CCB        *p_ccb;

    L2CAP_TRACE_API ("L2CA_UCDSetTxPriority()  priority: 0x%02x  BDA: %08x%04x", priority,
                     (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                     (rem_bda[4] << 8) + rem_bda[5]);

    if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL) {
        L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_UCDSetTxPriority");
        return (FALSE);
    }

    /* Find the channel control block */
    if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL) {
        L2CAP_TRACE_WARNING ("L2CAP - no CCB for L2CA_UCDSetTxPriority");
        return (FALSE);
    }

    /* it will update the order of CCB in LCB by priority and update round robin service variables */
    l2cu_change_pri_ccb (p_ccb, priority);

    return (TRUE);
}
Ejemplo n.º 2
0
/*******************************************************************************
**
**  Function        L2CA_UcdDiscover
**
**  Description     Discover UCD of remote device.
**
**  Parameters:     PSM
**                  BD_ADDR of remote device
**                  info_type : L2CAP_UCD_INFO_TYPE_RECEPTION
**                              L2CAP_UCD_INFO_TYPE_MTU
**
**
**  Return value:   TRUE if successs
**
*******************************************************************************/
BOOLEAN L2CA_UcdDiscover ( UINT16 psm, BD_ADDR rem_bda, UINT8 info_type )
{
    tL2C_LCB        *p_lcb;
    tL2C_CCB        *p_ccb;
    tL2C_RCB        *p_rcb;

    L2CAP_TRACE_API ("L2CA_UcdDiscover()  PSM: 0x%04x  BDA: %08x%04x, InfoType=0x%02x", psm,
                     (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                     (rem_bda[4] << 8) + rem_bda[5], info_type);

    /* Fail if the PSM is not registered */
    if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
            || ( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED )) {
        L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x", psm);
        return (FALSE);
    }

    /* First, see if we already have a link to the remote */
    /* then find the channel control block for UCD. */
    if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
            || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
        if ( l2c_ucd_connect (rem_bda) == FALSE ) {
            return (FALSE);
        }
    }

    /* set waiting flags in rcb */

    if ( info_type & L2CAP_UCD_INFO_TYPE_RECEPTION ) {
        p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION;
    }

    if ( info_type & L2CAP_UCD_INFO_TYPE_MTU ) {
        p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU;
    }

    /* if link is already established */
    if ((p_lcb) && (p_lcb->link_state == LST_CONNECTED)) {
        if (!p_ccb) {
            p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID);
        }
        l2c_ucd_check_pending_info_req(p_ccb);
    }
    return (TRUE);
}
Ejemplo n.º 3
0
/*******************************************************************************
**
**  Function        L2CA_UcdRegister
**
**  Description     Register PSM on UCD.
**
**  Parameters:     tL2CAP_UCD_CB_INFO
**
**  Return value:   TRUE if successs
**
*******************************************************************************/
BOOLEAN L2CA_UcdRegister ( UINT16 psm, tL2CAP_UCD_CB_INFO *p_cb_info )
{
    tL2C_RCB             *p_rcb;

    L2CAP_TRACE_API  ("L2CA_UcdRegister()  PSM: 0x%04x", psm);

    if ((!p_cb_info->pL2CA_UCD_Discover_Cb)
            || (!p_cb_info->pL2CA_UCD_Data_Cb)) {
        L2CAP_TRACE_ERROR ("L2CAP - no callback registering PSM(0x%04x) on UCD", psm);
        return (FALSE);
    }

    if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) {
        L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm);
        return (FALSE);
    }

    p_rcb->ucd.state   = L2C_UCD_STATE_W4_DATA;
    p_rcb->ucd.cb_info = *p_cb_info;

    /* check if master rcb is created for UCD */
    if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL) {
        if ((p_rcb = l2cu_allocate_rcb (L2C_UCD_RCB_ID)) == NULL) {
            L2CAP_TRACE_ERROR ("L2CAP - no RCB available for L2CA_UcdRegister");
            return (FALSE);
        } else {
            /* these callback functions will forward data to each UCD application */
            p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb            = l2c_ucd_discover_cback;
            p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb                = l2c_ucd_data_ind_cback;
            p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb   = l2c_ucd_congestion_status_cback;

            memset (&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO));
            p_rcb->api.pL2CA_DisconnectInd_Cb        = l2c_ucd_disconnect_ind_cback;

            /* This will make L2CAP check UCD congestion callback */
            p_rcb->api.pL2CA_CongestionStatus_Cb     = NULL;

            /* do nothing but prevent crash */
            p_rcb->api.pL2CA_ConfigInd_Cb            = l2c_ucd_config_ind_cback;
            p_rcb->api.pL2CA_ConfigCfm_Cb            = l2c_ucd_config_cfm_cback;
        }
    }

    return (TRUE);
}
Ejemplo n.º 4
0
/*******************************************************************************
**
**  Function        L2CA_UcdSetIdleTimeout
**
**  Description     Set UCD Idle timeout.
**
**  Parameters:     BD Addr
**                  Timeout in second
**
**  Return value:   TRUE if successs
**
*******************************************************************************/
BOOLEAN L2CA_UcdSetIdleTimeout ( BD_ADDR rem_bda, UINT16 timeout )
{
    tL2C_LCB        *p_lcb;
    tL2C_CCB        *p_ccb;

    L2CAP_TRACE_API ("L2CA_UcdSetIdleTimeout()  Timeout: 0x%04x  BDA: %08x%04x", timeout,
                     (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                     (rem_bda[4] << 8) + rem_bda[5]);

    /* First, see if we already have a link to the remote */
    /* then find the channel control block. */
    if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
            || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
        L2CAP_TRACE_WARNING ("L2CAP - no UCD channel");
        return (FALSE);
    } else {
        p_ccb->fixed_chnl_idle_tout = timeout;
        return (TRUE);
    }
}
Ejemplo n.º 5
0
/*******************************************************************************
**
**  Function        L2CA_UcdDeregister
**
**  Description     Deregister PSM on UCD.
**
**  Parameters:     PSM
**
**  Return value:   TRUE if successs
**
*******************************************************************************/
BOOLEAN L2CA_UcdDeregister ( UINT16 psm )
{
    tL2C_CCB    *p_ccb;
    tL2C_RCB    *p_rcb;
    UINT16      xx;

    L2CAP_TRACE_API  ("L2CA_UcdDeregister()  PSM: 0x%04x", psm);

    if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL) {
        L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x", psm);
        return (FALSE);
    }

    p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;

    /* check this was the last UCD registration */
    p_rcb = &l2cb.rcb_pool[0];

    for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
        if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED)) {
            return (TRUE);
        }
    }

    /* delete master rcb for UCD */
    if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL) {
        l2cu_release_rcb (p_rcb);
    }

    /* delete CCB for UCD */
    p_ccb = l2cb.ccb_pool;
    for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ ) {
        if (( p_ccb->in_use )
                && ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )) {
            l2cu_release_ccb (p_ccb);
        }
        p_ccb++;
    }

    return (TRUE);
}
Ejemplo n.º 6
0
/*******************************************************************************
**
**  Function        L2CA_EnableUpdateBleConnParams
**
**  Description     Enable or disable update based on the request from the peer
**
**  Parameters:     BD Address of remote
**
**  Return value:   TRUE if update started
**
*******************************************************************************/
BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
{
    tL2C_LCB            *p_lcb;

    /* See if we have a link control block for the remote device */
    p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);

    if (!p_lcb)
    {
        L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
            (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
            (rem_bda[4]<<8)+rem_bda[5]);
        return (FALSE);
    }

    L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x",__FUNCTION__,
        (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
        (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->conn_update_mask);

    if (p_lcb->transport != BT_TRANSPORT_LE)
    {
        L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__,
                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
                              (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
        return (FALSE);
    }

    if (enable)
        p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
    else
        p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;

    l2cble_start_conn_update(p_lcb);

    return (TRUE);
}
Ejemplo n.º 7
0
/*******************************************************************************
**
**  Function        L2CA_UcdDataWrite
**
**  Description     Send UCD to remote device
**
**  Parameters:     PSM
**                  BD Address of remote
**                  Pointer to buffer of type BT_HDR
**                  flags : L2CAP_FLUSHABLE_CH_BASED
**                          L2CAP_FLUSHABLE_PKT
**                          L2CAP_NON_FLUSHABLE_PKT
**
** Return value     L2CAP_DW_SUCCESS, if data accepted
**                  L2CAP_DW_FAILED,  if error
**
*******************************************************************************/
UINT16 L2CA_UcdDataWrite (UINT16 psm, BD_ADDR rem_bda, BT_HDR *p_buf, UINT16 flags)
{
    tL2C_LCB        *p_lcb;
    tL2C_CCB        *p_ccb;
    tL2C_RCB        *p_rcb;
    UINT8           *p;

    L2CAP_TRACE_API ("L2CA_UcdDataWrite()  PSM: 0x%04x  BDA: %08x%04x", psm,
                     (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                     (rem_bda[4] << 8) + rem_bda[5]);

    /* Fail if the PSM is not registered */
    if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
            || ( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED )) {
        L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x", psm);
        osi_free (p_buf);
        return (L2CAP_DW_FAILED);
    }

    /* First, see if we already have a link to the remote */
    /*  then find the channel control block for UCD */
    if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
            || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
        if ( l2c_ucd_connect (rem_bda) == FALSE ) {
            osi_free (p_buf);
            return (L2CAP_DW_FAILED);
        }

        /* If we still don't have lcb and ccb after connect attempt, then can't proceed */
        if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
                || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)) {
            osi_free (p_buf);
            return (L2CAP_DW_FAILED);
        }
    }

    /* write PSM */
    p_buf->offset -= L2CAP_UCD_OVERHEAD;
    p_buf->len += L2CAP_UCD_OVERHEAD;
    p = (UINT8 *)(p_buf + 1) + p_buf->offset;

    UINT16_TO_STREAM (p, psm);

    /* UCD MTU check */
    if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu)) {
        L2CAP_TRACE_WARNING ("L2CAP - Handle: 0x%04x  UCD bigger than peer's UCD mtu size cannot be sent", p_lcb->handle);
        osi_free (p_buf);
        return (L2CAP_DW_FAILED);
    }

    /* If already congested, do not accept any more packets */
    if (p_ccb->cong_sent) {
        L2CAP_TRACE_ERROR ("L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: %u  buff_quota: %u",
                           p_lcb->handle,
                           (fixed_queue_length(p_ccb->xmit_hold_q) +
                            fixed_queue_length(p_lcb->ucd_out_sec_pending_q)),
                           p_ccb->buff_quota);

        osi_free (p_buf);
        return (L2CAP_DW_FAILED);
    }

    /* channel based, packet based flushable or non-flushable */
    p_buf->layer_specific = flags;

    l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf);

    if (p_ccb->cong_sent) {
        return (L2CAP_DW_CONGESTED);
    } else {
        return (L2CAP_DW_SUCCESS);
    }
}