Beispiel #1
0
/*******************************************************************************
**
** Function         port_rfc_send_tx_data
**
** Description      This function is when forward data can be sent to the peer
**
*******************************************************************************/
UINT32 port_rfc_send_tx_data (tPORT *p_port)
{
    UINT32 events = 0;
    BT_HDR *p_buf;

    /* if there is data to be sent */
    if (p_port->tx.queue_size > 0) {
        /* while the rfcomm peer is not flow controlling us, and peer is ready */
        while (!p_port->tx.peer_fc && p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready) {
            /* get data from tx queue and send it */
            osi_mutex_global_lock();

            if ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL) {
                p_port->tx.queue_size -= p_buf->len;

                osi_mutex_global_unlock();

                RFCOMM_TRACE_DEBUG ("Sending RFCOMM_DataReq tx.queue_size=%d", p_port->tx.queue_size);

                RFCOMM_DataReq (p_port->rfc.p_mcb, p_port->dlci, p_buf);

                events |= PORT_EV_TXCHAR;

                if (p_port->tx.queue_size == 0) {
                    events |= PORT_EV_TXEMPTY;
                    break;
                }
            }
            /* queue is empty-- all data sent */
            else {
                osi_mutex_global_unlock();

                events |= PORT_EV_TXEMPTY;
                break;
            }
        }
        /* If we flow controlled user based on the queue size enable data again */
        events |= port_flow_control_user (p_port);
    }
    return (events & p_port->ev_mask);
}
Beispiel #2
0
/*******************************************************************************
**
** Function         PORT_DataInd
**
** Description      This function is called from the RFCOMM layer when data
**                  buffer is received from the peer.
**
*******************************************************************************/
void PORT_DataInd (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
{
    tPORT  *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
    UINT8  rx_char1;
    UINT32 events = 0;
    UINT8  *p;
    int    i;

    RFCOMM_TRACE_EVENT("PORT_DataInd with data length %d, p_mcb:%p,p_port:%p,dlci:%d",
                       p_buf->len, p_mcb, p_port, dlci);
    if (!p_port) {
        osi_free (p_buf);
        return;
    }
    /* If client registered callout callback with flow control we can just deliver receive data */
    if (p_port->p_data_co_callback) {
        /* Another packet is delivered to user.  Send credits to peer if required */

        if (p_port->p_data_co_callback(p_port->inx, (UINT8 *)p_buf, -1, DATA_CO_CALLBACK_TYPE_INCOMING)) {
            port_flow_control_peer(p_port, TRUE, 1);
        } else {
            port_flow_control_peer(p_port, FALSE, 0);
        }
        //osi_free (p_buf);
        return;
    } else {
        RFCOMM_TRACE_DEBUG("PORT_DataInd, p_port:%p, p_data_co_callback is null", p_port);
    }
    /* If client registered callback we can just deliver receive data */
    if (p_port->p_data_callback) {
        /* Another packet is delivered to user.  Send credits to peer if required */
        port_flow_control_peer(p_port, TRUE, 1);

        p_port->p_data_callback (p_port->inx, (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
        osi_free (p_buf);
        return;
    }

    /* Check if rx queue exceeds the limit */
    if ((p_port->rx.queue_size + p_buf->len > PORT_RX_CRITICAL_WM)
     || (fixed_queue_length(p_port->rx.queue) + 1 > p_port->rx_buf_critical)) {
        RFCOMM_TRACE_EVENT ("PORT_DataInd. Buffer over run. Dropping the buffer");
        osi_free (p_buf);

        RFCOMM_LineStatusReq (p_mcb, dlci, LINE_STATUS_OVERRUN);
        return;
    }

    /* If user registered to receive notification when a particular byte is */
    /* received we mast check all received bytes */
    if (((rx_char1 = p_port->user_port_pars.rx_char1) != 0)
            && (p_port->ev_mask & PORT_EV_RXFLAG)) {
        for (i = 0, p = (UINT8 *)(p_buf + 1) + p_buf->offset; i < p_buf->len; i++) {
            if (*p++ == rx_char1) {
                events |= PORT_EV_RXFLAG;
                break;
            }
        }
    }

    osi_mutex_global_lock();

    fixed_queue_enqueue(p_port->rx.queue, p_buf);
    p_port->rx.queue_size += p_buf->len;

    osi_mutex_global_unlock();

    /* perform flow control procedures if necessary */
    port_flow_control_peer(p_port, FALSE, 0);

    /* If user indicated flow control can not deliver any notifications to him */
    if (p_port->rx.user_fc) {
        if (events & PORT_EV_RXFLAG) {
            p_port->rx_flag_ev_pending = TRUE;
        }

        return;
    }

    events |= PORT_EV_RXCHAR;

    /* Mask out all events that are not of interest to user */
    events &= p_port->ev_mask;

    if (p_port->p_callback && events) {
        p_port->p_callback (events, p_port->inx);
    }
}
Beispiel #3
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;

    osi_mutex_global_lock();
    RFCOMM_TRACE_DEBUG("port_release_port, p_port:%p", p_port);
    while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->rx.queue)) != NULL) {
        osi_free (p_buf);
    }

    p_port->rx.queue_size = 0;

    while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL) {
        osi_free (p_buf);
    }

    p_port->tx.queue_size = 0;

    osi_mutex_global_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);
        fixed_queue_free(p_port->tx.queue, NULL);
        p_port->tx.queue = NULL;
        fixed_queue_free(p_port->rx.queue, NULL);
        p_port->rx.queue = NULL;
		
        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));
        }
    }
}