Esempio n. 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) {
        HCI_TRACE_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;
    HCI_TRACE_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(TASK_POST_BLOCKING);

}
Esempio n. 2
0
/*
 * Starts a oneshot timer with a timeout in seconds.
 */
void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec)
{
    osi_alarm_t *alarm = NULL;

    assert(p_tle != NULL);

    // Get the alarm for the timer list entry.
    osi_mutex_lock(&btu_oneshot_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
    if (!hash_map_has_key(btu_oneshot_alarm_hash_map, p_tle)) {
        alarm = osi_alarm_new("btu_oneshot", btu_oneshot_alarm_cb, (void *)p_tle, 0);
        hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm);
    }
    osi_mutex_unlock(&btu_oneshot_alarm_lock);

    alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle);
    if (alarm == NULL) {
        HCI_TRACE_ERROR("%s Unable to create alarm", __func__);
        return;
    }
    osi_alarm_cancel(alarm);

    p_tle->event = type;
    p_tle->in_use = TRUE;
    // NOTE: This value is in seconds but stored in a ticks field.
    p_tle->ticks = timeout_sec;
    osi_alarm_set(alarm, (period_ms_t)(timeout_sec * 1000));
}
Esempio n. 3
0
void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ticks)
{
    osi_alarm_t *alarm = NULL;

    assert(p_tle != NULL);

    // Get the alarm for the timer list entry.
    osi_mutex_lock(&btu_l2cap_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
    if (!hash_map_has_key(btu_l2cap_alarm_hash_map, p_tle)) {
        alarm = osi_alarm_new("btu_l2cap", btu_l2cap_alarm_cb, (void *)p_tle, 0);
        hash_map_set(btu_l2cap_alarm_hash_map, p_tle, (void *)alarm);
    }
    osi_mutex_unlock(&btu_l2cap_alarm_lock);

    alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle);
    if (alarm == NULL) {
        HCI_TRACE_ERROR("%s Unable to create alarm", __func__);
        return;
    }
    osi_alarm_cancel(alarm);

    p_tle->event = type;
    p_tle->ticks = timeout_ticks;
    p_tle->in_use = TRUE;
    // The quick timer ticks are 100ms long.
    osi_alarm_set(alarm, (period_ms_t)(timeout_ticks * 100));
}
Esempio n. 4
0
static void command_timed_out(void *context)
{
    command_waiting_response_t *cmd_wait_q = (command_waiting_response_t *)context;
    waiting_command_t *wait_entry;

    osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT);
    wait_entry = (list_is_empty(cmd_wait_q->commands_pending_response) ?
                  NULL : list_front(cmd_wait_q->commands_pending_response));
    osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);

    if (wait_entry == NULL) {
        HCI_TRACE_ERROR("%s with no commands pending response", __func__);
    } else
        // We shouldn't try to recover the stack from this command timeout.
        // If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
    {
        HCI_TRACE_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode);
    }
}
Esempio n. 5
0
static int hci_layer_init_env(void)
{
    command_waiting_response_t *cmd_wait_q;

    // The host is only allowed to send at most one command initially,
    // as per the Bluetooth spec, Volume 2, Part E, 4.4 (Command Flow Control)
    // This value can change when you get a command complete or command status event.
    hci_host_env.command_credits = 1;
    hci_host_env.command_queue = fixed_queue_new(QUEUE_SIZE_MAX);
    if (hci_host_env.command_queue) {
        fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready);
    } else {
        HCI_TRACE_ERROR("%s unable to create pending command queue.", __func__);
        return -1;
    }

    hci_host_env.packet_queue = fixed_queue_new(QUEUE_SIZE_MAX);
    if (hci_host_env.packet_queue) {
        fixed_queue_register_dequeue(hci_host_env.packet_queue, event_packet_ready);
    } else {
        HCI_TRACE_ERROR("%s unable to create pending packet queue.", __func__);
        return -1;
    }

    // Init Commands waiting response list and timer
    cmd_wait_q = &hci_host_env.cmd_waiting_q;
    cmd_wait_q->timer_is_set = false;
    cmd_wait_q->commands_pending_response = list_new(NULL);
    if (!cmd_wait_q->commands_pending_response) {
        HCI_TRACE_ERROR("%s unable to create list for commands pending response.", __func__);
        return -1;
    }
    osi_mutex_new(&cmd_wait_q->commands_pending_response_lock);
    cmd_wait_q->command_response_timer = osi_alarm_new("cmd_rsp_to", command_timed_out, cmd_wait_q, COMMAND_PENDING_TIMEOUT);
    if (!cmd_wait_q->command_response_timer) {
        HCI_TRACE_ERROR("%s unable to create command response timer.", __func__);
        return -1;
    }

    return 0;
}
Esempio n. 6
0
// TODO(zachoverflow): we seem to do this a couple places, like the HCI inject module. #centralize
static serial_data_type_t event_to_data_type(uint16_t event)
{
    if (event == MSG_STACK_TO_HC_HCI_ACL) {
        return DATA_TYPE_ACL;
    } else if (event == MSG_STACK_TO_HC_HCI_SCO) {
        return DATA_TYPE_SCO;
    } else if (event == MSG_STACK_TO_HC_HCI_CMD) {
        return DATA_TYPE_COMMAND;
    } else {
        HCI_TRACE_ERROR("%s invalid event type, could not translate 0x%x\n", __func__, event);
    }

    return 0;
}
Esempio n. 7
0
task_post_status_t btu_task_post(uint32_t sig, void *param, task_post_t timeout)
{
    BtTaskEvt_t evt;

    evt.sig = sig;
    evt.par = param;

    if (xQueueSend(xBtuQueue, &evt, timeout) != pdTRUE) {
        HCI_TRACE_ERROR("xBtuQueue failed\n");
        return TASK_POST_FAIL;
    }

    return TASK_POST_SUCCESS;
}
Esempio n. 8
0
task_post_status_t hci_host_task_post(task_post_t timeout)
{
    BtTaskEvt_t evt;

    if (hci_host_startup_flag == false) {
        return TASK_POST_FAIL;
    }

    evt.sig = SIG_HCI_HOST_SEND_AVAILABLE;
    evt.par = 0;

    if (xQueueSend(xHciHostQueue, &evt, timeout) != pdTRUE) {
        HCI_TRACE_ERROR("xHciHostQueue failed\n");
        return TASK_POST_FAIL;
    }

    return TASK_POST_SUCCESS;
}