Exemple #1
0
static void transmit_command(
    BT_HDR *command,
    command_complete_cb complete_callback,
    command_status_cb status_callback,
    void *context)
{
    uint8_t *stream;
    waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
    if (!wait_entry) {
        LOG_ERROR("%s couldn't allocate space for wait entry.", __func__);
        return;
    }

    stream = command->data + command->offset;
    STREAM_TO_UINT16(wait_entry->opcode, stream);
    wait_entry->complete_callback = complete_callback;
    wait_entry->status_callback = status_callback;
    wait_entry->command = command;
    wait_entry->context = context;

    // Store the command message type in the event field
    // in case the upper layer didn't already
    command->event = MSG_STACK_TO_HC_HCI_CMD;
    LOG_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", wait_entry->opcode);
    BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);

    fixed_queue_enqueue(hci_host_env.command_queue, wait_entry);
    hci_host_task_post();
}
static void inbound_data_waiting(void *context) {
  eager_reader_t *reader = (eager_reader_t *)context;

  data_buffer_t *buffer = (data_buffer_t *)reader->allocator->alloc(reader->buffer_size + sizeof(data_buffer_t));
  if (!buffer) {
    LOG_ERROR(LOG_TAG, "%s couldn't aquire memory for inbound data buffer.", __func__);
    return;
  }

  buffer->length = 0;
  buffer->offset = 0;

  int bytes_read = read(reader->inbound_fd, buffer->data, reader->buffer_size);
  if (bytes_read > 0) {
    // Save the data for later
    buffer->length = bytes_read;
    fixed_queue_enqueue(reader->buffers, buffer);

    // Tell consumers data is available by incrementing
    // the semaphore by the number of bytes we just read
    eventfd_write(reader->bytes_available_fd, bytes_read);
  } else {
    if (bytes_read == 0)
      LOG_WARN(LOG_TAG, "%s fd said bytes existed, but none were found.", __func__);
    else
      LOG_WARN(LOG_TAG, "%s unable to read from file descriptor: %s", __func__, strerror(errno));

    reader->allocator->free(buffer);
  }
}
Exemple #3
0
int if_output(cbuf *b, ifnet *i)
{
    bool release_sem = false;
    bool enqueue_failed = false;
//printf("if out");

    // stick the buffer on a transmit queue
    mutex_lock(&i->tx_queue_lock);
    if(fixed_queue_enqueue(&i->tx_queue, b) < 0)
        enqueue_failed = true;
    if(i->tx_queue.count == 1)
        release_sem = true;
    mutex_unlock(&i->tx_queue_lock);

    if(enqueue_failed) {
        cbuf_free_chain(b);
        return ERR_NO_MEMORY;
    }

    if(release_sem)
        sem_release(i->tx_queue_sem);

//printf("if %x out ok\n", i);
    return NO_ERROR;
}
Exemple #4
0
/*******************************************************************************
 **
 ** Function         btc_a2dp_sink_enque_buf
 **
 ** Description      This function is called by the av_co to fill A2DP Sink Queue
 **
 **
 ** Returns          size of the queue
 *******************************************************************************/
UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt)
{
    tBT_SBC_HDR *p_msg;

    if (btc_aa_snk_cb.rx_flush == TRUE) { /* Flush enabled, do not enque*/
        return fixed_queue_length(btc_aa_snk_cb.RxSbcQ);
    }

    if (fixed_queue_length(btc_aa_snk_cb.RxSbcQ) >= MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ) {
        APPL_TRACE_WARNING("Pkt dropped\n");
        return fixed_queue_length(btc_aa_snk_cb.RxSbcQ);
    }

    APPL_TRACE_DEBUG("btc_a2dp_sink_enque_buf + ");

    /* allocate and Queue this buffer */
    if ((p_msg = (tBT_SBC_HDR *) osi_malloc(sizeof(tBT_SBC_HDR) +
                                            p_pkt->offset + p_pkt->len)) != NULL) {
        memcpy(p_msg, p_pkt, (sizeof(BT_HDR) + p_pkt->offset + p_pkt->len));
        p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
        APPL_TRACE_VERBOSE("btc_a2dp_sink_enque_buf %d + \n", p_msg->num_frames_to_be_processed);
        fixed_queue_enqueue(btc_aa_snk_cb.RxSbcQ, p_msg);
        btc_a2dp_sink_data_post(BTC_A2DP_SINK_DATA_EVT);
    } else {
        /* let caller deal with a failed allocation */
        APPL_TRACE_WARNING("btc_a2dp_sink_enque_buf No Buffer left - ");
    }
    return fixed_queue_length(btc_aa_snk_cb.RxSbcQ);
}
Exemple #5
0
void btu_oneshot_alarm_cb(void *data) {
  assert(data != NULL);
  TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;

  btu_stop_timer_oneshot(p_tle);

  fixed_queue_enqueue(btu_oneshot_alarm_queue, p_tle);
}
Exemple #6
0
static void transmit_downward(data_dispatcher_type_t type, void *data) {
  if (type == MSG_STACK_TO_HC_HCI_CMD) {
    // TODO(zachoverflow): eliminate this call
    transmit_command((BT_HDR *)data, NULL, NULL, NULL);
    LOG_WARN(LOG_TAG, "%s legacy transmit of command. Use transmit_command instead.", __func__);
  } else {
    fixed_queue_enqueue(packet_queue, data);
  }
}
Exemple #7
0
static void transmit_downward(uint16_t type, void *data)
{
    if (type == MSG_STACK_TO_HC_HCI_CMD) {
        transmit_command((BT_HDR *)data, NULL, NULL, NULL);
        LOG_WARN("%s legacy transmit of command. Use transmit_command instead.\n", __func__);
    } else {
        fixed_queue_enqueue(hci_host_env.packet_queue, data);
    }
    //ke_event_set(KE_EVENT_HCI_HOST_THREAD);
    hci_host_task_post();
}
Exemple #8
0
static void transmit_downward(uint16_t type, void *data)
{
    if (type == MSG_STACK_TO_HC_HCI_CMD) {
        transmit_command((BT_HDR *)data, NULL, NULL, NULL);
        HCI_TRACE_WARNING("%s legacy transmit of command. Use transmit_command instead.\n", __func__);
    } else {
        fixed_queue_enqueue(hci_host_env.packet_queue, data);
    }

    hci_host_task_post(TASK_POST_BLOCKING);
}
Exemple #9
0
// Callback for the fragmenter to dispatch up a completely reassembled packet
static void dispatch_reassembled(BT_HDR *packet) {
  // Events should already have been dispatched before this point
  assert((packet->event & MSG_EVT_MASK) != MSG_HC_TO_STACK_HCI_EVT);
  assert(upwards_data_queue != NULL);

  if (upwards_data_queue) {
    fixed_queue_enqueue(upwards_data_queue, packet);
  } else {
    LOG_ERROR(LOG_TAG, "%s had no queue to place upwards data packet in. Dropping it on the floor.", __func__);
    buffer_allocator->free(packet);
  }
}
Exemple #10
0
// Callback for the fragmenter to dispatch up a completely reassembled packet
static void dispatch_reassembled(BT_HDR *packet)
{
    // Events should already have been dispatched before this point

    if (hci_host_env.upwards_data_queue) {
        fixed_queue_enqueue(hci_host_env.upwards_data_queue, packet);
        btu_task_post(SIG_BTU_WORK);
        //Tell Up-layer received packet.
    } else {
        LOG_DEBUG("%s had no queue to place upwards data packet in. Dropping it on the floor.", __func__);
        buffer_allocator->free(packet);
    }
}
bool data_dispatcher_dispatch(data_dispatcher_t *dispatcher, data_dispatcher_type_t type, void *data) {
  assert(dispatcher != NULL);
  assert(data != NULL);

  fixed_queue_t *queue = hash_map_get(dispatcher->dispatch_table, (void *)type);
  if (!queue)
    queue = dispatcher->default_queue;

  if (queue)
    fixed_queue_enqueue(queue, data);
  else
    LOG_WARN(LOG_TAG, "%s has no handler for type (%zd) in data dispatcher named: %s", __func__, type, dispatcher->name);

  return queue != NULL;
}
Exemple #12
0
static future_t *transmit_command_futured(BT_HDR *command) {
  waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
  assert(wait_entry != NULL);

  future_t *future = future_new();

  uint8_t *stream = command->data + command->offset;
  STREAM_TO_UINT16(wait_entry->opcode, stream);
  wait_entry->complete_future = future;
  wait_entry->command = command;

  // Store the command message type in the event field
  // in case the upper layer didn't already
  command->event = MSG_STACK_TO_HC_HCI_CMD;

  fixed_queue_enqueue(command_queue, wait_entry);
  return future;
}
bool thread_post(thread_t *thread, thread_fn func, void *context) {
  assert(thread != NULL);
  assert(func != NULL);

  // TODO(sharvil): if the current thread == |thread| and we've run out
  // of queue space, we should abort this operation, otherwise we'll
  // deadlock.

  // Queue item is freed either when the queue itself is destroyed
  // or when the item is removed from the queue for dispatch.
  work_item_t *item = (work_item_t *)osi_malloc(sizeof(work_item_t));
  if (!item) {
    LOG_ERROR("%s unable to allocate memory: %s", __func__, strerror(errno));
    return false;
  }
  item->func = func;
  item->context = context;
  fixed_queue_enqueue(thread->work_queue, item);
  return true;
}
Exemple #14
0
static void transmit_command(
    BT_HDR *command,
    command_complete_cb complete_callback,
    command_status_cb status_callback,
    void *context) {
  waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
  if (!wait_entry) {
    LOG_ERROR(LOG_TAG, "%s couldn't allocate space for wait entry.", __func__);
    return;
  }

  uint8_t *stream = command->data + command->offset;
  STREAM_TO_UINT16(wait_entry->opcode, stream);
  wait_entry->complete_callback = complete_callback;
  wait_entry->status_callback = status_callback;
  wait_entry->command = command;
  wait_entry->context = context;

  // Store the command message type in the event field
  // in case the upper layer didn't already
  command->event = MSG_STACK_TO_HC_HCI_CMD;

  fixed_queue_enqueue(command_queue, wait_entry);
}
Exemple #15
0
/*******************************************************************************
**
** Function         rfc_check_send_cmd
**
** Description      This function is called to send an RFCOMM command message
**                  or to handle the RFCOMM command message queue.
**
** Returns          void
**
*******************************************************************************/
void rfc_check_send_cmd(tRFC_MCB *p_mcb, BT_HDR *p_buf)
{
    BT_HDR  *p;

    /* if passed a buffer queue it */
    if (p_buf != NULL) {
        if (p_mcb->cmd_q == NULL) {
            RFCOMM_TRACE_ERROR("%s: empty queue: p_mcb = %p p_mcb->lcid = %u cached p_mcb = %p",
                               __func__, p_mcb, p_mcb->lcid,
                               rfc_find_lcid_mcb(p_mcb->lcid));
        }
        fixed_queue_enqueue(p_mcb->cmd_q, p_buf);
    }

    /* handle queue if L2CAP not congested */
    while (p_mcb->l2cap_congested == FALSE) {
        if ((p = (BT_HDR *)fixed_queue_try_dequeue(p_mcb->cmd_q)) == NULL) {
            break;
        }


        L2CA_DataWrite (p_mcb->lcid, p);
    }
}
Exemple #16
0
static void btu_l2cap_alarm_cb(void *data) {
  assert(data != NULL);
  TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *)data;

  fixed_queue_enqueue(btu_l2cap_alarm_queue, p_tle);
}
Exemple #17
0
/*******************************************************************************
**
**  Function        l2c_ucd_enqueue_pending_out_sec_q
**
**  Description     enqueue outgoing UCD packet into security pending queue
**                  and check congestion
**
**  Return          None
**
*******************************************************************************/
void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB  *p_ccb, void *p_data)
{
    fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data);
    l2cu_check_channel_congestion (p_ccb);
}
Exemple #18
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);
    }
}