Ejemplo n.º 1
0
static void hci_host_thread_handler(void *arg)
{
    /*
     * Previous task handles RX queue and two TX Queues, Since there is
     * a RX Thread Task in H4 layer which receives packet from driver layer.
     * Now HCI Host Task has been optimized to only process TX Queue
     * including command and data queue. And command queue has high priority,
     * All packets will be directly copied to single queue in driver layer with
     * H4 type header added (1 byte).
     */

    BtTaskEvt_t e;

    for (;;) {
        if (pdTRUE == xQueueReceive(xHciHostQueue, &e, (portTickType)portMAX_DELAY)) {

            if (e.sig == 0xff) {
                if (esp_vhci_host_check_send_available()) {
                    /*Now Target only allowed one packet per TX*/
                    BT_HDR *pkt = packet_fragmenter->fragment_current_packet();
                    if (pkt != NULL) {
                        packet_fragmenter->fragment_and_dispatch(pkt);
                    } else {
                        if (!fixed_queue_is_empty(hci_host_env.command_queue) &&
                                hci_host_env.command_credits > 0) {
                            fixed_queue_process(hci_host_env.command_queue);
                        } else if (!fixed_queue_is_empty(hci_host_env.packet_queue)) {
                            fixed_queue_process(hci_host_env.packet_queue);
                        }
                    }
                }
            }
        }
    }
}
Ejemplo n.º 2
0
/*******************************************************************************
**
** Function         avdt_ccb_snd_msg
**
** Description
**
**
** Returns          void.
**
*******************************************************************************/
void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data)
{
    BT_HDR      *p_msg;
    UNUSED(p_data);

    /* if not congested */
    if (!p_ccb->cong) {
        /* are we sending a fragmented message? continue sending fragment */
        if (p_ccb->p_curr_msg != NULL) {
            avdt_msg_send(p_ccb, NULL);
        }
        /* do we have responses to send?  send them */
        else if (!fixed_queue_is_empty(p_ccb->rsp_q)) {
            while ((p_msg = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL) {
                if (avdt_msg_send(p_ccb, p_msg) == TRUE) {
                    /* break out if congested */
                    break;
                }
            }
        }

        /* do we have commands to send?  send next command */
        avdt_ccb_snd_cmd(p_ccb, NULL);
    }
}
Ejemplo n.º 3
0
/*******************************************************************************
 **
 ** Function         btc_a2dp_sink_rx_flush_req
 **
 ** Description
 **
 ** Returns          TRUE is success
 **
 *******************************************************************************/
BOOLEAN btc_a2dp_sink_rx_flush_req(void)
{
    if (fixed_queue_is_empty(btc_aa_snk_cb.RxSbcQ) == TRUE) { /*  Que is already empty */
        return TRUE;
    }

    btc_a2dp_sink_ctrl_post(BTC_MEDIA_FLUSH_AA_RX, NULL);
    return TRUE;
}
Ejemplo n.º 4
0
/*******************************************************************************
**
**  Function        l2c_ucd_delete_sec_pending_q
**
** Description      discard all of UCD packets in security pending queue
**
** Returns          None
**
*******************************************************************************/
void l2c_ucd_delete_sec_pending_q(tL2C_LCB  *p_lcb)
{
    /* clean up any security pending UCD */
    while (p_lcb->ucd_out_sec_pending_q.p_first) {
        osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q));
	}
    fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL);
    p_lcb->ucd_out_sec_pending_q = NULL;

    while (! fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q)) {
        osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q));
	}
    fixed_queue_free(p_lcb->ucd_in_sec_pending_q);
    p_lcb->ucd_in_sec_pending_q = NULL;
}
Ejemplo n.º 5
0
static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
{
    tBT_SBC_HDR *p_msg;

    if (fixed_queue_is_empty(btc_aa_snk_cb.RxSbcQ)) {
        APPL_TRACE_DEBUG("  QUE  EMPTY ");
    } else {
        if (btc_aa_snk_cb.rx_flush == TRUE) {
            btc_a2dp_sink_flush_q(btc_aa_snk_cb.RxSbcQ);
            return;
        }

        while ((p_msg = (tBT_SBC_HDR *)fixed_queue_try_peek_first(btc_aa_snk_cb.RxSbcQ)) != NULL ) {
            btc_a2dp_sink_handle_inc_media(p_msg);
            p_msg = (tBT_SBC_HDR *)fixed_queue_try_dequeue(btc_aa_snk_cb.RxSbcQ);
            if ( p_msg == NULL ) {
                APPL_TRACE_ERROR("Insufficient data in que ");
                break;
            }
            osi_free(p_msg);
        }
        APPL_TRACE_DEBUG(" Process Frames - ");
    }
}
Ejemplo n.º 6
0
// Returns true if the event was intercepted and should not proceed to
// higher layers. Also inspects an incoming event for interesting
// information, like how many commands are now able to be sent.
static bool filter_incoming_event(BT_HDR *packet)
{
    waiting_command_t *wait_entry = NULL;
    uint8_t *stream = packet->data + packet->offset;
    uint8_t event_code;
    command_opcode_t opcode;

    STREAM_TO_UINT8(event_code, stream);
    STREAM_SKIP_UINT8(stream); // Skip the parameter total length field

    LOG_DEBUG("Receive packet event_code=0x%x\n", event_code);

    if (event_code == HCI_COMMAND_COMPLETE_EVT) {
        STREAM_TO_UINT8(hci_host_env.command_credits, stream);
        STREAM_TO_UINT16(opcode, stream);

        wait_entry = get_waiting_command(opcode);
        if (!wait_entry) {
            LOG_WARN("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode);
        } else if (wait_entry->complete_callback) {
            wait_entry->complete_callback(packet, wait_entry->context);
        } else if (wait_entry->complete_future) {
            future_ready(wait_entry->complete_future, packet);
        }

        goto intercepted;
    } else if (event_code == HCI_COMMAND_STATUS_EVT) {
        uint8_t status;
        STREAM_TO_UINT8(status, stream);
        STREAM_TO_UINT8(hci_host_env.command_credits, stream);
        STREAM_TO_UINT16(opcode, stream);

        // If a command generates a command status event, it won't be getting a command complete event

        wait_entry = get_waiting_command(opcode);
        if (!wait_entry) {
            LOG_WARN("%s command status event with no matching command. opcode: 0x%x", __func__, opcode);
        } else if (wait_entry->status_callback) {
            wait_entry->status_callback(status, wait_entry->command, wait_entry->context);
        }

        goto intercepted;
    }

    return false;
intercepted:
    restart_comamnd_waiting_response_timer(&hci_host_env.cmd_waiting_q, false);

    /*Tell HCI Host Task to continue TX Pending commands*/
    if (hci_host_env.command_credits &&
            !fixed_queue_is_empty(hci_host_env.command_queue)) {
        hci_host_task_post();
    }
    //ke_event_set(KE_EVENT_HCI_HOST_THREAD);

    if (wait_entry) {
        // If it has a callback, it's responsible for freeing the packet
        if (event_code == HCI_COMMAND_STATUS_EVT ||
                (!wait_entry->complete_callback && !wait_entry->complete_future)) {
            buffer_allocator->free(packet);
        }

        // If it has a callback, it's responsible for freeing the command
        if (event_code == HCI_COMMAND_COMPLETE_EVT || !wait_entry->status_callback) {
            buffer_allocator->free(wait_entry->command);
        }

        osi_free(wait_entry);
    } else {
        buffer_allocator->free(packet);
    }

    return true;
}
Ejemplo n.º 7
0
/*******************************************************************************
**
** Function         rfc_port_sm_opened
**
** Description      This function handles events for the port in the OPENED
**                  state
**
** Returns          void
**
*******************************************************************************/
void rfc_port_sm_opened (tPORT *p_port, UINT16 event, void *p_data)
{
    switch (event) {
    case RFC_EVENT_OPEN:
        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:
        /* Send credits in the frame.  Pass them in the layer specific member of the hdr. */
        /* There might be an initial case when we reduced rx_max and credit_rx is still */
        /* bigger.  Make sure that we do not send 255 */
        if ((p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
                && (((BT_HDR *)p_data)->len < p_port->peer_mtu)
                && (!p_port->rx.user_fc)
                && (p_port->credit_rx_max > p_port->credit_rx)) {
            ((BT_HDR *)p_data)->layer_specific = (UINT8) (p_port->credit_rx_max - p_port->credit_rx);
            p_port->credit_rx = p_port->credit_rx_max;
        } else {
            ((BT_HDR *)p_data)->layer_specific = 0;
        }
        rfc_send_buf_uih (p_port->rfc.p_mcb, p_port->dlci, (BT_HDR *)p_data);
        rfc_dec_credit (p_port);
        return;

    case RFC_EVENT_UA:
        return;

    case RFC_EVENT_SABME:
        rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
        return;

    case RFC_EVENT_DM:
        PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci);
        rfc_port_closed (p_port);
        return;

    case RFC_EVENT_DISC:
        p_port->rfc.state = RFC_STATE_CLOSED;
        rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
        if (! fixed_queue_is_empty(p_port->rx.queue)) {
            /* give a chance to upper stack to close port properly */
            RFCOMM_TRACE_DEBUG("port queue is not empty");
            rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT);
        } else {
            PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci);
        }
        return;

    case RFC_EVENT_UIH:
        rfc_port_uplink_data (p_port, (BT_HDR *)p_data);
        return;

    case RFC_EVENT_TIMEOUT:
        Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ;
        RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
        return;
    }
    RFCOMM_TRACE_WARNING ("Port state opened Event ignored %d", event);
}
Ejemplo n.º 8
0
/*******************************************************************************
 **
 ** Function         btc_a2dp_sink_flush_q
 **
 ** Description
 **
 ** Returns          void
 **
 *******************************************************************************/
static void btc_a2dp_sink_flush_q(fixed_queue_t *p_q)
{
    while (! fixed_queue_is_empty(p_q)) {
        osi_free(fixed_queue_try_dequeue(p_q));
    }
}