Example #1
0
/*******************************************************************************
**
** Function         rfc_process_pn
**
** Description      This function handles DLC parameter negotiation frame.
**                  Record MTU and pass indication to the upper layer.
**
*******************************************************************************/
void rfc_process_pn (tRFC_MCB *p_mcb, BOOLEAN is_command, MX_FRAME *p_frame)
{
    tPORT *p_port;
    UINT8 dlci = p_frame->dlci;

    if (is_command) {
        /* Ignore if Multiplexer is being shut down */
        if (p_mcb->state != RFC_MX_STATE_DISC_WAIT_UA) {
            PORT_ParNegInd (p_mcb, dlci, p_frame->u.pn.mtu,
                            p_frame->u.pn.conv_layer, p_frame->u.pn.k);
        } else {
            rfc_send_dm(p_mcb, dlci, FALSE);
            RFCOMM_TRACE_WARNING("***** MX PN while disconnecting *****");
        }

        return;
    }
    /* If we are not awaiting response just ignore it */
    p_port = port_find_mcb_dlci_port (p_mcb, dlci);
    if ((p_port == NULL) || !(p_port->rfc.expected_rsp & RFC_RSP_PN)) {
        return;
    }

    p_port->rfc.expected_rsp &= ~RFC_RSP_PN;

    rfc_port_timer_stop (p_port);

    PORT_ParNegCnf (p_mcb, dlci, p_frame->u.pn.mtu,
                    p_frame->u.pn.conv_layer, p_frame->u.pn.k);
}
Example #2
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);
}
Example #3
0
/*******************************************************************************
**
** Function         rfc_port_sm_sabme_wait_ua
**
** Description      This function handles events when SABME on the DLC was
**                  sent and SM is waiting for UA or DM.
**
** Returns          void
**
*******************************************************************************/
void rfc_port_sm_sabme_wait_ua (tPORT *p_port, UINT16 event, void *p_data)
{
    switch (event)
    {
    case RFC_EVENT_OPEN:
    case RFC_EVENT_ESTABLISH_RSP:
        RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
        return;

    case RFC_EVENT_CLOSE:
        rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT);
        rfc_send_disc (p_port->rfc.p_mcb, p_port->dlci);
        p_port->rfc.expected_rsp = 0;
        p_port->rfc.state = RFC_STATE_DISC_WAIT_UA;
        return;

    case RFC_EVENT_CLEAR:
        rfc_port_closed (p_port);
        return;

    case RFC_EVENT_DATA:
        GKI_freebuf (p_data);
        break;

    case RFC_EVENT_UA:
        rfc_port_timer_stop (p_port);
        p_port->rfc.state = RFC_STATE_OPENED;
        PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_SUCCESS);
        return;

    case RFC_EVENT_DM:
        p_port->rfc.p_mcb->is_disc_initiator = TRUE;
        PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
        rfc_port_closed (p_port);
        return;

    case RFC_EVENT_DISC:
        rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
        PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
        rfc_port_closed (p_port);
        return;

    case RFC_EVENT_SABME:
        /* Continue to wait for the UA the SABME this side sent */
        rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
        return;

    case RFC_EVENT_UIH:
        GKI_freebuf (p_data);
        return;

    case RFC_EVENT_TIMEOUT:
        p_port->rfc.state = RFC_STATE_CLOSED;
        PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
        return;
    }
    RFCOMM_TRACE_WARNING ("Port state sabme_wait_ua Event ignored %d", event);
}
Example #4
0
/*******************************************************************************
**
** Function         rfc_process_rls
**
** Description      This function handles Remote Line Status command.
**                  Pass command to the user.
**
*******************************************************************************/
void rfc_process_rls (tRFC_MCB *p_mcb, BOOLEAN is_command, MX_FRAME *p_frame)
{
    tPORT *p_port;

    if (is_command) {
        PORT_LineStatusInd (p_mcb, p_frame->dlci, p_frame->u.rls.line_status);
        rfc_send_rls (p_mcb, p_frame->dlci, FALSE, p_frame->u.rls.line_status);
    } else {
        p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci);

        /* If we are not awaiting response just ignore it */
        if (!p_port || !(p_port->rfc.expected_rsp & RFC_RSP_RLS)) {
            return;
        }

        p_port->rfc.expected_rsp &= ~RFC_RSP_RLS;

        rfc_port_timer_stop (p_port);
    }
}
Example #5
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);
}
Example #6
0
/*******************************************************************************
**
** Function         rfc_process_msc
**
** Description      This function handles Modem Status Command.
**                  Pass command to the user.
**
*******************************************************************************/
void rfc_process_msc (tRFC_MCB *p_mcb, BOOLEAN is_command, MX_FRAME *p_frame)
{
    tPORT_CTRL pars;
    tPORT      *p_port;
    UINT8      modem_signals = p_frame->u.msc.signals;
    BOOLEAN    new_peer_fc = FALSE;

    p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci);
    if (p_port == NULL) {
        return;
    }

    pars.modem_signal = 0;

    if (modem_signals & RFCOMM_MSC_RTC) {
        pars.modem_signal |= MODEM_SIGNAL_DTRDSR;
    }

    if (modem_signals & RFCOMM_MSC_RTR) {
        pars.modem_signal |= MODEM_SIGNAL_RTSCTS;
    }

    if (modem_signals & RFCOMM_MSC_IC) {
        pars.modem_signal |= MODEM_SIGNAL_RI;
    }

    if (modem_signals & RFCOMM_MSC_DV) {
        pars.modem_signal |= MODEM_SIGNAL_DCD;
    }

    pars.fc = ((modem_signals & RFCOMM_MSC_FC) == RFCOMM_MSC_FC);

    pars.break_signal     = (p_frame->u.msc.break_present) ?
                            p_frame->u.msc.break_duration : 0;
    pars.discard_buffers  = 0;
    pars.break_signal_seq = RFCOMM_CTRL_BREAK_IN_SEQ;   /* this is default */

    /* Check if this command is passed only to indicate flow control */
    if (is_command) {
        rfc_send_msc (p_mcb, p_frame->dlci, FALSE, &pars);

        if (p_port->rfc.p_mcb->flow != PORT_FC_CREDIT) {
            /* Spec 1.1 indicates that only FC bit is used for flow control */
            p_port->peer_ctrl.fc = new_peer_fc = pars.fc;

            if (new_peer_fc != p_port->tx.peer_fc) {
                PORT_FlowInd (p_mcb, p_frame->dlci, (BOOLEAN)!new_peer_fc);
            }
        }

        PORT_ControlInd (p_mcb, p_frame->dlci, &pars);

        return;
    }

    /* If we are not awaiting response just ignore it */
    if (!(p_port->rfc.expected_rsp & RFC_RSP_MSC)) {
        return;
    }

    p_port->rfc.expected_rsp &= ~RFC_RSP_MSC;

    rfc_port_timer_stop (p_port);

    PORT_ControlCnf (p_port->rfc.p_mcb, p_port->dlci, &pars);
}
Example #7
0
/*******************************************************************************
**
** Function         rfc_process_rpn
**
** Description      This function handles Remote DLC parameter negotiation
**                  command/response.  Pass command to the user.
**
*******************************************************************************/
void rfc_process_rpn (tRFC_MCB *p_mcb, BOOLEAN is_command,
                      BOOLEAN is_request, MX_FRAME *p_frame)
{
    tPORT_STATE port_pars;
    tPORT       *p_port;

    if ((p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci)) == NULL) {
        /* This is the first command on the port */
        if (is_command) {

            memset(&port_pars, 0, sizeof(tPORT_STATE));
            rfc_set_port_state(&port_pars, p_frame);

            PORT_PortNegInd(p_mcb, p_frame->dlci, &port_pars, p_frame->u.rpn.param_mask);
        }
        return;
    }

    if (is_command && is_request) {
        /* This is the special situation when peer just request local pars */
        port_pars = p_port->peer_port_pars;
        rfc_send_rpn (p_mcb, p_frame->dlci, FALSE, &p_port->peer_port_pars, 0);
        return;
    }

    port_pars = p_port->peer_port_pars;

    rfc_set_port_state(&port_pars, p_frame);

    if (is_command) {
        PORT_PortNegInd (p_mcb, p_frame->dlci, &port_pars, p_frame->u.rpn.param_mask);
        return;
    }

    /* If we are not awaiting response just ignore it */
    p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci);
    if ((p_port == NULL) || !(p_port->rfc.expected_rsp & (RFC_RSP_RPN | RFC_RSP_RPN_REPLY))) {
        return;
    }

    /* If we sent a request for port parameters to the peer he is replying with */
    /* mask 0. */
    rfc_port_timer_stop (p_port);

    if (p_port->rfc.expected_rsp & RFC_RSP_RPN_REPLY) {
        p_port->rfc.expected_rsp &= ~RFC_RSP_RPN_REPLY;

        p_port->peer_port_pars = port_pars;

        if ((port_pars.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT))
                || (port_pars.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT))) {
            /* This is satisfactory port parameters.  Set mask as it was Ok */
            p_frame->u.rpn.param_mask = RFCOMM_RPN_PM_MASK;
        } else {
            /* Current peer parameters are not good, try to fix them */
            p_port->peer_port_pars.fc_type = (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT);

            p_port->rfc.expected_rsp |= RFC_RSP_RPN;
            rfc_send_rpn (p_mcb, p_frame->dlci, TRUE, &p_port->peer_port_pars,
                          RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT);
            rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
            return;
        }
    } else {
        p_port->rfc.expected_rsp &= ~RFC_RSP_RPN;
    }

    /* Check if all suggested parameters were accepted */
    if (((p_frame->u.rpn.param_mask & (RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT)) ==
            (RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT))
            || ((p_frame->u.rpn.param_mask & (RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT)) ==
                (RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT))) {
        PORT_PortNegCnf (p_mcb, p_port->dlci, &port_pars, RFCOMM_SUCCESS);
        return;
    }

    /* If we were proposing RTR flow control try RTC flow control */
    /* If we were proposing RTC flow control try no flow control */
    /* otherwise drop the connection */
    if (p_port->peer_port_pars.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT)) {
        /* Current peer parameters are not good, try to fix them */
        p_port->peer_port_pars.fc_type = (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT);

        p_port->rfc.expected_rsp |= RFC_RSP_RPN;

        rfc_send_rpn (p_mcb, p_frame->dlci, TRUE, &p_port->peer_port_pars,
                      RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT);
        rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
        return;
    }

    /* Other side does not support flow control */
    if (p_port->peer_port_pars.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT)) {
        p_port->peer_port_pars.fc_type = RFCOMM_FC_OFF;
        PORT_PortNegCnf (p_mcb, p_port->dlci, &port_pars, RFCOMM_SUCCESS);
    }
}
Example #8
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));
        }
    }
}