Exemple #1
0
/*******************************************************************************
**
** Function         port_rfc_closed
**
** Description      This function when RFCOMM side of port is closed
**
*******************************************************************************/
void port_rfc_closed (tPORT *p_port, UINT8 res)
{
    UINT8     old_signals;
    UINT32    events = 0;
    tRFC_MCB *p_mcb = p_port->rfc.p_mcb;

    if ((p_port->state == PORT_STATE_OPENING) && (p_port->is_server)) {
        /* The servr side has not been informed that connection is up, ignore */
        RFCOMM_TRACE_EVENT ("port_rfc_closed in OPENING state ignored");

        rfc_port_timer_stop (p_port);
        p_port->rfc.state = RFC_STATE_CLOSED;

        if (p_mcb) {
            p_mcb->port_inx[p_port->dlci] = 0;

            /* If there are no more ports opened on this MCB release it */
            rfc_check_mcb_active (p_mcb);
            p_port->rfc.p_mcb = NULL;
        }

        /* Need to restore DLCI to listening state
         * if the server was on the initiating RFC
         */
        p_port->dlci &= 0xfe;

        return;
    }

    if ((p_port->state != PORT_STATE_CLOSING) && (p_port->state != PORT_STATE_CLOSED)) {
        p_port->line_status |= LINE_STATUS_FAILED;

        old_signals = p_port->peer_ctrl.modem_signal;

        p_port->peer_ctrl.modem_signal &= ~(PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);

        events |= port_get_signal_changes (p_port, old_signals, p_port->peer_ctrl.modem_signal);

        if (p_port->ev_mask & PORT_EV_CONNECT_ERR) {
            events |= PORT_EV_CONNECT_ERR;
        }
    }
    RFCOMM_TRACE_EVENT ("port_rfc_closed state:%d sending events:%x", p_port->state, events);

    if ((p_port->p_callback != NULL) && events) {
        p_port->p_callback (events, p_port->inx);
    }

    if (p_port->p_mgmt_callback) {
        p_port->p_mgmt_callback (res, p_port->inx);
    }

    p_port->rfc.state = RFC_STATE_CLOSED;

    RFCOMM_TRACE_WARNING ("%s RFCOMM connection in state %d closed: %s (res: %d)",
                          __func__, p_port->state, PORT_GetResultString(res), res);

    port_release_port (p_port);
}
Exemple #2
0
/*******************************************************************************
**
** Function         PORT_StartCnf
**
** Description      This function is called from the RFCOMM layer when
**                  establishing of the multiplexer channel is completed.
**                  Continue establishing of the connection for all ports that
**                  are in the OPENING state
**
*******************************************************************************/
void PORT_StartCnf (tRFC_MCB *p_mcb, UINT16 result)
{
    tPORT   *p_port;
    int     i;
    BOOLEAN no_ports_up = TRUE;

    RFCOMM_TRACE_EVENT ("PORT_StartCnf result:%d", result);

    p_port = &rfc_cb.port.port[0];
    for (i = 0; i < MAX_RFC_PORTS; i++, p_port++)
    {
        if (p_port->rfc.p_mcb == p_mcb)
        {
            no_ports_up = FALSE;

            if (result == RFCOMM_SUCCESS)
                RFCOMM_ParNegReq (p_mcb, p_port->dlci, p_port->mtu);
            else
            {
                RFCOMM_TRACE_WARNING ("PORT_StartCnf failed result:%d", result);

                /* Warning: result is also set to 4 when l2cap connection
                   fails due to l2cap connect cnf (no_resources) */
                if( result == HCI_ERR_PAGE_TIMEOUT )
                    p_port->error = PORT_PAGE_TIMEOUT;
                else
                    p_port->error = PORT_START_FAILED;

                rfc_release_multiplexer_channel (p_mcb);
                p_port->rfc.p_mcb = NULL;

                /* Send event to the application */
                if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECT_ERR))
                    (p_port->p_callback)(PORT_EV_CONNECT_ERR, p_port->inx);

                if (p_port->p_mgmt_callback)
                    p_port->p_mgmt_callback (PORT_START_FAILED, p_port->inx);

                port_release_port (p_port);
            }
        }
    }

    /* There can be a situation when after starting connection, user closes the */
    /* port, we can catch it here to close multiplexor channel */
    if (no_ports_up)
    {
        rfc_check_mcb_active (p_mcb);
    }
}
Exemple #3
0
/*******************************************************************************
**
** Function         rfc_port_closed
**
** Description      The function is called when port is released based on the
**                  event received from the lower layer, typically L2CAP
**                  connection down, DISC, or DM frame.
**
** Returns          void
**
*******************************************************************************/
void rfc_port_closed (tPORT *p_port)
{
    tRFC_MCB *p_mcb = p_port->rfc.p_mcb;

    RFCOMM_TRACE_DEBUG ("rfc_port_closed");

    rfc_port_timer_stop (p_port);

    p_port->rfc.state = RFC_STATE_CLOSED;

    /* If multiplexer channel was up mark it as down */
    if (p_mcb) {
        p_mcb->port_inx[p_port->dlci] = 0;

        /* If there are no more ports opened on this MCB release it */
        rfc_check_mcb_active (p_mcb);
    }

    /* Notify port that RFC connection is gone */
    port_rfc_closed (p_port, PORT_CLOSED);
}
Exemple #4
0
/*******************************************************************************
**
** Function         PORT_ParNegInd
**
** Description      This function is called from the RFCOMM layer to change
**                  DLCI parameters (currently only MTU is negotiated).
**                  If can not find the port do not accept the request.
**                  Otherwise save the MTU size supported by the peer.
**
*******************************************************************************/
void PORT_ParNegInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k)
{
    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
    UINT8 our_cl;
    UINT8 our_k;

    RFCOMM_TRACE_EVENT ("PORT_ParNegInd dlci:%d mtu:%d", dlci, mtu);

    if (!p_port) {
        /* This can be a first request for this port */
        p_port = port_find_dlci_port (dlci);
        if (!p_port) {
            /* If the port cannot be opened, send a DM.  Per Errata 1205 */
            rfc_send_dm(p_mcb, dlci, FALSE);
            /* check if this is the last port open, some headsets have
            problem, they don't disconnect if we send DM */
            rfc_check_mcb_active( p_mcb );
            RFCOMM_TRACE_EVENT( "PORT_ParNegInd: port not found" );
            return;
        }
        p_mcb->port_inx[dlci] = p_port->inx;
    }

    memcpy (p_port->bd_addr, p_mcb->bd_addr, BD_ADDR_LEN);

    /* Connection is up and we know local and remote features, select MTU */
    port_select_mtu (p_port);

    p_port->rfc.p_mcb   = p_mcb;
    p_port->mtu         = (p_port->mtu < mtu) ? p_port->mtu : mtu;
    p_port->peer_mtu    = p_port->mtu;

    /* Negotiate the flow control mechanism.  If flow control mechanism for */
    /* mux has not been set yet, set it now.  If either we or peer wants TS 07.10, */
    /* use that.  Otherwise both must want credit based, so use that. If flow is */
    /* already defined for this mux, we respond with that value. */
    if (p_mcb->flow == PORT_FC_UNDEFINED) {
        if ((PORT_FC_DEFAULT == PORT_FC_TS710) || (cl == RFCOMM_PN_CONV_LAYER_TYPE_1)) {
            p_mcb->flow = PORT_FC_TS710;
        } else {
            p_mcb->flow = PORT_FC_CREDIT;
        }
    }

    /* Regardless of our flow control mechanism, if the PN cl is zero, we must */
    /* respond with zero.  "A responding implementation must set this field to 14 */
    /* if (and only if) the PN request was 15."  This could happen if a PN is sent */
    /* after the DLCI is already established-- the PN in that case must have cl = 0. */
    /* See RFCOMM spec 5.5.3 */
    if (cl == RFCOMM_PN_CONV_LAYER_TYPE_1) {
        our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
        our_k = 0;
    } else if (p_mcb->flow == PORT_FC_CREDIT) {
        /* get credits */
        port_get_credits (p_port, k);

        /* Set convergence layer and number of credits (k) */
        our_cl = RFCOMM_PN_CONV_LAYER_CBFC_R;
        our_k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX;
        p_port->credit_rx = our_k;
    } else {
        /* must not be using credit based flow control; use TS 7.10 */
        our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
        our_k = 0;
    }
    RFCOMM_ParNegRsp (p_mcb, dlci, p_port->mtu, our_cl, our_k);
}
Exemple #5
0
/*******************************************************************************
**
** Function         port_release_port
**
** Description      Release port infor control block.
**
** Returns          Pointer to the PORT or NULL if not found
**
*******************************************************************************/
void port_release_port (tPORT *p_port)
{
    BT_HDR *p_buf;
    UINT32 mask;
    tPORT_CALLBACK *p_port_cb;
    tPORT_STATE user_port_pars;

    PORT_SCHEDULE_LOCK;
    RFCOMM_TRACE_DEBUG("port_release_port, p_port:%p", p_port);
    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue)) != NULL)
        GKI_freebuf (p_buf);

    p_port->rx.queue_size = 0;

    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->tx.queue)) != NULL)
        GKI_freebuf (p_buf);

    p_port->tx.queue_size = 0;

    PORT_SCHEDULE_UNLOCK;

    p_port->state = PORT_STATE_CLOSED;

    if (p_port->rfc.state == RFC_STATE_CLOSED)
    {
        RFCOMM_TRACE_DEBUG ("rfc_port_closed DONE");
        if (p_port->rfc.p_mcb)
        {
            p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;

            /* If there are no more ports opened on this MCB release it */
            rfc_check_mcb_active (p_port->rfc.p_mcb);
        }
        rfc_port_timer_stop (p_port);
        RFCOMM_TRACE_DEBUG ("port_release_port:p_port->keep_port_handle:%d", p_port->keep_port_handle);
        if( p_port->keep_port_handle )
        {
            RFCOMM_TRACE_DEBUG ("port_release_port:Initialize handle:%d", p_port->inx);
            /* save event mask and callback */
            mask = p_port->ev_mask;
            p_port_cb = p_port->p_callback;
            user_port_pars = p_port->user_port_pars;

            port_set_defaults(p_port);
            /* restore */
            p_port->ev_mask         = mask;
            p_port->p_callback      = p_port_cb;
            p_port->user_port_pars  = user_port_pars;
            p_port->mtu             = p_port->keep_mtu;

            p_port->state           = PORT_STATE_OPENING;
            p_port->rfc.p_mcb       = NULL;
            if(p_port->is_server)
                p_port->dlci       &= 0xfe;

            p_port->local_ctrl.modem_signal = p_port->default_signal_state;
            memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN);
        }
        else
        {
            RFCOMM_TRACE_DEBUG ("port_release_port:Clean-up handle:%d", p_port->inx);
            memset (p_port, 0, sizeof (tPORT));
        }
    }
}